blob: 37cc30445c6e969b4ba8aff80baec53b7c4a7f04 [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
Rubin Xu12384742019-04-24 03:05:12 -070019import static android.content.pm.PackageManager.GET_PERMISSIONS;
20import static android.content.pm.PackageManager.MATCH_ANY_USER;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -070021import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
Erik Klinef851d6d2015-04-20 16:03:48 +090022import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090023import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070024import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
25import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
26import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090027import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070028import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090029import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
30import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090031import static android.net.ConnectivityManager.TYPE_NONE;
Chalard Jeanf9861102019-05-10 04:33:43 -070032import static android.net.ConnectivityManager.TYPE_VPN;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070033import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8d573212019-05-23 22:57:18 -070034import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
35import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
36import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
37import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
38import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
39import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060040import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
45import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090052import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060053import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080054import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060055import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
59import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
60import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
61import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
62import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090063import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060064import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
65import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080066import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
67import static android.net.NetworkPolicyManager.RULE_NONE;
68import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
69import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Rubin Xu9a3f7242019-04-11 11:45:43 -070070import static android.net.RouteInfo.RTN_UNREACHABLE;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060071
72import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090073import static com.android.internal.util.TestUtils.waitForIdleLooper;
junyulai7c469172019-01-16 20:23:34 +080074import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090075
Rubin Xu9a3f7242019-04-11 11:45:43 -070076import static org.junit.Assert.assertArrayEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090077import static org.junit.Assert.assertEquals;
78import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080079import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090080import static org.junit.Assert.assertNotNull;
81import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060082import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090083import static org.junit.Assert.fail;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -070084import static org.mockito.ArgumentMatchers.anyString;
Rubin Xu9a3f7242019-04-11 11:45:43 -070085import static org.mockito.ArgumentMatchers.eq;
Erik Klinee89953b2018-01-11 16:11:10 +090086import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090087import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060088import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090089import static org.mockito.Mockito.doAnswer;
90import static org.mockito.Mockito.doNothing;
Rubin Xu9a3f7242019-04-11 11:45:43 -070091import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080092import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060093import static org.mockito.Mockito.never;
94import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090095import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090096import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090097import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060098import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070099import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900100import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700101
junyulai7c469172019-01-16 20:23:34 +0800102import android.annotation.NonNull;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900103import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400104import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400105import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900106import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900107import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700108import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400109import android.content.Intent;
110import android.content.IntentFilter;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700111import android.content.pm.ApplicationInfo;
112import android.content.pm.PackageInfo;
Rubin Xu12384742019-04-24 03:05:12 -0700113import android.content.pm.PackageManager;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700114import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900115import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400116import android.net.ConnectivityManager;
117import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900118import android.net.ConnectivityManager.PacketKeepalive;
119import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900120import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900121import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800122import android.net.IDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800123import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900124import android.net.INetworkMonitor;
125import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800126import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700127import android.net.INetworkPolicyManager;
128import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800129import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900130import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800131import android.net.IpSecManager;
132import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900133import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700134import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700135import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400136import android.net.Network;
137import android.net.NetworkAgent;
138import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700139import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700140import android.net.NetworkInfo;
141import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400142import android.net.NetworkMisc;
143import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700144import android.net.NetworkSpecifier;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700145import android.net.NetworkStack;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900146import android.net.NetworkStackClient;
Varun Anand02c50ef2019-02-07 14:13:13 -0800147import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100148import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000149import android.net.ProxyInfo;
Wayne Ma28417f42019-04-17 08:03:59 -0700150import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700151import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800152import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900153import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900154import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900155import android.net.shared.NetworkMonitorUtils;
156import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900157import android.net.util.MultinetworkPolicyTracker;
Rubin Xu12384742019-04-24 03:05:12 -0700158import android.os.Binder;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700159import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400160import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700161import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700162import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700163import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900164import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900165import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700166import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800167import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700168import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000169import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800170import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900171import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900172import android.os.UserHandle;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700173import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900174import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800175import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900176import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800177import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100178import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700179import android.util.Log;
Etan Cohenae574a82019-01-08 12:09:18 -0800180import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700181
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800182import androidx.test.InstrumentationRegistry;
183import androidx.test.filters.SmallTest;
184import androidx.test.runner.AndroidJUnit4;
185
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900186import com.android.internal.net.VpnConfig;
Varun Anand02c50ef2019-02-07 14:13:13 -0800187import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900188import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900189import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900190import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900191import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900192import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900193import com.android.server.connectivity.DefaultNetworkMetrics;
194import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900195import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800196import com.android.server.connectivity.Nat464Xlat;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700197import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000198import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800199import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900200import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900201import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900202import com.android.server.net.NetworkPolicyManagerInternal;
Benedict Wongc9511e72019-06-12 17:46:31 +0000203import com.android.server.net.NetworkStatsFactory;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400204
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900205import org.junit.After;
206import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900207import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900208import org.junit.Test;
209import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900210import org.mockito.ArgumentCaptor;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700211import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900212import org.mockito.Mock;
213import org.mockito.MockitoAnnotations;
214import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900215import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900216
junyulai0c666972019-03-04 22:45:36 +0800217import java.io.IOException;
218import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800219import java.net.Inet4Address;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700220import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700221import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900222import java.net.InetSocketAddress;
223import java.net.Socket;
junyulai4a192e22018-06-13 15:00:37 +0800224import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400225import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900226import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100227import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800228import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500229import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100230import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900231import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100232import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900233import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800234import java.util.concurrent.Executor;
junyulaie4135282019-01-03 18:50:15 +0800235import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800236import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900237import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900238import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700239import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900240import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700241
242/**
243 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400244 *
245 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900246 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700247 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900248@RunWith(AndroidJUnit4.class)
249@SmallTest
250public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700251 private static final String TAG = "ConnectivityServiceTest";
252
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900253 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900254 private static final int TEST_LINGER_DELAY_MS = 250;
255 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
256 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
257 // timeout. For this, our assertions should run fast enough to leave less than
258 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
259 // supposedly fired, and the time we call expectCallback.
260 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900261 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
262 // complete before callbacks are verified.
263 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900264
junyulai4a192e22018-06-13 15:00:37 +0800265 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700266 private static final String MOBILE_IFNAME = "test_rmnet_data0";
267 private static final String WIFI_IFNAME = "test_wlan0";
Luke Huang65914772019-03-16 00:31:46 +0800268 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700269
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900270 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400271 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900272 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400273 private MockNetworkAgent mWiFiNetworkAgent;
274 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900275 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900276 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900277 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800278 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700279
Hugo Benichi64901e52017-10-19 14:42:40 +0900280 @Mock IpConnectivityMetrics.Logger mMetricsService;
281 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900282 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600283 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800284 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800285 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800286 @Mock INetd mMockNetd;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900287 @Mock NetworkStackClient mNetworkStack;
Rubin Xu12384742019-04-24 03:05:12 -0700288 @Mock PackageManager mPackageManager;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700289 @Mock UserManager mUserManager;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700290 @Mock NotificationManager mNotificationManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900291
Wayne Ma28417f42019-04-17 08:03:59 -0700292 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
293 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900294
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900295 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
296 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
297 // reflect the state of our test ConnectivityService.
298 private class WrappedConnectivityManager extends ConnectivityManager {
299 private Network mFakeBoundNetwork;
300
301 public synchronized boolean bindProcessToNetwork(Network network) {
302 mFakeBoundNetwork = network;
303 return true;
304 }
305
306 public synchronized Network getBoundNetworkForProcess() {
307 return mFakeBoundNetwork;
308 }
309
310 public WrappedConnectivityManager(Context context, ConnectivityService service) {
311 super(context, service);
312 }
313 }
314
Paul Jensend7b6ca92015-05-13 14:05:12 -0400315 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900316 private final MockContentResolver mContentResolver;
317
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900318 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900319 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900320
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900321 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400322 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900323
324 mResources = spy(base.getResources());
325 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
326 thenReturn(new String[] {
327 "wifi,1,1,1,-1,true",
328 "mobile,0,0,0,-1,true",
329 "mobile_mms,2,0,2,60000,true",
330 });
331
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900332 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900333 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400334 }
335
336 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900337 public void startActivityAsUser(Intent intent, UserHandle handle) {
338 mStartedActivities.offer(intent);
339 }
340
341 public Intent expectStartActivityIntent(int timeoutMs) {
342 Intent intent = null;
343 try {
344 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
345 } catch (InterruptedException e) {}
346 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
347 return intent;
348 }
349
350 public void expectNoStartActivityIntent(int timeoutMs) {
351 try {
352 assertNull("Received unexpected Intent to start activity",
353 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
354 } catch (InterruptedException e) {}
355 }
356
357 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900358 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900359 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700360 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900361 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700362 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400363 return super.getSystemService(name);
364 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900365
366 @Override
367 public ContentResolver getContentResolver() {
368 return mContentResolver;
369 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900370
371 @Override
372 public Resources getResources() {
373 return mResources;
374 }
Rubin Xu12384742019-04-24 03:05:12 -0700375
376 @Override
377 public PackageManager getPackageManager() {
378 return mPackageManager;
379 }
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700380
381 @Override
382 public void enforceCallingOrSelfPermission(String permission, String message) {
383 // The mainline permission can only be held if signed with the network stack certificate
384 // Skip testing for this permission.
385 if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
386 // All other permissions should be held by the test or unnecessary: check as normal to
387 // make sure the code does not rely on unexpected permissions.
388 super.enforceCallingOrSelfPermission(permission, message);
389 }
390 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400391
Hugo Benichi669f0232017-06-29 22:58:39 +0900392 public void waitForIdle(int timeoutMsAsInt) {
393 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900394 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
395 waitForIdle(mCellNetworkAgent, timeoutMs);
396 waitForIdle(mWiFiNetworkAgent, timeoutMs);
397 waitForIdle(mEthernetNetworkAgent, timeoutMs);
398 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900399 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900400 }
401
Hugo Benichi669f0232017-06-29 22:58:39 +0900402 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900403 if (agent == null) {
404 return;
405 }
406 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
407 }
408
409 private void waitForIdle() {
410 waitForIdle(TIMEOUT_MS);
411 }
412
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900413 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900414 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900415 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
416
417 // Tests that waitForIdle returns immediately if the service is already idle.
418 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900419 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900420 }
421
422 // Bring up a network that we can use to send messages to ConnectivityService.
423 ConditionVariable cv = waitForConnectivityBroadcasts(1);
424 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
425 mWiFiNetworkAgent.connect(false);
426 waitFor(cv);
427 Network n = mWiFiNetworkAgent.getNetwork();
428 assertNotNull(n);
429
430 // Tests that calling waitForIdle waits for messages to be processed.
431 for (int i = 0; i < attempts; i++) {
432 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900433 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900434 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
435 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900436 }
437
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900438 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
439 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800440 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900441 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900442 // Bring up a network that we can use to send messages to ConnectivityService.
443 ConditionVariable cv = waitForConnectivityBroadcasts(1);
444 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
445 mWiFiNetworkAgent.connect(false);
446 waitFor(cv);
447 Network n = mWiFiNetworkAgent.getNetwork();
448 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900449
450 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900451 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900452 for (int i = 0; i < attempts; i++) {
453 mWiFiNetworkAgent.setSignalStrength(i);
454 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
455 // We hit a race condition, as expected. Pass the test.
456 return;
457 }
458 }
459
460 // No race? There is a bug in this test.
461 fail("expected race condition at least once in " + attempts + " attempts");
462 }
463
Paul Jensend7b6ca92015-05-13 14:05:12 -0400464 private class MockNetworkAgent {
Chiachang Wang8d573212019-05-23 22:57:18 -0700465 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
466 | NETWORK_VALIDATION_PROBE_HTTP
467 | NETWORK_VALIDATION_PROBE_HTTPS;
468 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
469 | NETWORK_VALIDATION_RESULT_VALID;
470 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
471 | NETWORK_VALIDATION_PROBE_FALLBACK
472 | NETWORK_VALIDATION_RESULT_PARTIAL;
473 private static final int VALIDATION_RESULT_INVALID = 0;
474
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900475 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400476 private final NetworkInfo mNetworkInfo;
477 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900478 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400479 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400480 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700481 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400482 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400483 private NetworkAgent mNetworkAgent;
junyulai0c666972019-03-04 22:45:36 +0800484 private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
junyulai48eac1d42018-12-27 17:25:29 +0800485 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900486 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400487 // Contains the redirectUrl from networkStatus(). Before reading, wait for
488 // mNetworkStatusReceived.
489 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400490
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900491 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8d573212019-05-23 22:57:18 -0700492 private int mNmValidationResult = VALIDATION_RESULT_BASE;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900493 private String mNmValidationRedirectUrl = null;
494 private boolean mNmProvNotificationRequested = false;
495
496 void setNetworkValid() {
Chiachang Wang8d573212019-05-23 22:57:18 -0700497 mNmValidationResult = VALIDATION_RESULT_VALID;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900498 mNmValidationRedirectUrl = null;
499 }
500
501 void setNetworkInvalid() {
Chiachang Wang8d573212019-05-23 22:57:18 -0700502 mNmValidationResult = VALIDATION_RESULT_INVALID;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900503 mNmValidationRedirectUrl = null;
504 }
505
506 void setNetworkPortal(String redirectUrl) {
507 setNetworkInvalid();
508 mNmValidationRedirectUrl = redirectUrl;
509 }
510
lucasline252a742019-03-12 13:08:03 +0800511 void setNetworkPartial() {
Chiachang Wang8d573212019-05-23 22:57:18 -0700512 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
513 mNmValidationRedirectUrl = null;
514 }
515
516 void setNetworkPartialValid() {
517 mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
lucasline252a742019-03-12 13:08:03 +0800518 mNmValidationRedirectUrl = null;
519 }
520
Paul Jensend7b6ca92015-05-13 14:05:12 -0400521 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100522 this(transport, new LinkProperties());
523 }
524
525 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400526 final int type = transportToLegacyType(transport);
Chalard Jeanf9861102019-05-10 04:33:43 -0700527 final String typeName = ConnectivityManager.getNetworkTypeName(type);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400528 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
529 mNetworkCapabilities = new NetworkCapabilities();
530 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400531 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900532 case TRANSPORT_ETHERNET:
533 mScore = 70;
534 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400535 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400536 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400537 break;
538 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400539 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400540 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900541 case TRANSPORT_WIFI_AWARE:
542 mScore = 20;
543 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900544 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900545 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900546 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900547 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400548 default:
549 throw new UnsupportedOperationException("unimplemented network type");
550 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900551 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900552 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900553
554 mNetworkMonitor = mock(INetworkMonitor.class);
555 final Answer validateAnswer = inv -> {
556 new Thread(this::onValidationRequested).start();
557 return null;
558 };
559
560 try {
Remi NGUYEN VAN3962f672019-03-27 15:42:53 +0900561 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900562 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
563 } catch (RemoteException e) {
564 fail(e.getMessage());
565 }
566
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900567 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900568 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
569 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
570 doNothing().when(mNetworkStack).makeNetworkMonitor(
571 nmNetworkCaptor.capture(),
572 any() /* name */,
573 nmCbCaptor.capture());
574
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900575 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
576 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Chalard Jean08577fc2018-05-02 21:14:54 +0900577 linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900578 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900579 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900580
581 @Override
junyulaie4135282019-01-03 18:50:15 +0800582 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900583 int slot = msg.arg1;
584 if (mExpectedKeepaliveSlot != null) {
585 assertEquals((int) mExpectedKeepaliveSlot, slot);
586 }
junyulaie4135282019-01-03 18:50:15 +0800587 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900588 }
589
590 @Override
junyulaie4135282019-01-03 18:50:15 +0800591 public void stopSocketKeepalive(Message msg) {
592 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900593 }
Paul Jensen232437312016-04-06 09:51:26 -0400594
595 @Override
596 public void networkStatus(int status, String redirectUrl) {
597 mRedirectUrl = redirectUrl;
598 mNetworkStatusReceived.open();
599 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700600
601 @Override
602 protected void preventAutomaticReconnect() {
603 mPreventReconnectReceived.open();
604 }
Mark Chiend0f8ca82019-04-29 09:46:04 -0700605
606 @Override
607 protected void addKeepalivePacketFilter(Message msg) {
608 Log.i(TAG, "Add keepalive packet filter.");
609 }
610
611 @Override
612 protected void removeKeepalivePacketFilter(Message msg) {
613 Log.i(TAG, "Remove keepalive packet filter.");
614 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400615 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900616
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900617 assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900618 mNmCallbacks = nmCbCaptor.getValue();
619
620 try {
621 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
622 } catch (RemoteException e) {
623 fail(e.getMessage());
624 }
625
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900626 // Waits for the NetworkAgent to be registered, which includes the creation of the
627 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900628 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900629 }
630
631 private void onValidationRequested() {
632 try {
633 if (mNmProvNotificationRequested
Chiachang Wang6786252e2019-05-25 08:42:17 -0700634 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900635 mNmCallbacks.hideProvisioningNotification();
636 mNmProvNotificationRequested = false;
637 }
638
639 mNmCallbacks.notifyNetworkTested(
640 mNmValidationResult, mNmValidationRedirectUrl);
641
642 if (mNmValidationRedirectUrl != null) {
643 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900644 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900645 mNmProvNotificationRequested = true;
646 }
647 } catch (RemoteException e) {
648 fail(e.getMessage());
649 }
Paul Jensen3d911462015-06-12 06:40:24 -0400650 }
651
652 public void adjustScore(int change) {
653 mScore += change;
654 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400655 }
656
Chalard Jeanf9861102019-05-10 04:33:43 -0700657 public int getScore() {
658 return mScore;
659 }
660
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900661 public void explicitlySelected(boolean acceptUnvalidated) {
662 mNetworkAgent.explicitlySelected(acceptUnvalidated);
663 }
664
Paul Jensen85cf78e2015-06-25 13:25:07 -0400665 public void addCapability(int capability) {
666 mNetworkCapabilities.addCapability(capability);
667 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
668 }
669
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900670 public void removeCapability(int capability) {
671 mNetworkCapabilities.removeCapability(capability);
672 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
673 }
674
Chalard Jean0b214af2018-01-12 17:22:49 +0900675 public void setUids(Set<UidRange> uids) {
676 mNetworkCapabilities.setUids(uids);
677 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
678 }
679
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900680 public void setSignalStrength(int signalStrength) {
681 mNetworkCapabilities.setSignalStrength(signalStrength);
682 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
683 }
684
Etan Cohena7434272017-04-03 12:17:51 -0700685 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
686 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900687 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
688 }
689
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900690 public void setNetworkCapabilities(NetworkCapabilities nc,
691 boolean sendToConnectivityService) {
692 mNetworkCapabilities.set(nc);
693 if (sendToConnectivityService) {
694 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
695 }
696 }
697
Paul Jensene0988542015-06-25 15:30:08 -0400698 public void connectWithoutInternet() {
699 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
700 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
701 }
702
Paul Jensend7b6ca92015-05-13 14:05:12 -0400703 /**
Paul Jensene0988542015-06-25 15:30:08 -0400704 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400705 * @param validated Indicate if network should pretend to be validated.
706 */
707 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900708 connect(validated, true);
709 }
710
711 /**
712 * Transition this NetworkAgent to CONNECTED state.
713 * @param validated Indicate if network should pretend to be validated.
714 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
715 */
716 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900717 assertEquals("MockNetworkAgents can only be connected once",
718 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400719 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
720
Paul Jensend7b6ca92015-05-13 14:05:12 -0400721 NetworkCallback callback = null;
722 final ConditionVariable validatedCv = new ConditionVariable();
723 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900724 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400725 NetworkRequest request = new NetworkRequest.Builder()
726 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900727 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400728 .build();
729 callback = new NetworkCallback() {
730 public void onCapabilitiesChanged(Network network,
731 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400732 if (network.equals(getNetwork()) &&
733 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400734 validatedCv.open();
735 }
736 }
737 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400738 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400739 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900740 if (hasInternet) {
741 addCapability(NET_CAPABILITY_INTERNET);
742 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400743
Paul Jensene0988542015-06-25 15:30:08 -0400744 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400745
746 if (validated) {
747 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400748 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900749 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400750 }
751
752 if (callback != null) mCm.unregisterNetworkCallback(callback);
753 }
754
Paul Jensen232437312016-04-06 09:51:26 -0400755 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900756 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400757 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400758 }
759
lucasline252a742019-03-12 13:08:03 +0800760 public void connectWithPartialConnectivity() {
761 setNetworkPartial();
762 connect(false);
763 }
764
Erik Kline1d3db322017-02-28 16:20:20 +0900765 public void suspend() {
766 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
767 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
768 }
769
Chalard Jean804b8fb2018-01-30 22:41:41 +0900770 public void resume() {
771 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
772 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
773 }
774
Paul Jensend7b6ca92015-05-13 14:05:12 -0400775 public void disconnect() {
776 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
777 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
778 }
779
780 public Network getNetwork() {
781 return new Network(mNetworkAgent.netId);
782 }
Paul Jensene0988542015-06-25 15:30:08 -0400783
Calvin On1f64f3f2016-10-11 15:10:46 -0700784 public ConditionVariable getPreventReconnectReceived() {
785 return mPreventReconnectReceived;
786 }
787
Paul Jensene0988542015-06-25 15:30:08 -0400788 public ConditionVariable getDisconnectedCV() {
789 return mDisconnected;
790 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400791
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900792 public void sendLinkProperties(LinkProperties lp) {
793 mNetworkAgent.sendLinkProperties(lp);
794 }
795
796 public void setStartKeepaliveError(int error) {
797 mStartKeepaliveError = error;
798 }
799
800 public void setStopKeepaliveError(int error) {
801 mStopKeepaliveError = error;
802 }
803
804 public void setExpectedKeepaliveSlot(Integer slot) {
805 mExpectedKeepaliveSlot = slot;
806 }
Paul Jensen232437312016-04-06 09:51:26 -0400807
808 public String waitForRedirectUrl() {
809 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
810 return mRedirectUrl;
811 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900812
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900813 public NetworkAgent getNetworkAgent() {
814 return mNetworkAgent;
815 }
816
Chalard Jean804b8fb2018-01-30 22:41:41 +0900817 public NetworkCapabilities getNetworkCapabilities() {
818 return mNetworkCapabilities;
819 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400820 }
821
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900822 /**
823 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
824 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean08577fc2018-05-02 21:14:54 +0900825 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900826 * expectRemoveRequests.
827 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700828 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400829 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
830 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400831 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700832
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900833 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean08577fc2018-05-02 21:14:54 +0900834 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
835 // once, then cause some other thread to add or remove requests, then call
836 // waitForRequests().
837 // It is not possible to wait for both add and remove requests. When adding, the queue
838 // contains the expected score. When removing, the value is unused, all matters is the
839 // number of objects in the queue.
840 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900841
842 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean08577fc2018-05-02 21:14:54 +0900843 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900844 private boolean mExpectingAdditions;
845
Etan Cohenae574a82019-01-08 12:09:18 -0800846 // Used to collect the networks requests managed by this factory. This is a duplicate of
847 // the internal information stored in the NetworkFactory (which is private).
848 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
849
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700850 public MockNetworkFactory(Looper looper, Context context, String logTag,
851 NetworkCapabilities filter) {
852 super(looper, context, logTag, filter);
Chalard Jean08577fc2018-05-02 21:14:54 +0900853 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700854 }
855
856 public int getMyRequestCount() {
857 return getRequestCount();
858 }
859
860 protected void startNetwork() {
861 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400862 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700863 }
864
865 protected void stopNetwork() {
866 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400867 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700868 }
869
870 public boolean getMyStartRequested() {
871 return mNetworkStarted.get();
872 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400873
874 public ConditionVariable getNetworkStartedCV() {
875 mNetworkStartedCV.close();
876 return mNetworkStartedCV;
877 }
878
879 public ConditionVariable getNetworkStoppedCV() {
880 mNetworkStoppedCV.close();
881 return mNetworkStoppedCV;
882 }
883
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900884 @Override
Chalard Jean08577fc2018-05-02 21:14:54 +0900885 protected void handleAddRequest(NetworkRequest request, int score,
886 int factorySerialNumber) {
887 synchronized (mExpectations) {
888 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900889
Chalard Jean08577fc2018-05-02 21:14:54 +0900890 assertNotNull("Added more requests than expected (" + request + " score : "
891 + score + ")", expectedScore);
892 // If we're expecting anything, we must be expecting additions.
893 if (!mExpectingAdditions) {
894 fail("Can't add requests while expecting requests to be removed");
895 }
896 if (expectedScore != score) {
897 fail("Expected score was " + expectedScore + " but actual was " + score
898 + " in added request");
899 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900900
Chalard Jean08577fc2018-05-02 21:14:54 +0900901 // Add the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800902 mNetworkRequests.put(request.requestId, request);
Chalard Jean08577fc2018-05-02 21:14:54 +0900903 super.handleAddRequest(request, score, factorySerialNumber);
904 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900905 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400906 }
907
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900908 @Override
909 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900910 synchronized (mExpectations) {
911 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900912
Chalard Jean08577fc2018-05-02 21:14:54 +0900913 assertTrue("Removed more requests than expected", expectedScore != null);
914 // If we're expecting anything, we must be expecting removals.
915 if (mExpectingAdditions) {
916 fail("Can't remove requests while expecting requests to be added");
917 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900918
Chalard Jean08577fc2018-05-02 21:14:54 +0900919 // Remove the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800920 mNetworkRequests.remove(request.requestId);
Chalard Jean08577fc2018-05-02 21:14:54 +0900921 super.handleRemoveRequest(request);
922 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900923 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400924 }
925
Etan Cohenae574a82019-01-08 12:09:18 -0800926 // Trigger releasing the request as unfulfillable
927 public void triggerUnfulfillable(NetworkRequest r) {
928 super.releaseRequestAsUnfulfillableByAnyFactory(r);
929 }
930
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900931 private void assertNoExpectations() {
Chalard Jean08577fc2018-05-02 21:14:54 +0900932 if (mExpectations.size() != 0) {
933 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900934 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400935 }
936
Chalard Jean08577fc2018-05-02 21:14:54 +0900937 // Expects that requests with the specified scores will be added.
938 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900939 assertNoExpectations();
940 mExpectingAdditions = true;
Chalard Jean08577fc2018-05-02 21:14:54 +0900941 for (int score : scores) {
942 mExpectations.add(score);
943 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400944 }
945
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900946 // Expects that count requests will be removed.
947 public void expectRemoveRequests(final int count) {
948 assertNoExpectations();
949 mExpectingAdditions = false;
Chalard Jean08577fc2018-05-02 21:14:54 +0900950 for (int i = 0; i < count; ++i) {
951 mExpectations.add(0); // For removals the score is ignored so any value will do.
952 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900953 }
954
955 // Waits for the expected request additions or removals to happen within a timeout.
956 public void waitForRequests() throws InterruptedException {
Chalard Jean08577fc2018-05-02 21:14:54 +0900957 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
958 synchronized (mExpectations) {
959 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
960 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
961 }
962 }
963 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900964 final String msg = count + " requests still not " +
965 (mExpectingAdditions ? "added" : "removed") +
966 " after " + TIMEOUT_MS + " ms";
967 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900968 }
969
Etan Cohenae574a82019-01-08 12:09:18 -0800970 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
971 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900972 waitForRequests();
973 assertEquals(count, getMyRequestCount());
Etan Cohenae574a82019-01-08 12:09:18 -0800974 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400975 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700976 }
977
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900978 private static Looper startHandlerThreadAndReturnLooper() {
979 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
980 handlerThread.start();
981 return handlerThread.getLooper();
982 }
983
984 private class MockVpn extends Vpn {
985 // TODO : the interactions between this mock and the mock network agent are too
986 // hard to get right at this moment, because it's unclear in which case which
987 // target needs to get a method call or both, and in what order. It's because
988 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
989 // parent class of MockVpn agent wants that responsibility.
990 // That being said inside the test it should be possible to make the interactions
991 // harder to get wrong with precise speccing, judicious comments, helper methods
992 // and a few sprinkled assertions.
993
994 private boolean mConnected = false;
995 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
996 // not inherit from NetworkAgent.
997 private MockNetworkAgent mMockNetworkAgent;
998
999 public MockVpn(int userId) {
1000 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
1001 userId);
1002 }
1003
1004 public void setNetworkAgent(MockNetworkAgent agent) {
1005 waitForIdle(agent, TIMEOUT_MS);
1006 mMockNetworkAgent = agent;
1007 mNetworkAgent = agent.getNetworkAgent();
1008 mNetworkCapabilities.set(agent.getNetworkCapabilities());
1009 }
1010
1011 public void setUids(Set<UidRange> uids) {
1012 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -08001013 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001014 }
1015
1016 @Override
1017 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -08001018 if (mMockNetworkAgent == null) {
1019 return NETID_UNSET;
1020 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001021 return mMockNetworkAgent.getNetwork().netId;
1022 }
1023
1024 @Override
1025 public boolean appliesToUid(int uid) {
1026 return mConnected; // Trickery to simplify testing.
1027 }
1028
1029 @Override
1030 protected boolean isCallerEstablishedOwnerLocked() {
1031 return mConnected; // Similar trickery
1032 }
1033
Varun Anandc51b06d2019-02-25 17:22:02 -08001034 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001035 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1036 mConnected = true;
1037 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001038 mConfig.isMetered = isAlwaysMetered;
1039 }
1040
1041 public void connectAsAlwaysMetered() {
1042 connect(true /* isAlwaysMetered */);
1043 }
1044
1045 public void connect() {
1046 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001047 }
1048
1049 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001050 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1051 if (!mConnected) return null;
1052 super.updateCapabilities(defaultNetwork);
1053 // Because super.updateCapabilities will update the capabilities of the agent but
1054 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001055 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001056 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001057 }
1058
1059 private void copyCapabilitiesToNetworkAgent() {
1060 if (null != mMockNetworkAgent) {
1061 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1062 false /* sendToConnectivityService */);
1063 }
1064 }
1065
1066 public void disconnect() {
1067 mConnected = false;
1068 mConfig = null;
1069 }
1070 }
1071
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001072 private class FakeWakeupMessage extends WakeupMessage {
1073 private static final int UNREASONABLY_LONG_WAIT = 1000;
1074
1075 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
1076 super(context, handler, cmdName, cmd);
1077 }
1078
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001079 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
1080 int arg1, int arg2, Object obj) {
1081 super(context, handler, cmdName, cmd, arg1, arg2, obj);
1082 }
1083
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001084 @Override
1085 public void schedule(long when) {
1086 long delayMs = when - SystemClock.elapsedRealtime();
1087 if (delayMs < 0) delayMs = 0;
1088 if (delayMs > UNREASONABLY_LONG_WAIT) {
1089 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
1090 "ms into the future: " + delayMs);
1091 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001092 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1093 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001094 }
1095
1096 @Override
1097 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001098 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001099 }
1100
1101 @Override
1102 public void onAlarm() {
1103 throw new AssertionError("Should never happen. Update this fake.");
1104 }
1105 }
1106
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001107 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +09001108 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001109 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -04001110
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001111 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001112 super(c, h, r);
1113 }
1114
1115 @Override
1116 public boolean configRestrictsAvoidBadWifi() {
1117 return configRestrictsAvoidBadWifi;
1118 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001119
1120 @Override
1121 public int configMeteredMultipathPreference() {
1122 return configMeteredMultipathPreference;
1123 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001124 }
1125
1126 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001127 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001128 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001129
Paul Jensend7b6ca92015-05-13 14:05:12 -04001130 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001131 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Luke Huang65914772019-03-16 00:31:46 +08001132 IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
Rubin Xu9a3f7242019-04-11 11:45:43 -07001133 super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001134 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001135 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001136 }
1137
1138 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001139 protected MockableSystemProperties getSystemProperties() {
1140 // Minimal approach to overriding system properties: let most calls fall through to real
1141 // device values, and only override ones values that are important to this test.
1142 mSystemProperties = spy(new MockableSystemProperties());
1143 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1144 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1145 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001146 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001147
1148 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001149 protected Tethering makeTethering() {
1150 return mock(Tethering.class);
1151 }
1152
1153 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001154 protected ProxyTracker makeProxyTracker() {
1155 return mock(ProxyTracker.class);
1156 }
1157
1158 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001159 protected int reserveNetId() {
1160 while (true) {
1161 final int netId = super.reserveNetId();
1162
1163 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1164 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001165 Context context = InstrumentationRegistry.getContext();
1166 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001167 boolean overlaps = false;
1168 for (Network network : networks) {
1169 if (netId == network.netId) {
1170 overlaps = true;
1171 break;
1172 }
1173 }
1174 if (overlaps) continue;
1175
1176 return netId;
1177 }
1178 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001179
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001180 @Override
1181 protected boolean queryUserAccess(int uid, int netId) {
1182 return true;
1183 }
1184
junyulai4a192e22018-06-13 15:00:37 +08001185 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1186 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1187 }
1188
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001189 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001190 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001191 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001192 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001193 return tracker;
1194 }
1195
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001196 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1197 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001198 }
1199
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001200 @Override
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +09001201 protected NetworkStackClient getNetworkStack() {
1202 return mNetworkStack;
1203 }
1204
1205 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001206 public WakeupMessage makeWakeupMessage(
1207 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1208 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001209 }
1210
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001211 @Override
1212 public boolean hasService(String name) {
1213 // Currenty, the only relevant service that ConnectivityService checks for is
1214 // ETHERNET_SERVICE.
1215 return Context.ETHERNET_SERVICE.equals(name);
1216 }
1217
Hugo Benichi64901e52017-10-19 14:42:40 +09001218 @Override
1219 protected IpConnectivityMetrics.Logger metricsLogger() {
1220 return mMetricsService;
1221 }
1222
dalyk1fcb7392018-03-05 12:42:22 -05001223 @Override
1224 protected void registerNetdEventCallback() {
1225 }
1226
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001227 public void mockVpn(int uid) {
1228 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001229 int userId = UserHandle.getUserId(uid);
1230 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001231 // This has no effect unless the VPN is actually connected, because things like
1232 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1233 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001234 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001235 }
1236 }
1237
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001238 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001239 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001240 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001241
1242 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001243 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001244 }
Mike Yuf9729752018-08-17 15:22:05 +08001245
1246 public void setUidRulesChanged(int uidRules) {
1247 try {
1248 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1249 } catch (RemoteException ignored) {
1250 }
1251 }
1252
1253 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1254 try {
1255 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1256 } catch (RemoteException ignored) {
1257 }
1258 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001259 }
1260
Paul Jensen3d911462015-06-12 06:40:24 -04001261 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001262 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1263 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001264 */
1265 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001266 if (conditionVariable.block(TIMEOUT_MS)) {
1267 return;
1268 }
1269 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001270 }
1271
Rubin Xu9a3f7242019-04-11 11:45:43 -07001272 private static final int VPN_USER = 0;
1273 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1274 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1275 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1276
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001277 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001278 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001279 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001280
Hugo Benichi64901e52017-10-19 14:42:40 +09001281 MockitoAnnotations.initMocks(this);
1282 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1283
Rubin Xu9a3f7242019-04-11 11:45:43 -07001284 when(mUserManager.getUsers(eq(true))).thenReturn(
1285 Arrays.asList(new UserInfo[] {
1286 new UserInfo(VPN_USER, "", 0),
1287 }));
Rubin Xu9a3f7242019-04-11 11:45:43 -07001288
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001289 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1290 // http://b/25897652 .
1291 if (Looper.myLooper() == null) {
1292 Looper.prepare();
1293 }
Rubin Xu12384742019-04-24 03:05:12 -07001294 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001295
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001296 FakeSettingsProvider.clearSettingsProvider();
1297 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1298 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001299 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1300 LocalServices.addService(
1301 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001302
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001303 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001304 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001305 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001306 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001307 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001308 mMockNetd,
1309 mMockDnsResolver);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001310
Mike Yuf9729752018-08-17 15:22:05 +08001311 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1312 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1313 verify(mNpm).registerListener(policyListenerCaptor.capture());
1314 mPolicyListener = policyListenerCaptor.getValue();
1315
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001316 // Create local CM before sending system ready so that we can answer
1317 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001318 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001319 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001320 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001321 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001322
1323 // Ensure that the default setting for Captive Portals is used for most tests
1324 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001325 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001326 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001327 }
1328
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001329 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001330 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001331 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001332 if (mCellNetworkAgent != null) {
1333 mCellNetworkAgent.disconnect();
1334 mCellNetworkAgent = null;
1335 }
1336 if (mWiFiNetworkAgent != null) {
1337 mWiFiNetworkAgent.disconnect();
1338 mWiFiNetworkAgent = null;
1339 }
1340 if (mEthernetNetworkAgent != null) {
1341 mEthernetNetworkAgent.disconnect();
1342 mEthernetNetworkAgent = null;
1343 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001344 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001345 }
1346
Rubin Xu12384742019-04-24 03:05:12 -07001347 private void mockDefaultPackages() throws Exception {
1348 final String testPackageName = mContext.getPackageName();
1349 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1350 testPackageName, PackageManager.GET_PERMISSIONS);
1351 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1352 new String[] {testPackageName});
1353 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1354 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1355
1356 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1357 Arrays.asList(new PackageInfo[] {
1358 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1359 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1360 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1361 }));
1362 }
1363
1364 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001365 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001366 case TRANSPORT_ETHERNET:
1367 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001368 case TRANSPORT_WIFI:
1369 return TYPE_WIFI;
1370 case TRANSPORT_CELLULAR:
1371 return TYPE_MOBILE;
Chalard Jeanf9861102019-05-10 04:33:43 -07001372 case TRANSPORT_VPN:
1373 return TYPE_VPN;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001374 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001375 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001376 }
1377 }
1378
1379 private void verifyActiveNetwork(int transport) {
1380 // Test getActiveNetworkInfo()
1381 assertNotNull(mCm.getActiveNetworkInfo());
1382 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1383 // Test getActiveNetwork()
1384 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001385 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001386 if (!NetworkCapabilities.isValidTransport(transport)) {
1387 throw new IllegalStateException("Unknown transport " + transport);
1388 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001389 switch (transport) {
1390 case TRANSPORT_WIFI:
1391 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1392 break;
1393 case TRANSPORT_CELLULAR:
1394 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1395 break;
1396 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001397 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001398 }
1399 // Test getNetworkInfo(Network)
1400 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001401 assertEquals(transportToLegacyType(transport),
1402 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001403 // Test getNetworkCapabilities(Network)
1404 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1405 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1406 }
1407
1408 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001409 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001410 // Test getActiveNetworkInfo()
1411 assertNull(mCm.getActiveNetworkInfo());
1412 // Test getActiveNetwork()
1413 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001414 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001415 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001416 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001417 }
1418
1419 /**
1420 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1421 * broadcasts are received.
1422 */
1423 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1424 final ConditionVariable cv = new ConditionVariable();
1425 mServiceContext.registerReceiver(new BroadcastReceiver() {
1426 private int remaining = count;
1427 public void onReceive(Context context, Intent intent) {
1428 if (--remaining == 0) {
1429 cv.open();
1430 mServiceContext.unregisterReceiver(this);
1431 }
1432 }
1433 }, new IntentFilter(CONNECTIVITY_ACTION));
1434 return cv;
1435 }
1436
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001437 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001438 public void testNetworkTypes() {
1439 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1440 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1441 // will fail. Failing here is much easier to debug.
1442 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1443 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001444 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1445 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1446
1447 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1448 // mocks, this assert exercises the ConnectivityService code path that ensures that
1449 // TYPE_ETHERNET is supported if the ethernet service is running.
1450 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001451 }
1452
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001453 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001454 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001455 verifyNoNetwork();
1456 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1457 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1458 assertNull(mCm.getActiveNetworkInfo());
1459 assertNull(mCm.getActiveNetwork());
1460 // Test bringing up validated cellular.
1461 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1462 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001463 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001464 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001465 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001466 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1467 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1468 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1469 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1470 // Test bringing up validated WiFi.
1471 cv = waitForConnectivityBroadcasts(2);
1472 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001473 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001474 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001475 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001476 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1477 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1478 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1479 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1480 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001481 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001482 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001483 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001484 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001485 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001486 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1487 // Test WiFi disconnect.
1488 cv = waitForConnectivityBroadcasts(1);
1489 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001490 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001491 verifyNoNetwork();
1492 }
1493
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001494 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001495 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1496 // Test bringing up unvalidated WiFi
1497 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1498 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1499 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001500 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001501 verifyActiveNetwork(TRANSPORT_WIFI);
1502 // Test bringing up unvalidated cellular
1503 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1504 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001505 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001506 verifyActiveNetwork(TRANSPORT_WIFI);
1507 // Test cellular disconnect.
1508 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001509 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001510 verifyActiveNetwork(TRANSPORT_WIFI);
1511 // Test bringing up validated cellular
1512 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1513 cv = waitForConnectivityBroadcasts(2);
1514 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001515 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001516 verifyActiveNetwork(TRANSPORT_CELLULAR);
1517 // Test cellular disconnect.
1518 cv = waitForConnectivityBroadcasts(2);
1519 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001520 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001521 verifyActiveNetwork(TRANSPORT_WIFI);
1522 // Test WiFi disconnect.
1523 cv = waitForConnectivityBroadcasts(1);
1524 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001525 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001526 verifyNoNetwork();
1527 }
1528
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001529 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001530 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1531 // Test bringing up unvalidated cellular.
1532 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1533 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1534 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001535 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001536 verifyActiveNetwork(TRANSPORT_CELLULAR);
1537 // Test bringing up unvalidated WiFi.
1538 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1539 cv = waitForConnectivityBroadcasts(2);
1540 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001541 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001542 verifyActiveNetwork(TRANSPORT_WIFI);
1543 // Test WiFi disconnect.
1544 cv = waitForConnectivityBroadcasts(2);
1545 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001546 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001547 verifyActiveNetwork(TRANSPORT_CELLULAR);
1548 // Test cellular disconnect.
1549 cv = waitForConnectivityBroadcasts(1);
1550 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001551 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001552 verifyNoNetwork();
1553 }
1554
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001555 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001556 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001557 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001558 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001559 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1560 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001561 waitFor(cv);
1562 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001563 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001564 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001565 // Test bringing up validated cellular.
1566 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001567 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001568 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001569 waitFor(cv);
1570 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001571 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1572 NET_CAPABILITY_VALIDATED));
1573 // Test cellular disconnect.
1574 cv = waitForConnectivityBroadcasts(2);
1575 mCellNetworkAgent.disconnect();
1576 waitFor(cv);
1577 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001578 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001579 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001580 NET_CAPABILITY_VALIDATED));
1581 }
1582
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001583 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001584 public void testCellularOutscoresWeakWifi() throws Exception {
1585 // Test bringing up validated cellular.
1586 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1587 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1588 mCellNetworkAgent.connect(true);
1589 waitFor(cv);
1590 verifyActiveNetwork(TRANSPORT_CELLULAR);
1591 // Test bringing up validated WiFi.
1592 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1593 cv = waitForConnectivityBroadcasts(2);
1594 mWiFiNetworkAgent.connect(true);
1595 waitFor(cv);
1596 verifyActiveNetwork(TRANSPORT_WIFI);
1597 // Test WiFi getting really weak.
1598 cv = waitForConnectivityBroadcasts(2);
1599 mWiFiNetworkAgent.adjustScore(-11);
1600 waitFor(cv);
1601 verifyActiveNetwork(TRANSPORT_CELLULAR);
1602 // Test WiFi restoring signal strength.
1603 cv = waitForConnectivityBroadcasts(2);
1604 mWiFiNetworkAgent.adjustScore(11);
1605 waitFor(cv);
1606 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001607 }
1608
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001609 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001610 public void testReapingNetwork() throws Exception {
1611 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1612 // Expect it to be torn down immediately because it satisfies no requests.
1613 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1614 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1615 mWiFiNetworkAgent.connectWithoutInternet();
1616 waitFor(cv);
1617 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1618 // Expect it to be torn down immediately because it satisfies no requests.
1619 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1620 cv = mCellNetworkAgent.getDisconnectedCV();
1621 mCellNetworkAgent.connectWithoutInternet();
1622 waitFor(cv);
1623 // Test bringing up validated WiFi.
1624 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1625 cv = waitForConnectivityBroadcasts(1);
1626 mWiFiNetworkAgent.connect(true);
1627 waitFor(cv);
1628 verifyActiveNetwork(TRANSPORT_WIFI);
1629 // Test bringing up unvalidated cellular.
1630 // Expect it to be torn down because it could never be the highest scoring network
1631 // satisfying the default request even if it validated.
1632 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1633 cv = mCellNetworkAgent.getDisconnectedCV();
1634 mCellNetworkAgent.connect(false);
1635 waitFor(cv);
1636 verifyActiveNetwork(TRANSPORT_WIFI);
1637 cv = mWiFiNetworkAgent.getDisconnectedCV();
1638 mWiFiNetworkAgent.disconnect();
1639 waitFor(cv);
1640 }
1641
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001642 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001643 public void testCellularFallback() throws Exception {
1644 // Test bringing up validated cellular.
1645 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1646 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1647 mCellNetworkAgent.connect(true);
1648 waitFor(cv);
1649 verifyActiveNetwork(TRANSPORT_CELLULAR);
1650 // Test bringing up validated WiFi.
1651 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1652 cv = waitForConnectivityBroadcasts(2);
1653 mWiFiNetworkAgent.connect(true);
1654 waitFor(cv);
1655 verifyActiveNetwork(TRANSPORT_WIFI);
1656 // Reevaluate WiFi (it'll instantly fail DNS).
1657 cv = waitForConnectivityBroadcasts(2);
1658 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1659 NET_CAPABILITY_VALIDATED));
1660 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1661 // Should quickly fall back to Cellular.
1662 waitFor(cv);
1663 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1664 NET_CAPABILITY_VALIDATED));
1665 verifyActiveNetwork(TRANSPORT_CELLULAR);
1666 // Reevaluate cellular (it'll instantly fail DNS).
1667 cv = waitForConnectivityBroadcasts(2);
1668 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1669 NET_CAPABILITY_VALIDATED));
1670 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1671 // Should quickly fall back to WiFi.
1672 waitFor(cv);
1673 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1674 NET_CAPABILITY_VALIDATED));
1675 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1676 NET_CAPABILITY_VALIDATED));
1677 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001678 }
1679
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001680 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001681 public void testWiFiFallback() throws Exception {
1682 // Test bringing up unvalidated WiFi.
1683 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1684 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1685 mWiFiNetworkAgent.connect(false);
1686 waitFor(cv);
1687 verifyActiveNetwork(TRANSPORT_WIFI);
1688 // Test bringing up validated cellular.
1689 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1690 cv = waitForConnectivityBroadcasts(2);
1691 mCellNetworkAgent.connect(true);
1692 waitFor(cv);
1693 verifyActiveNetwork(TRANSPORT_CELLULAR);
1694 // Reevaluate cellular (it'll instantly fail DNS).
1695 cv = waitForConnectivityBroadcasts(2);
1696 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1697 NET_CAPABILITY_VALIDATED));
1698 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1699 // Should quickly fall back to WiFi.
1700 waitFor(cv);
1701 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1702 NET_CAPABILITY_VALIDATED));
1703 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001704 }
1705
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001706 @Test
1707 public void testRequiresValidation() {
1708 assertTrue(NetworkMonitorUtils.isValidationRequired(
1709 mCm.getDefaultRequest().networkCapabilities));
1710 }
1711
Paul Jensen3d911462015-06-12 06:40:24 -04001712 enum CallbackState {
1713 NONE,
1714 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001715 NETWORK_CAPABILITIES,
1716 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001717 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001718 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001719 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001720 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001721 UNAVAILABLE,
1722 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001723 }
1724
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001725 private static class CallbackInfo {
1726 public final CallbackState state;
1727 public final Network network;
1728 public final Object arg;
1729 public CallbackInfo(CallbackState s, Network n, Object o) {
1730 state = s; network = n; arg = o;
1731 }
1732 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001733 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001734 }
1735 @Override
1736 public boolean equals(Object o) {
1737 if (!(o instanceof CallbackInfo)) return false;
1738 // Ignore timeMs, since it's unpredictable.
1739 CallbackInfo other = (CallbackInfo) o;
1740 return (state == other.state) && Objects.equals(network, other.network);
1741 }
1742 @Override
1743 public int hashCode() {
1744 return Objects.hash(state, network);
1745 }
1746 }
1747
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001748 /**
1749 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1750 * this class receives, by calling expectCallback() exactly once each time a callback is
1751 * received. assertNoCallback may be called at any time.
1752 */
Paul Jensen3d911462015-06-12 06:40:24 -04001753 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001754 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001755 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001756
Erik Klineacdd6392016-07-07 16:50:58 +09001757 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001758 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001759 }
Paul Jensen3d911462015-06-12 06:40:24 -04001760
Erik Klineacdd6392016-07-07 16:50:58 +09001761 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001762 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001763 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001764 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001765 }
1766
Erik Klineacdd6392016-07-07 16:50:58 +09001767 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001768 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1769 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1770 }
1771
1772 @Override
1773 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1774 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1775 }
1776
1777 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001778 public void onUnavailable() {
1779 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1780 }
1781
1782 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001783 public void onNetworkSuspended(Network network) {
1784 setLastCallback(CallbackState.SUSPENDED, network, null);
1785 }
1786
1787 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001788 public void onNetworkResumed(Network network) {
1789 setLastCallback(CallbackState.RESUMED, network, null);
1790 }
1791
1792 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001793 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001794 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001795 }
1796
Erik Klineacdd6392016-07-07 16:50:58 +09001797 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001798 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001799 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001800 setLastCallback(CallbackState.LOST, network, null);
1801 }
1802
Mike Yuf9729752018-08-17 15:22:05 +08001803 @Override
1804 public void onBlockedStatusChanged(Network network, boolean blocked) {
1805 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1806 }
1807
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001808 public Network getLastAvailableNetwork() {
1809 return mLastAvailableNetwork;
1810 }
1811
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001812 CallbackInfo nextCallback(int timeoutMs) {
1813 CallbackInfo cb = null;
1814 try {
1815 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1816 } catch (InterruptedException e) {
1817 }
1818 if (cb == null) {
1819 // LinkedBlockingQueue.poll() returns null if it timeouts.
1820 fail("Did not receive callback after " + timeoutMs + "ms");
1821 }
1822 return cb;
1823 }
1824
Erik Kline1d3db322017-02-28 16:20:20 +09001825 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1826 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1827 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001828 CallbackInfo actual = nextCallback(timeoutMs);
1829 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001830
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001831 if (state == CallbackState.LOSING) {
1832 String msg = String.format(
1833 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001834 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001835 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001836 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001837 }
Erik Kline1d3db322017-02-28 16:20:20 +09001838
1839 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001840 }
1841
Erik Kline1d3db322017-02-28 16:20:20 +09001842 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001843 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001844 }
1845
Hugo Benichi16f0a942017-06-20 14:07:59 +09001846 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001847 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001848 }
1849
1850 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1851 int timeLeft = timeoutMs;
1852 while (timeLeft > 0) {
1853 long start = SystemClock.elapsedRealtime();
1854 CallbackInfo info = nextCallback(timeLeft);
1855 if (fn.test(info)) {
1856 return info;
1857 }
1858 timeLeft -= (SystemClock.elapsedRealtime() - start);
1859 }
1860 fail("Did not receive expected callback after " + timeoutMs + "ms");
1861 return null;
1862 }
1863
Lorenzo Colitti27334542018-01-12 16:22:21 +09001864 // Expects onAvailable and the callbacks that follow it. These are:
1865 // - onSuspended, iff the network was suspended when the callbacks fire.
1866 // - onCapabilitiesChanged.
1867 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001868 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001869 //
1870 // @param agent the network to expect the callbacks on.
1871 // @param expectSuspended whether to expect a SUSPENDED callback.
1872 // @param expectValidated the expected value of the VALIDATED capability in the
1873 // onCapabilitiesChanged callback.
1874 // @param timeoutMs how long to wait for the callbacks.
1875 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001876 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001877 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001878 if (expectSuspended) {
1879 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001880 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001881 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001882 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001883 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001884 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001885 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001886 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001887 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001888 }
1889
Lorenzo Colitti27334542018-01-12 16:22:21 +09001890 // Expects the available callbacks (validated), plus onSuspended.
1891 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001892 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001893 }
1894
Lorenzo Colitti27334542018-01-12 16:22:21 +09001895 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001896 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1897 }
1898
1899 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1900 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001901 }
1902
Lorenzo Colitti27334542018-01-12 16:22:21 +09001903 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001904 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1905 }
1906
1907 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1908 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001909 }
1910
1911 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1912 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1913 // one we just sent.
1914 // TODO: this is likely a bug. Fix it and remove this method.
1915 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001916 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001917 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001918 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001919 // Implicitly check the network is allowed to use.
1920 // TODO: should we need to consider if network is in blocked status in this case?
1921 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001922 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1923 assertEquals(nc1, nc2);
1924 }
1925
1926 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1927 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1928 // when a network connects and satisfies a callback, and then immediately validates.
1929 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1930 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001931 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1932 }
1933
Lorenzo Colitti27334542018-01-12 16:22:21 +09001934 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001935 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001936 }
1937
1938 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1939 int timeoutMs) {
1940 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001941 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1942 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001943 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001944 }
1945
Lorenzo Colitti27334542018-01-12 16:22:21 +09001946 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001947 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001948 }
1949
1950 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1951 int timeoutMs) {
1952 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001953 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1954 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001955 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001956 }
1957
Chalard Jean0b214af2018-01-12 17:22:49 +09001958 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1959 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001960 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1961 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001962 }
1963
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001964 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1965 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1966 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1967 fn.test((LinkProperties) cbi.arg));
1968 }
1969
Mike Yuf9729752018-08-17 15:22:05 +08001970 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1971 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1972 boolean actualBlocked = (boolean) cbi.arg;
1973 assertEquals(expectBlocked, actualBlocked);
1974 }
1975
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001976 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001977 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001978 CallbackInfo c = mCallbacks.peek();
1979 assertNull("Unexpected callback: " + c, c);
1980 }
1981 }
1982
1983 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1984 // only be declared in a static or top level type".
1985 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1986 for (TestNetworkCallback c : callbacks) {
1987 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001988 }
1989 }
1990
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001991 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001992 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001993 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001994 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1995 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001996 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1997 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001998 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1999 .addTransportType(TRANSPORT_WIFI).build();
2000 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2001 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002002 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002003 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
2004 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2005
2006 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04002007 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2008 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2009 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002010 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2011 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002012 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2013 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002014 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002015
Paul Jensen3d911462015-06-12 06:40:24 -04002016 // This should not trigger spurious onAvailable() callbacks, b/21762680.
2017 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09002018 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002019 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002020 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2021
Paul Jensen3d911462015-06-12 06:40:24 -04002022 cv = waitForConnectivityBroadcasts(2);
2023 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2024 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002025 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2026 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002027 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2028 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002029 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002030
Paul Jensen3d911462015-06-12 06:40:24 -04002031 cv = waitForConnectivityBroadcasts(2);
2032 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002033 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2034 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09002035 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04002036 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002037 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002038
Paul Jensen3d911462015-06-12 06:40:24 -04002039 cv = waitForConnectivityBroadcasts(1);
2040 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002041 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2042 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002043 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002044 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002045
2046 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04002047 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2048 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002049 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2050 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002051 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002052 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002053
Paul Jensen3d911462015-06-12 06:40:24 -04002054 // This should not trigger spurious onAvailable() callbacks, b/21762680.
2055 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09002056 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002057 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002058 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2059
Paul Jensen3d911462015-06-12 06:40:24 -04002060 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2061 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002062 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002063 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002064 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002065 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002066 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002067 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002068 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002069
Paul Jensen3d911462015-06-12 06:40:24 -04002070 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002071 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2072 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2073 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002074
Paul Jensen3d911462015-06-12 06:40:24 -04002075 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002076 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2077 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2078 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002079 }
2080
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002081 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002082 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002083 // This test would be flaky with the default 120ms timer: that is short enough that
2084 // lingered networks are torn down before assertions can be run. We don't want to mock the
2085 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
2086 // in detecting races.
2087 mService.mLingerDelayMs = 300;
2088
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002089 NetworkRequest request = new NetworkRequest.Builder()
2090 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
2091 .build();
2092 TestNetworkCallback callback = new TestNetworkCallback();
2093 mCm.registerNetworkCallback(request, callback);
2094
2095 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2096 mCm.registerDefaultNetworkCallback(defaultCallback);
2097
2098 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2099 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2100 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2101
2102 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2103 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2104 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2105
2106 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002107 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2108 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002109 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002110 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002111
2112 mWiFiNetworkAgent.connect(true);
2113 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2114 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002115 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002116 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002117 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002118 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002119 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002120 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002121 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002122
2123 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002124 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002125 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002126 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002127 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002128 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002129 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002130 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002131
2132 mEthernetNetworkAgent.disconnect();
2133 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2134 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002135 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002136 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002137
2138 for (int i = 0; i < 4; i++) {
2139 MockNetworkAgent oldNetwork, newNetwork;
2140 if (i % 2 == 0) {
2141 mWiFiNetworkAgent.adjustScore(-15);
2142 oldNetwork = mWiFiNetworkAgent;
2143 newNetwork = mCellNetworkAgent;
2144 } else {
2145 mWiFiNetworkAgent.adjustScore(15);
2146 oldNetwork = mCellNetworkAgent;
2147 newNetwork = mWiFiNetworkAgent;
2148
2149 }
2150 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002151 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2152 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002153 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002154 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2155 }
2156 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2157
2158 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2159 // if the network is still up.
2160 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002161 // We expect a notification about the capabilities change, and nothing else.
2162 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2163 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002164 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002165 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002166
2167 // Wifi no longer satisfies our listen, which is for an unmetered network.
2168 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002169 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2170
2171 // Disconnect our test networks.
2172 mWiFiNetworkAgent.disconnect();
2173 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002174 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002175 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002176 mCellNetworkAgent.disconnect();
2177 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002178 waitForIdle();
2179 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002180
2181 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002182 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002183
2184 // Check that a network is only lingered or torn down if it would not satisfy a request even
2185 // if it validated.
2186 request = new NetworkRequest.Builder().clearCapabilities().build();
2187 callback = new TestNetworkCallback();
2188
2189 mCm.registerNetworkCallback(request, callback);
2190
2191 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2192 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002193 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2194 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002195 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002196 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002197
2198 // Bring up wifi with a score of 20.
2199 // Cell stays up because it would satisfy the default request if it validated.
2200 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2201 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002202 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2203 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002204 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002205 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002206
2207 mWiFiNetworkAgent.disconnect();
2208 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2209 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002210 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002211 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002212 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002213
2214 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002215 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002216 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2217 mWiFiNetworkAgent.adjustScore(50);
2218 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002219 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002220 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002221 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002222 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002223 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002224
2225 // Tear down wifi.
2226 mWiFiNetworkAgent.disconnect();
2227 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2228 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002229 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002230 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002231 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002232
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002233 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2234 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002235 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2236 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002237 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002238 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002239 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002240 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002241 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002242 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002243 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002244
2245 mWiFiNetworkAgent.disconnect();
2246 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002247 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002248 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002249 mCellNetworkAgent.disconnect();
2250 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2251 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002252 waitForIdle();
2253 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002254
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002255 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002256 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2257 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002258 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2259 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002260 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002261 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2262 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002263 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2264 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002265 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002266 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002267 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002268 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002269
2270 NetworkRequest cellRequest = new NetworkRequest.Builder()
2271 .addTransportType(TRANSPORT_CELLULAR).build();
2272 NetworkCallback noopCallback = new NetworkCallback();
2273 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002274 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2275 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002276 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002277 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002278
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002279 // Similar to the above: lingering can start even after the lingered request is removed.
2280 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002281 mWiFiNetworkAgent.disconnect();
2282 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002283 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002284 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002285 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002286
2287 // Cell is now the default network. Pin it with a cell-specific request.
2288 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2289 mCm.requestNetwork(cellRequest, noopCallback);
2290
2291 // Now connect wifi, and expect it to become the default network.
2292 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2293 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002294 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2295 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002296 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002297 // The default request is lingering on cell, but nothing happens to cell, and we send no
2298 // callbacks for it, because it's kept up by cellRequest.
2299 callback.assertNoCallback();
2300 // Now unregister cellRequest and expect cell to start lingering.
2301 mCm.unregisterNetworkCallback(noopCallback);
2302 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2303
2304 // Let linger run its course.
2305 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002306 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002307 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002308
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002309 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2310 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2311 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002312 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002313 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2314 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002315 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002316 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2317 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002318 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2319 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002320 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002321
2322 // Let linger run its course.
2323 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2324
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002325 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002326 mEthernetNetworkAgent.disconnect();
2327 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2328 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2329 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002330
2331 mCm.unregisterNetworkCallback(callback);
2332 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002333 mCm.unregisterNetworkCallback(trackDefaultCallback);
2334 }
2335
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002336 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002337 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002338 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002339 NetworkRequest request = new NetworkRequest.Builder()
2340 .clearCapabilities()
2341 .build();
2342 TestNetworkCallback callback = new TestNetworkCallback();
2343 mCm.registerNetworkCallback(request, callback);
2344
2345 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2346 mCm.registerDefaultNetworkCallback(defaultCallback);
2347
2348 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2349 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2350
2351 mCellNetworkAgent.connect(true);
2352 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2353 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2354
2355 // Wifi comes up and cell lingers.
2356 mWiFiNetworkAgent.connect(true);
2357 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2358 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2359 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2360 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2361
2362 // File a request for cellular, then release it.
2363 NetworkRequest cellRequest = new NetworkRequest.Builder()
2364 .addTransportType(TRANSPORT_CELLULAR).build();
2365 NetworkCallback noopCallback = new NetworkCallback();
2366 mCm.requestNetwork(cellRequest, noopCallback);
2367 mCm.unregisterNetworkCallback(noopCallback);
2368 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2369
2370 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002371 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002372 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2373 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2374 lingerTimeoutMs);
2375
2376 // Clean up.
2377 mCm.unregisterNetworkCallback(defaultCallback);
2378 mCm.unregisterNetworkCallback(callback);
2379 }
2380
2381 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002382 public void testExplicitlySelected() {
2383 NetworkRequest request = new NetworkRequest.Builder()
2384 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2385 .build();
2386 TestNetworkCallback callback = new TestNetworkCallback();
2387 mCm.registerNetworkCallback(request, callback);
2388
2389 // Bring up validated cell.
2390 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2391 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002392 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002393
2394 // Bring up unvalidated wifi with explicitlySelected=true.
2395 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2396 mWiFiNetworkAgent.explicitlySelected(false);
2397 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002398 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002399
2400 // Cell Remains the default.
2401 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2402
2403 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2404 // it's explicitly selected.
2405 mWiFiNetworkAgent.adjustScore(-40);
2406 mWiFiNetworkAgent.adjustScore(40);
2407 callback.assertNoCallback();
2408
2409 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2410 // wifi even though it's unvalidated.
2411 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2412 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2413 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2414
2415 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2416 mWiFiNetworkAgent.disconnect();
2417 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2418 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2419 mWiFiNetworkAgent.explicitlySelected(false);
2420 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002421 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002422
2423 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2424 // network to disconnect.
2425 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2426 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2427
2428 // Reconnect, again with explicitlySelected=true, but this time validate.
2429 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2430 mWiFiNetworkAgent.explicitlySelected(false);
2431 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002432 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002433 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2434 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2435 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2436
2437 // BUG: the network will no longer linger, even though it's validated and outscored.
2438 // TODO: fix this.
2439 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2440 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002441 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002442 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2443 callback.assertNoCallback();
2444
2445 // Clean up.
2446 mWiFiNetworkAgent.disconnect();
2447 mCellNetworkAgent.disconnect();
2448 mEthernetNetworkAgent.disconnect();
2449
2450 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2451 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2452 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002453 }
2454
Chalard Jean08577fc2018-05-02 21:14:54 +09002455 private int[] makeIntArray(final int size, final int value) {
2456 final int[] array = new int[size];
2457 Arrays.fill(array, value);
2458 return array;
2459 }
2460
Paul Jensen85cf78e2015-06-25 13:25:07 -04002461 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002462 // Verify NOT_RESTRICTED is set appropriately
2463 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2464 .build().networkCapabilities;
2465 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2466 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2467 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002468 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002469 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2470 } else {
2471 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2472 }
2473
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002474 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002475 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002476 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2477 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002478 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002479 mServiceContext, "testFactory", filter);
2480 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002481 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002482 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002483 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002484 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002485 int expectedRequestCount = 1;
2486 NetworkCallback networkCallback = null;
2487 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2488 // add one.
2489 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002490 assertFalse(testFactory.getMyStartRequested());
2491 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2492 networkCallback = new NetworkCallback();
Chalard Jean08577fc2018-05-02 21:14:54 +09002493 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002494 mCm.requestNetwork(request, networkCallback);
2495 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002496 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002497 }
Paul Jensen3d911462015-06-12 06:40:24 -04002498 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002499 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2500 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002501
Paul Jensen85cf78e2015-06-25 13:25:07 -04002502 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002503 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002504 // Rather than create a validated network which complicates things by registering it's
2505 // own NetworkRequest during startup, just bump up the score to cancel out the
2506 // unvalidated penalty.
2507 testAgent.adjustScore(40);
2508 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002509
2510 // When testAgent connects, ConnectivityService will re-send us all current requests with
2511 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2512 // them.
Chalard Jean08577fc2018-05-02 21:14:54 +09002513 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002514 testAgent.connect(false);
2515 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002516 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002517 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002518 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002519
Paul Jensen85cf78e2015-06-25 13:25:07 -04002520 // Bring in a bunch of requests.
Chalard Jean08577fc2018-05-02 21:14:54 +09002521 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002522 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002523 ConnectivityManager.NetworkCallback[] networkCallbacks =
2524 new ConnectivityManager.NetworkCallback[10];
2525 for (int i = 0; i< networkCallbacks.length; i++) {
2526 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2527 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002528 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002529 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2530 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002531 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2532 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002533
Paul Jensen85cf78e2015-06-25 13:25:07 -04002534 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002535 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002536 for (int i = 0; i < networkCallbacks.length; i++) {
2537 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2538 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002539 testFactory.waitForNetworkRequests(expectedRequestCount);
2540 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002541
Paul Jensen85cf78e2015-06-25 13:25:07 -04002542 // Drop the higher scored network.
2543 cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002544 // With the default network disconnecting, the requests are sent with score 0 to factories.
2545 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002546 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002547 waitFor(cv);
Chalard Jean08577fc2018-05-02 21:14:54 +09002548 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002549 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2550 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002551
2552 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002553 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002554 handlerThread.quit();
2555 }
2556
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002557 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002558 public void testNetworkFactoryRequests() throws Exception {
2559 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2560 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2561 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2562 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2563 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2564 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2565 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2566 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2567 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2568 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2569 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2570 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2571 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2572 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2573 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2574 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2575 }
2576
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002577 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002578 public void testNoMutableNetworkRequests() throws Exception {
2579 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002580 NetworkRequest request1 = new NetworkRequest.Builder()
2581 .addCapability(NET_CAPABILITY_VALIDATED)
2582 .build();
2583 NetworkRequest request2 = new NetworkRequest.Builder()
2584 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2585 .build();
2586
2587 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2588 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2589 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2590 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2591 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002592 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002593
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002594 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002595 public void testMMSonWiFi() throws Exception {
2596 // Test bringing up cellular without MMS NetworkRequest gets reaped
2597 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2598 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2599 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2600 mCellNetworkAgent.connectWithoutInternet();
2601 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002602 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002603 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002604 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002605
Paul Jensene0988542015-06-25 15:30:08 -04002606 // Test bringing up validated WiFi.
2607 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2608 cv = waitForConnectivityBroadcasts(1);
2609 mWiFiNetworkAgent.connect(true);
2610 waitFor(cv);
2611 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002612
Paul Jensene0988542015-06-25 15:30:08 -04002613 // Register MMS NetworkRequest
2614 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2615 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2616 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2617 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002618
Paul Jensene0988542015-06-25 15:30:08 -04002619 // Test bringing up unvalidated cellular with MMS
2620 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2621 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002622 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002623 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002624 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002625
Paul Jensene0988542015-06-25 15:30:08 -04002626 // Test releasing NetworkRequest disconnects cellular with MMS
2627 cv = mCellNetworkAgent.getDisconnectedCV();
2628 mCm.unregisterNetworkCallback(networkCallback);
2629 waitFor(cv);
2630 verifyActiveNetwork(TRANSPORT_WIFI);
2631 }
2632
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002633 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002634 public void testMMSonCell() throws Exception {
2635 // Test bringing up cellular without MMS
2636 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2637 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2638 mCellNetworkAgent.connect(false);
2639 waitFor(cv);
2640 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002641
Paul Jensene0988542015-06-25 15:30:08 -04002642 // Register MMS NetworkRequest
2643 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2644 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2645 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2646 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002647
Paul Jensene0988542015-06-25 15:30:08 -04002648 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002649 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2650 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2651 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002652 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002653 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002654
Paul Jensene0988542015-06-25 15:30:08 -04002655 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2656 cv = mmsNetworkAgent.getDisconnectedCV();
2657 mCm.unregisterNetworkCallback(networkCallback);
2658 waitFor(cv);
2659 verifyActiveNetwork(TRANSPORT_CELLULAR);
2660 }
2661
lucaslinf3b59b32019-03-26 17:49:49 +08002662 @Test
lucasline252a742019-03-12 13:08:03 +08002663 public void testPartialConnectivity() {
2664 // Register network callback.
2665 NetworkRequest request = new NetworkRequest.Builder()
2666 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2667 .build();
2668 TestNetworkCallback callback = new TestNetworkCallback();
2669 mCm.registerNetworkCallback(request, callback);
2670
2671 // Bring up validated mobile data.
2672 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2673 mCellNetworkAgent.connect(true);
2674 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2675
2676 // Bring up wifi with partial connectivity.
2677 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2678 mWiFiNetworkAgent.connectWithPartialConnectivity();
2679 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2680 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2681
2682 // Mobile data should be the default network.
2683 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2684 callback.assertNoCallback();
2685
lucaslinf3b59b32019-03-26 17:49:49 +08002686 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2687 // probe.
Chiachang Wang8d573212019-05-23 22:57:18 -07002688 mWiFiNetworkAgent.setNetworkPartialValid();
lucasline252a742019-03-12 13:08:03 +08002689 // If the user chooses yes to use this partial connectivity wifi, switch the default
2690 // network to wifi and check if wifi becomes valid or not.
2691 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2692 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002693 // If user accepts partial connectivity network,
2694 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002695 waitForIdle();
2696 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002697 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002698 } catch (RemoteException e) {
2699 fail(e.getMessage());
2700 }
lucaslinf3b59b32019-03-26 17:49:49 +08002701 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2702 // validated.
2703 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
lucasline252a742019-03-12 13:08:03 +08002704 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2705 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2706 mWiFiNetworkAgent);
2707 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2708 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2709
2710 // Disconnect and reconnect wifi with partial connectivity again.
2711 mWiFiNetworkAgent.disconnect();
2712 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2714 mWiFiNetworkAgent.connectWithPartialConnectivity();
2715 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2716 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2717
2718 // Mobile data should be the default network.
2719 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2720
2721 // If the user chooses no, disconnect wifi immediately.
2722 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2723 false /* always */);
2724 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2725
2726 // If user accepted partial connectivity before, and device reconnects to that network
2727 // again, but now the network has full connectivity. The network shouldn't contain
2728 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2729 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2730 // acceptUnvalidated is also used as setting for accepting partial networks.
2731 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2732 mWiFiNetworkAgent.connect(true);
lucaslinf3b59b32019-03-26 17:49:49 +08002733 // If user accepted partial connectivity network before,
2734 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2735 // ConnectivityService#updateNetworkInfo().
2736 waitForIdle();
2737 try {
2738 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2739 } catch (RemoteException e) {
2740 fail(e.getMessage());
2741 }
lucasline252a742019-03-12 13:08:03 +08002742 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2743 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2744 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2745 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2746 // Wifi should be the default network.
2747 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2748 mWiFiNetworkAgent.disconnect();
2749 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2750
2751 // If user accepted partial connectivity before, and now the device reconnects to the
2752 // partial connectivity network. The network should be valid and contain
2753 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2754 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2755 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
lucaslinf3b59b32019-03-26 17:49:49 +08002756 // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
2757 // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
2758 // to ConnectivityService first then send VALID. Once NetworkMonitor support
2759 // multi-testResult, this test case also need to be changed to meet the new design.
lucasline252a742019-03-12 13:08:03 +08002760 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002761 // If user accepted partial connectivity network before,
2762 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2763 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002764 waitForIdle();
2765 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002766 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002767 } catch (RemoteException e) {
2768 fail(e.getMessage());
2769 }
lucaslinf3b59b32019-03-26 17:49:49 +08002770 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002771 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
lucaslinf3b59b32019-03-26 17:49:49 +08002772 // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
2773 // NetworkMonitor detects partial connectivity
lucasline252a742019-03-12 13:08:03 +08002774 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002775 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2776 mWiFiNetworkAgent.setNetworkValid();
2777 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2778 // validated.
2779 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2780 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2781 mWiFiNetworkAgent.disconnect();
2782 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002783 }
2784
2785 @Test
Chiachang Wang8d573212019-05-23 22:57:18 -07002786 public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
2787 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2788 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2789 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2790 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2791
2792 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2793 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2794 .addCapability(NET_CAPABILITY_VALIDATED).build();
2795 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2796
2797 // Bring up a network with a captive portal.
2798 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2799 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chiachang Wang6786252e2019-05-25 08:42:17 -07002800 String redirectUrl = "http://android.com/path";
2801 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
Chiachang Wang8d573212019-05-23 22:57:18 -07002802 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wang6786252e2019-05-25 08:42:17 -07002803 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8d573212019-05-23 22:57:18 -07002804
2805 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2806 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2807 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2808 .launchCaptivePortalApp();
2809
2810 // Report that the captive portal is dismissed with partial connectivity, and check that
2811 // callbacks are fired.
2812 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wang6786252e2019-05-25 08:42:17 -07002813 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8d573212019-05-23 22:57:18 -07002814 waitForIdle();
2815 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2816 mWiFiNetworkAgent);
2817
2818 // Report partial connectivity is accepted.
2819 mWiFiNetworkAgent.setNetworkPartialValid();
2820 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2821 false /* always */);
2822 waitForIdle();
2823 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang6786252e2019-05-25 08:42:17 -07002824 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chiachang Wang8d573212019-05-23 22:57:18 -07002825 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2826 NetworkCapabilities nc =
2827 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2828 mWiFiNetworkAgent);
2829
2830 mCm.unregisterNetworkCallback(captivePortalCallback);
2831 mCm.unregisterNetworkCallback(validatedCallback);
2832 }
2833
2834 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002835 public void testCaptivePortal() {
2836 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2837 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2838 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2839 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2840
2841 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2842 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2843 .addCapability(NET_CAPABILITY_VALIDATED).build();
2844 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002845
2846 // Bring up a network with a captive portal.
2847 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002848 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002849 String firstRedirectUrl = "http://example.com/firstPath";
2850 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002851 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002852 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002853
2854 // Take down network.
2855 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002856 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002857 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002858
2859 // Bring up a network with a captive portal.
2860 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002861 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002862 String secondRedirectUrl = "http://example.com/secondPath";
2863 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002864 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002865 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002866
2867 // Make captive portal disappear then revalidate.
2868 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002869 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002870 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002871 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002872
2873 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002874 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002875 // Expect no notification to be shown when captive portal disappears by itself
2876 verify(mNotificationManager, never()).notifyAsUser(
2877 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002878
2879 // Break network connectivity.
2880 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002881 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002882 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002883 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002884 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002885
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002886 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002887 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002888 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2889 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2890 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2891 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2892
2893 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2894 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2895 .addCapability(NET_CAPABILITY_VALIDATED).build();
2896 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2897
2898 // Bring up wifi.
2899 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2900 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002901 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002902 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2903
2904 // Check that calling startCaptivePortalApp does nothing.
2905 final int fastTimeoutMs = 100;
2906 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002907 waitForIdle();
2908 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002909 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2910
2911 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002912 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002913 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002914 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002915 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2916
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002917 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002918 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002919 waitForIdle();
2920 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2921
2922 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2923 final Bundle testBundle = new Bundle();
2924 final String testKey = "testkey";
2925 final String testValue = "testvalue";
2926 testBundle.putString(testKey, testValue);
2927 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2928 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2929 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2930 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002931
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002932 // Report that the captive portal is dismissed, and check that callbacks are fired
2933 mWiFiNetworkAgent.setNetworkValid();
2934 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002935 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002936 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002937 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2938 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002939
2940 mCm.unregisterNetworkCallback(validatedCallback);
2941 mCm.unregisterNetworkCallback(captivePortalCallback);
2942 }
2943
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002944 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002945 public void testAvoidOrIgnoreCaptivePortals() {
2946 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2947 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2948 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2949 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2950
2951 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2952 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2953 .addCapability(NET_CAPABILITY_VALIDATED).build();
2954 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2955
2956 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2957 // Bring up a network with a captive portal.
2958 // Expect it to fail to connect and not result in any callbacks.
2959 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2960 String firstRedirectUrl = "http://example.com/firstPath";
2961
2962 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2963 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2964 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2965 waitFor(disconnectCv);
2966 waitFor(avoidCv);
2967
2968 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002969 }
2970
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002971 private NetworkRequest.Builder newWifiRequestBuilder() {
2972 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2973 }
2974
Etan Cohen836ad572018-12-30 17:59:59 -08002975 /**
2976 * Verify request matching behavior with network specifiers.
2977 *
2978 * Note: this test is somewhat problematic since it involves removing capabilities from
2979 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2980 * as a WTF bug in
2981 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2982 * does work.
2983 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002984 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002985 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002986 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2987 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2988 Parcelable {
2989 @Override
2990 public boolean satisfiedBy(NetworkSpecifier other) {
2991 return true;
2992 }
2993
2994 @Override
2995 public int describeContents() {
2996 return 0;
2997 }
2998
2999 @Override
3000 public void writeToParcel(Parcel dest, int flags) {}
3001
3002 @Override
3003 public NetworkSpecifier redact() {
3004 return null;
3005 }
3006 }
3007
3008 // A network specifier that matches either another LocalNetworkSpecifier with the same
3009 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
3010 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3011 private String mString;
3012
3013 LocalStringNetworkSpecifier(String string) {
3014 mString = string;
3015 }
3016
3017 @Override
3018 public boolean satisfiedBy(NetworkSpecifier other) {
3019 if (other instanceof LocalStringNetworkSpecifier) {
3020 return TextUtils.equals(mString,
3021 ((LocalStringNetworkSpecifier) other).mString);
3022 }
3023 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
3024 return false;
3025 }
3026
3027 @Override
3028 public int describeContents() {
3029 return 0;
3030 }
3031 @Override
3032 public void writeToParcel(Parcel dest, int flags) {}
3033 }
3034
3035
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003036 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07003037 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003038 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07003039 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
3040 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08003041 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
3042 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07003043 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08003044 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003045
3046 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
3047 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
3048 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07003049 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003050 TestNetworkCallback cFoo = new TestNetworkCallback();
3051 TestNetworkCallback cBar = new TestNetworkCallback();
3052 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08003053 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003054
3055 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
3056 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
3057 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07003058 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003059 mCm.registerNetworkCallback(rFoo, cFoo);
3060 mCm.registerNetworkCallback(rBar, cBar);
3061
Etan Cohen836ad572018-12-30 17:59:59 -08003062 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
3063 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
3064
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003065 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3066 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003067 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3068 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3069 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3070 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003071 assertNoCallbacks(cFoo, cBar);
3072
Etan Cohen836ad572018-12-30 17:59:59 -08003073 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003074 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003075 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08003076 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
3077 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003078 }
Etan Cohen836ad572018-12-30 17:59:59 -08003079 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
3080 mWiFiNetworkAgent);
3081 assertEquals(nsFoo,
3082 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003083 cFoo.assertNoCallback();
3084
Etan Cohen836ad572018-12-30 17:59:59 -08003085 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003086 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003087 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003088 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08003089 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
3090 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003091 }
Etan Cohen836ad572018-12-30 17:59:59 -08003092 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
3093 mWiFiNetworkAgent);
3094 assertEquals(nsBar,
3095 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3096 cBar.assertNoCallback();
3097
3098 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3099 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3100 for (TestNetworkCallback c : emptyCallbacks) {
3101 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3102 mWiFiNetworkAgent);
3103 }
3104 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3105 mWiFiNetworkAgent);
3106 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3107 mWiFiNetworkAgent);
3108 assertNull(
3109 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3110 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003111 cBar.assertNoCallback();
3112
3113 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08003114 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003115 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3116 for (TestNetworkCallback c: emptyCallbacks) {
3117 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
3118 }
3119
Etan Cohen836ad572018-12-30 17:59:59 -08003120 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003121 }
3122
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003123 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003124 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003125 try {
3126 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003127 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
3128 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
3129 } catch (IllegalArgumentException expected) {
3130 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003131 }
3132
Etan Cohenddb9ef02015-11-18 10:56:15 -08003133 try {
3134 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3135 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003136 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003137 mService.requestNetwork(networkCapabilities, null, 0, null,
3138 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07003139 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
3140 } catch (IllegalArgumentException expected) {
3141 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003142 }
3143
Etan Cohena7434272017-04-03 12:17:51 -07003144 class NonParcelableSpecifier extends NetworkSpecifier {
3145 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3146 };
3147 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3148 @Override public int describeContents() { return 0; }
3149 @Override public void writeToParcel(Parcel p, int flags) {}
3150 }
3151 NetworkRequest.Builder builder;
3152
3153 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3154 try {
3155 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3156 Parcel parcelW = Parcel.obtain();
3157 builder.build().writeToParcel(parcelW, 0);
3158 fail("Parceling a non-parcelable specifier did not throw an exception");
3159 } catch (Exception e) {
3160 // expected
3161 }
3162
3163 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3164 builder.setNetworkSpecifier(new ParcelableSpecifier());
3165 NetworkRequest nr = builder.build();
3166 assertNotNull(nr);
3167
3168 try {
3169 Parcel parcelW = Parcel.obtain();
3170 nr.writeToParcel(parcelW, 0);
3171 byte[] bytes = parcelW.marshall();
3172 parcelW.recycle();
3173
3174 Parcel parcelR = Parcel.obtain();
3175 parcelR.unmarshall(bytes, 0, bytes.length);
3176 parcelR.setDataPosition(0);
3177 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3178 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
3179 } catch (Exception e) {
3180 // expected
3181 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08003182 }
3183
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003184 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07003185 public void testNetworkSpecifierUidSpoofSecurityException() {
3186 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3187 @Override
3188 public boolean satisfiedBy(NetworkSpecifier other) {
3189 return true;
3190 }
3191
3192 @Override
3193 public void assertValidFromUid(int requestorUid) {
3194 throw new SecurityException("failure");
3195 }
3196
3197 @Override
3198 public int describeContents() { return 0; }
3199 @Override
3200 public void writeToParcel(Parcel dest, int flags) {}
3201 }
3202
3203 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3204 mWiFiNetworkAgent.connect(false);
3205
3206 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3207 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3208 networkSpecifier).build();
3209 TestNetworkCallback networkCallback = new TestNetworkCallback();
3210 try {
3211 mCm.requestNetwork(networkRequest, networkCallback);
3212 fail("Network request with spoofed UID did not throw a SecurityException");
3213 } catch (SecurityException e) {
3214 // expected
3215 }
3216 }
3217
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003218 @Test
paulhu3d67f532019-03-22 16:35:06 +08003219 public void testInvalidSignalStrength() {
3220 NetworkRequest r = new NetworkRequest.Builder()
3221 .addCapability(NET_CAPABILITY_INTERNET)
3222 .addTransportType(TRANSPORT_WIFI)
3223 .setSignalStrength(-75)
3224 .build();
3225 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3226 // permission should get SecurityException.
3227 try {
3228 mCm.registerNetworkCallback(r, new NetworkCallback());
3229 fail("Expected SecurityException filing a callback with signal strength");
3230 } catch (SecurityException expected) {
3231 // expected
3232 }
3233
3234 try {
3235 mCm.registerNetworkCallback(r, PendingIntent.getService(
3236 mServiceContext, 0, new Intent(), 0));
3237 fail("Expected SecurityException filing a callback with signal strength");
3238 } catch (SecurityException expected) {
3239 // expected
3240 }
3241
3242 // Requesting a Network with signal strength should get IllegalArgumentException.
3243 try {
3244 mCm.requestNetwork(r, new NetworkCallback());
3245 fail("Expected IllegalArgumentException filing a request with signal strength");
3246 } catch (IllegalArgumentException expected) {
3247 // expected
3248 }
3249
3250 try {
3251 mCm.requestNetwork(r, PendingIntent.getService(
3252 mServiceContext, 0, new Intent(), 0));
3253 fail("Expected IllegalArgumentException filing a request with signal strength");
3254 } catch (IllegalArgumentException expected) {
3255 // expected
3256 }
3257 }
3258
3259 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003260 public void testRegisterDefaultNetworkCallback() throws Exception {
3261 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3262 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3263 defaultNetworkCallback.assertNoCallback();
3264
3265 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3266 // whenever Wi-Fi is up. Without this, the mobile network agent is
3267 // reaped before any other activity can take place.
3268 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3269 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3270 .addTransportType(TRANSPORT_CELLULAR).build();
3271 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3272 cellNetworkCallback.assertNoCallback();
3273
3274 // Bring up cell and expect CALLBACK_AVAILABLE.
3275 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3276 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003277 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3278 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003279 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003280
3281 // Bring up wifi and expect CALLBACK_AVAILABLE.
3282 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3283 mWiFiNetworkAgent.connect(true);
3284 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003285 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003286 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003287
3288 // Bring down cell. Expect no default network callback, since it wasn't the default.
3289 mCellNetworkAgent.disconnect();
3290 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3291 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003292 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003293
3294 // Bring up cell. Expect no default network callback, since it won't be the default.
3295 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3296 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003297 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003298 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003299 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003300
3301 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3302 // followed by AVAILABLE cell.
3303 mWiFiNetworkAgent.disconnect();
3304 cellNetworkCallback.assertNoCallback();
3305 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003306 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003307 mCellNetworkAgent.disconnect();
3308 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3309 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003310 waitForIdle();
3311 assertEquals(null, mCm.getActiveNetwork());
3312
3313 final int uid = Process.myUid();
3314 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3315 final ArraySet<UidRange> ranges = new ArraySet<>();
3316 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003317 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3318 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003319 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003320 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003321 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3322 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3323
3324 vpnNetworkAgent.disconnect();
3325 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3326 waitForIdle();
3327 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003328 }
3329
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003330 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003331 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003332 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003333 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003334 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3335 .addTransportType(TRANSPORT_CELLULAR).build();
3336 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3337
3338 // Bring up the mobile network.
3339 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3340 mCellNetworkAgent.connect(true);
3341
Erik Kline1d3db322017-02-28 16:20:20 +09003342 // We should get onAvailable(), onCapabilitiesChanged(), and
3343 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3344 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003345 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003346 cellNetworkCallback.assertNoCallback();
3347
3348 // Update LinkProperties.
3349 final LinkProperties lp = new LinkProperties();
3350 lp.setInterfaceName("foonet_data0");
3351 mCellNetworkAgent.sendLinkProperties(lp);
3352 // We should get onLinkPropertiesChanged().
3353 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3354 cellNetworkCallback.assertNoCallback();
3355
Erik Kline1d3db322017-02-28 16:20:20 +09003356 // Suspend the network.
3357 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003358 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3359 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003360 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3361 cellNetworkCallback.assertNoCallback();
3362
Erik Klineacdd6392016-07-07 16:50:58 +09003363 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003364 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003365 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003366 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3367 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003368 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003369 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003370 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3371
3372 mCellNetworkAgent.resume();
3373 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3374 mCellNetworkAgent);
3375 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3376 cellNetworkCallback.assertNoCallback();
3377
3378 dfltNetworkCallback = new TestNetworkCallback();
3379 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3380 // This time onNetworkSuspended should not be called.
3381 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3382 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003383
Erik Klineacdd6392016-07-07 16:50:58 +09003384 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3385 mCm.unregisterNetworkCallback(cellNetworkCallback);
3386 }
3387
Calvin On1f64f3f2016-10-11 15:10:46 -07003388 private void setCaptivePortalMode(int mode) {
3389 ContentResolver cr = mServiceContext.getContentResolver();
3390 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3391 }
3392
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003393 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003394 ContentResolver cr = mServiceContext.getContentResolver();
3395 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003396 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003397 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003398 }
3399
Erik Kline79c6d052018-03-21 07:18:33 -07003400 private void setPrivateDnsSettings(String mode, String specifier) {
3401 final ContentResolver cr = mServiceContext.getContentResolver();
3402 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3403 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3404 mService.updatePrivateDnsSettings();
3405 waitForIdle();
3406 }
3407
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003408 private boolean isForegroundNetwork(MockNetworkAgent network) {
3409 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3410 assertNotNull(nc);
3411 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3412 }
3413
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003414 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003415 public void testBackgroundNetworks() throws Exception {
3416 // Create a background request. We can't do this ourselves because ConnectivityService
3417 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003418 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003419 final NetworkRequest request = new NetworkRequest.Builder().build();
3420 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3421 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3422 final TestNetworkCallback callback = new TestNetworkCallback();
3423 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3424 mCm.registerNetworkCallback(request, callback);
3425 mCm.registerNetworkCallback(fgRequest, fgCallback);
3426
3427 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3428 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003429 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3430 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003431 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3432
3433 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3434 mWiFiNetworkAgent.connect(true);
3435
3436 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003437 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003438 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003439 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003440 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003441 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003442 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003443 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3444 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3445
3446 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003447 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003448 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3449 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003450 // Expect a network capabilities update sans FOREGROUND.
3451 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003452 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3453 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3454
3455 // File a cell request and check that cell comes into the foreground.
3456 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3457 .addTransportType(TRANSPORT_CELLULAR).build();
3458 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3459 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003460 // NOTE: This request causes the network's capabilities to change. This
3461 // is currently delivered before the onAvailable() callbacks.
3462 // TODO: Fix this.
3463 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003464 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3465 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003466 // Expect a network capabilities update with FOREGROUND, because the most recent
3467 // request causes its state to change.
3468 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003469 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3470 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3471
3472 // Release the request. The network immediately goes into the background, since it was not
3473 // lingering.
3474 mCm.unregisterNetworkCallback(cellCallback);
3475 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003476 // Expect a network capabilities update sans FOREGROUND.
3477 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003478 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3479 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3480
3481 // Disconnect wifi and check that cell is foreground again.
3482 mWiFiNetworkAgent.disconnect();
3483 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3484 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003485 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003486 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3487
3488 mCm.unregisterNetworkCallback(callback);
3489 mCm.unregisterNetworkCallback(fgCallback);
3490 }
3491
Hugo Benichi849b81b2017-05-25 13:42:31 +09003492 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003493 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003494 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003495 // Benchmarks connecting and switching performance in the presence of a large number of
3496 // NetworkRequests.
3497 // 1. File NUM_REQUESTS requests.
3498 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3499 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3500 // and NUM_REQUESTS onAvailable callbacks to fire.
3501 // See how long it took.
3502 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003503 final int REGISTER_TIME_LIMIT_MS = 200;
3504 final int CONNECT_TIME_LIMIT_MS = 60;
3505 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003506 final int UNREGISTER_TIME_LIMIT_MS = 20;
3507
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003508 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3509 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3510 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3511 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3512
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003513 for (int i = 0; i < NUM_REQUESTS; i++) {
3514 callbacks[i] = new NetworkCallback() {
3515 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3516 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3517 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003518 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003519
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003520 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3521 for (NetworkCallback cb : callbacks) {
3522 mCm.registerNetworkCallback(request, cb);
3523 }
3524 });
3525
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003526 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3527 // Don't request that the network validate, because otherwise connect() will block until
3528 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3529 // and we won't actually measure anything.
3530 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003531
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003532 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003533 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003534 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003535 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3536 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3537 onAvailableDispatchingDuration));
3538 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3539 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3540 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003541
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003542 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003543 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003544 mWiFiNetworkAgent.adjustScore(40);
3545 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003546
3547 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003548 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003549 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003550 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3551 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3552 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3553 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3554 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003555
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003556 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3557 for (NetworkCallback cb : callbacks) {
3558 mCm.unregisterNetworkCallback(cb);
3559 }
3560 });
3561 }
3562
3563 private long durationOf(Runnable fn) {
3564 long startTime = SystemClock.elapsedRealtime();
3565 fn.run();
3566 return SystemClock.elapsedRealtime() - startTime;
3567 }
3568
3569 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3570 long timeTaken = durationOf(fn);
3571 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003572 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003573 assertTrue(msg, timeTaken <= timeLimit);
3574 }
3575
3576 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3577 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003578 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003579 } catch (InterruptedException e) {}
3580 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003581 }
3582
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003583 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003584 public void testMobileDataAlwaysOn() throws Exception {
3585 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3586 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3587 .addTransportType(TRANSPORT_CELLULAR).build();
3588 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3589
3590 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3591 handlerThread.start();
3592 NetworkCapabilities filter = new NetworkCapabilities()
3593 .addTransportType(TRANSPORT_CELLULAR)
3594 .addCapability(NET_CAPABILITY_INTERNET);
3595 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3596 mServiceContext, "testFactory", filter);
3597 testFactory.setScoreFilter(40);
3598
3599 // Register the factory and expect it to start looking for a network.
Chalard Jean08577fc2018-05-02 21:14:54 +09003600 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003601 testFactory.register();
3602 testFactory.waitForNetworkRequests(1);
3603 assertTrue(testFactory.getMyStartRequested());
3604
3605 // Bring up wifi. The factory stops looking for a network.
3606 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chalard Jean08577fc2018-05-02 21:14:54 +09003607 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3608 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003609 mWiFiNetworkAgent.connect(true);
Chalard Jean08577fc2018-05-02 21:14:54 +09003610 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003611 assertFalse(testFactory.getMyStartRequested());
3612
3613 ContentResolver cr = mServiceContext.getContentResolver();
3614
3615 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean08577fc2018-05-02 21:14:54 +09003616 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003617 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003618 testFactory.waitForNetworkRequests(2);
3619 assertTrue(testFactory.getMyStartRequested());
3620
3621 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003622 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003623 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Chalard Jean08577fc2018-05-02 21:14:54 +09003624 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003625 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003626 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003627 testFactory.waitForNetworkRequests(2);
3628 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3629
3630 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003631 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003632 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003633 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003634
3635 // Turn off mobile data always on and expect the request to disappear...
3636 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003637 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003638 testFactory.waitForNetworkRequests(1);
3639
3640 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003641 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003642 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003643
3644 testFactory.unregister();
3645 mCm.unregisterNetworkCallback(cellNetworkCallback);
3646 handlerThread.quit();
3647 }
3648
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003649 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003650 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003651 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003652 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003653 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3654
Erik Kline065ab6e2016-10-02 18:02:14 +09003655 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003656 String[] values = new String[] {null, "0", "1"};
3657 for (int i = 0; i < values.length; i++) {
3658 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003659 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003660 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003661 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003662 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003663 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003664 }
3665
Erik Kline065ab6e2016-10-02 18:02:14 +09003666 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003667
3668 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003669 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003670 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003671 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003672 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003673
3674 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003675 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003676 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003677 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003678 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003679
3680 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003681 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003682 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003683 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003684 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003685 }
3686
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003687 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003688 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003689 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003690 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003691
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003692 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003693 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003694
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003695 // File a request for cell to ensure it doesn't go down.
3696 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3697 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3698 .addTransportType(TRANSPORT_CELLULAR).build();
3699 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3700
3701 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3702 mCm.registerDefaultNetworkCallback(defaultCallback);
3703
3704 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3705 .addTransportType(TRANSPORT_WIFI)
3706 .addCapability(NET_CAPABILITY_VALIDATED)
3707 .build();
3708 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3709 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3710
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003711 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003712 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003713
3714 // Bring up validated cell.
3715 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3716 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003717 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3718 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003719 Network cellNetwork = mCellNetworkAgent.getNetwork();
3720
3721 // Bring up validated wifi.
3722 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3723 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003724 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3725 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003726 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3727
3728 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003729 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003730 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003731 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003732 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3733
3734 // Because avoid bad wifi is off, we don't switch to cellular.
3735 defaultCallback.assertNoCallback();
3736 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3737 NET_CAPABILITY_VALIDATED));
3738 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3739 NET_CAPABILITY_VALIDATED));
3740 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3741
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003742 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3743 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003744 tracker.configRestrictsAvoidBadWifi = false;
3745 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003746 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003747 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3748
3749 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003750 tracker.configRestrictsAvoidBadWifi = true;
3751 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003752 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003753 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3754
3755 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3756 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003757 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003758 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3759 NET_CAPABILITY_VALIDATED));
3760 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3761 NET_CAPABILITY_VALIDATED));
3762 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3763
3764 // Disconnect and reconnect wifi to clear the one-time switch above.
3765 mWiFiNetworkAgent.disconnect();
3766 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3767 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003768 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3769 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003770 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3771
3772 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003773 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003774 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003775 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003776 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3777
3778 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003779 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003780 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003781
3782 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003783 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003784 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3785 NET_CAPABILITY_VALIDATED));
3786 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3787 NET_CAPABILITY_VALIDATED));
3788 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3789
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003790 // Simulate the user turning the cellular fallback setting off and then on.
3791 // We switch to wifi and then to cell.
3792 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003793 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003794 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003795 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3796 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003797 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003798 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003799 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3800
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003801 // If cell goes down, we switch to wifi.
3802 mCellNetworkAgent.disconnect();
3803 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003804 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003805 validatedWifiCallback.assertNoCallback();
3806
3807 mCm.unregisterNetworkCallback(cellNetworkCallback);
3808 mCm.unregisterNetworkCallback(validatedWifiCallback);
3809 mCm.unregisterNetworkCallback(defaultCallback);
3810 }
3811
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003812 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003813 public void testMeteredMultipathPreferenceSetting() throws Exception {
3814 final ContentResolver cr = mServiceContext.getContentResolver();
3815 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3816 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3817
3818 for (int config : Arrays.asList(0, 3, 2)) {
3819 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3820 tracker.configMeteredMultipathPreference = config;
3821 Settings.Global.putString(cr, settingName, setting);
3822 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003823 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003824
3825 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3826 String msg = String.format("config=%d, setting=%s", config, setting);
3827 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3828 }
3829 }
3830 }
3831
Erik Kline3841a482015-11-25 12:49:38 +09003832 /**
3833 * Validate that a satisfied network request does not trigger onUnavailable() once the
3834 * time-out period expires.
3835 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003836 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003837 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3838 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3839 NetworkCapabilities.TRANSPORT_WIFI).build();
3840 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003841 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003842
3843 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3844 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003845 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003846 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003847
3848 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003849 networkCallback.assertNoCallback();
3850 }
3851
3852 /**
3853 * Validate that a satisfied network request followed by a disconnected (lost) network does
3854 * not trigger onUnavailable() once the time-out period expires.
3855 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003856 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003857 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3858 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3859 NetworkCapabilities.TRANSPORT_WIFI).build();
3860 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003861 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003862
3863 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3864 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003865 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003866 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003867 mWiFiNetworkAgent.disconnect();
3868 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3869
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003870 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003871 networkCallback.assertNoCallback();
3872 }
3873
3874 /**
3875 * Validate that when a time-out is specified for a network request the onUnavailable()
3876 * callback is called when time-out expires. Then validate that if network request is
3877 * (somehow) satisfied - the callback isn't called later.
3878 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003879 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003880 public void testTimedoutNetworkRequest() {
3881 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3882 NetworkCapabilities.TRANSPORT_WIFI).build();
3883 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003884 final int timeoutMs = 10;
3885 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003886
3887 // pass timeout and validate that UNAVAILABLE is called
3888 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3889
3890 // create a network satisfying request - validate that request not triggered
3891 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3892 mWiFiNetworkAgent.connect(false);
3893 networkCallback.assertNoCallback();
3894 }
3895
3896 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003897 * Validate that when a network request is unregistered (cancelled), no posterior event can
3898 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003899 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003900 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003901 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003902 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3903 NetworkCapabilities.TRANSPORT_WIFI).build();
3904 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003905 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003906
Hugo Benichidfb559a2016-12-20 14:57:49 +09003907 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003908 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003909 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3910 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003911 networkCallback.assertNoCallback();
3912
3913 // create a network satisfying request - validate that request not triggered
3914 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3915 mWiFiNetworkAgent.connect(false);
3916 networkCallback.assertNoCallback();
3917 }
3918
Etan Cohen46c23572019-05-22 09:17:33 -07003919 @Test
3920 public void testUnfulfillableNetworkRequest() throws Exception {
3921 runUnfulfillableNetworkRequest(false);
3922 }
3923
3924 @Test
3925 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3926 runUnfulfillableNetworkRequest(true);
3927 }
3928
Etan Cohenae574a82019-01-08 12:09:18 -08003929 /**
3930 * Validate the callback flow for a factory releasing a request as unfulfillable.
3931 */
Etan Cohen46c23572019-05-22 09:17:33 -07003932 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenae574a82019-01-08 12:09:18 -08003933 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3934 NetworkCapabilities.TRANSPORT_WIFI).build();
3935 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3936
3937 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3938 handlerThread.start();
3939 NetworkCapabilities filter = new NetworkCapabilities()
3940 .addTransportType(TRANSPORT_WIFI)
3941 .addCapability(NET_CAPABILITY_INTERNET);
3942 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3943 mServiceContext, "testFactory", filter);
3944 testFactory.setScoreFilter(40);
3945
3946 // Register the factory and expect it to receive the default request.
3947 testFactory.expectAddRequestsWithScores(0);
3948 testFactory.register();
3949 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3950
3951 assertEquals(1, requests.size()); // have 1 request at this point
3952 int origRequestId = requests.valueAt(0).requestId;
3953
3954 // Now file the test request and expect it.
3955 testFactory.expectAddRequestsWithScores(0);
3956 mCm.requestNetwork(nr, networkCallback);
3957 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3958
3959 int newRequestId = 0;
3960 for (int i = 0; i < requests.size(); ++i) {
3961 if (requests.valueAt(i).requestId != origRequestId) {
3962 newRequestId = requests.valueAt(i).requestId;
3963 break;
3964 }
3965 }
3966
Etan Cohen9869b472019-05-23 09:16:26 -07003967 testFactory.expectRemoveRequests(1);
Etan Cohen46c23572019-05-22 09:17:33 -07003968 if (preUnregister) {
3969 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenae574a82019-01-08 12:09:18 -08003970
Etan Cohen46c23572019-05-22 09:17:33 -07003971 // Simulate the factory releasing the request as unfulfillable: no-op since
3972 // the callback has already been unregistered (but a test that no exceptions are
3973 // thrown).
3974 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3975 } else {
3976 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen46c23572019-05-22 09:17:33 -07003977 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3978
3979 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3980 testFactory.waitForRequests();
3981
3982 // unregister network callback - a no-op (since already freed by the
3983 // on-unavailable), but should not fail or throw exceptions.
3984 mCm.unregisterNetworkCallback(networkCallback);
3985 }
Etan Cohen5acedec2019-04-16 15:07:55 -07003986
Etan Cohenae574a82019-01-08 12:09:18 -08003987 testFactory.unregister();
3988 handlerThread.quit();
3989 }
3990
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003991 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3992
3993 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3994
3995 private class CallbackValue {
3996 public CallbackType callbackType;
3997 public int error;
3998
3999 public CallbackValue(CallbackType type) {
4000 this.callbackType = type;
4001 this.error = PacketKeepalive.SUCCESS;
4002 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
4003 }
4004
4005 public CallbackValue(CallbackType type, int error) {
4006 this.callbackType = type;
4007 this.error = error;
4008 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
4009 }
4010
4011 @Override
4012 public boolean equals(Object o) {
4013 return o instanceof CallbackValue &&
4014 this.callbackType == ((CallbackValue) o).callbackType &&
4015 this.error == ((CallbackValue) o).error;
4016 }
4017
4018 @Override
4019 public String toString() {
4020 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
4021 }
4022 }
4023
junyulai7c469172019-01-16 20:23:34 +08004024 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004025
4026 @Override
4027 public void onStarted() {
4028 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4029 }
4030
4031 @Override
4032 public void onStopped() {
4033 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4034 }
4035
4036 @Override
4037 public void onError(int error) {
4038 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4039 }
4040
4041 private void expectCallback(CallbackValue callbackValue) {
4042 try {
4043 assertEquals(
4044 callbackValue,
4045 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4046 } catch (InterruptedException e) {
4047 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4048 }
4049 }
4050
4051 public void expectStarted() {
4052 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4053 }
4054
4055 public void expectStopped() {
4056 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4057 }
4058
4059 public void expectError(int error) {
4060 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4061 }
4062 }
4063
junyulai48eac1d42018-12-27 17:25:29 +08004064 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
4065
4066 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
4067
4068 private class CallbackValue {
4069 public CallbackType callbackType;
4070 public int error;
4071
4072 CallbackValue(CallbackType type) {
4073 this.callbackType = type;
4074 this.error = SocketKeepalive.SUCCESS;
4075 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
4076 }
4077
4078 CallbackValue(CallbackType type, int error) {
4079 this.callbackType = type;
4080 this.error = error;
4081 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
4082 }
4083
4084 @Override
4085 public boolean equals(Object o) {
4086 return o instanceof CallbackValue
4087 && this.callbackType == ((CallbackValue) o).callbackType
4088 && this.error == ((CallbackValue) o).error;
4089 }
4090
4091 @Override
4092 public String toString() {
4093 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
4094 error);
4095 }
4096 }
4097
4098 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08004099 private final Executor mExecutor;
4100
4101 TestSocketKeepaliveCallback(@NonNull Executor executor) {
4102 mExecutor = executor;
4103 }
junyulai48eac1d42018-12-27 17:25:29 +08004104
4105 @Override
4106 public void onStarted() {
4107 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4108 }
4109
4110 @Override
4111 public void onStopped() {
4112 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4113 }
4114
4115 @Override
4116 public void onError(int error) {
4117 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4118 }
4119
4120 private void expectCallback(CallbackValue callbackValue) {
4121 try {
4122 assertEquals(
4123 callbackValue,
4124 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4125 } catch (InterruptedException e) {
4126 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4127 }
4128 }
4129
4130 public void expectStarted() {
4131 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4132 }
4133
4134 public void expectStopped() {
4135 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4136 }
4137
4138 public void expectError(int error) {
4139 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4140 }
junyulai7c469172019-01-16 20:23:34 +08004141
4142 public void assertNoCallback() {
4143 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
4144 CallbackValue cv = mCallbacks.peek();
4145 assertNull("Unexpected callback: " + cv, cv);
4146 }
junyulai48eac1d42018-12-27 17:25:29 +08004147 }
4148
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004149 private Network connectKeepaliveNetwork(LinkProperties lp) {
4150 // Ensure the network is disconnected before we do anything.
4151 if (mWiFiNetworkAgent != null) {
4152 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4153 }
4154
4155 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4156 ConditionVariable cv = waitForConnectivityBroadcasts(1);
4157 mWiFiNetworkAgent.connect(true);
4158 waitFor(cv);
4159 verifyActiveNetwork(TRANSPORT_WIFI);
4160 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09004161 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004162 return mWiFiNetworkAgent.getNetwork();
4163 }
4164
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004165 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004166 public void testPacketKeepalives() throws Exception {
4167 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4168 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4169 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4170 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4171 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4172
Nathan Harold63dd8132018-02-14 13:09:45 -08004173 final int validKaInterval = 15;
4174 final int invalidKaInterval = 9;
4175
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004176 LinkProperties lp = new LinkProperties();
4177 lp.setInterfaceName("wlan12");
4178 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4179 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4180 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4181 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4182
4183 Network notMyNet = new Network(61234);
4184 Network myNet = connectKeepaliveNetwork(lp);
4185
4186 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4187 PacketKeepalive ka;
4188
4189 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004190 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004191 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4192
Nathan Harold63dd8132018-02-14 13:09:45 -08004193 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004194 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4195
Nathan Harold63dd8132018-02-14 13:09:45 -08004196 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004197 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4198
Nathan Harold63dd8132018-02-14 13:09:45 -08004199 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004200 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4201
Nathan Harold63dd8132018-02-14 13:09:45 -08004202 // NAT-T is only supported for IPv4.
4203 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4204 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004205
Nathan Harold63dd8132018-02-14 13:09:45 -08004206 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004207 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4208
Nathan Harold63dd8132018-02-14 13:09:45 -08004209 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004210 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4211
Nathan Harold63dd8132018-02-14 13:09:45 -08004212 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004213 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4214
Nathan Harold63dd8132018-02-14 13:09:45 -08004215 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004216 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4217
4218 // Check that a started keepalive can be stopped.
4219 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004220 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004221 callback.expectStarted();
4222 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
4223 ka.stop();
4224 callback.expectStopped();
4225
4226 // Check that deleting the IP address stops the keepalive.
4227 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004228 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004229 callback.expectStarted();
4230 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4231 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4232 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4233 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4234 mWiFiNetworkAgent.sendLinkProperties(lp);
4235
4236 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004237 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004238 callback.expectStarted();
4239 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004240 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004241 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4242
4243 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004244 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004245 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004246 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004247 ka.stop();
4248
4249 // Reconnect.
4250 myNet = connectKeepaliveNetwork(lp);
4251 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4252
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004253 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4254 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004255 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004256 callback.expectStarted();
4257
4258 // The second one gets slot 2.
4259 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4260 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004261 PacketKeepalive ka2 = mCm.startNattKeepalive(
4262 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004263 callback2.expectStarted();
4264
4265 // Now stop the first one and create a third. This also gets slot 1.
4266 ka.stop();
4267 callback.expectStopped();
4268
4269 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4270 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004271 PacketKeepalive ka3 = mCm.startNattKeepalive(
4272 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004273 callback3.expectStarted();
4274
4275 ka2.stop();
4276 callback2.expectStopped();
4277
4278 ka3.stop();
4279 callback3.expectStopped();
4280 }
Udam Sainib7c24872016-01-04 12:16:14 -08004281
junyulaiafe9b492019-03-19 18:50:23 +08004282 @FunctionalInterface
4283 private interface ThrowingConsumer<T> {
4284 void accept(T t) throws Exception;
4285 }
4286
Xiao Maa4637112019-02-07 15:03:57 +09004287 // Helper method to prepare the executor and run test
junyulaiafe9b492019-03-19 18:50:23 +08004288 private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
junyulaie4135282019-01-03 18:50:15 +08004289 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004290 final Executor executorInline = (Runnable r) -> r.run();
4291 functor.accept(executorSingleThread);
junyulaie4135282019-01-03 18:50:15 +08004292 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004293 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004294 }
junyulaie4135282019-01-03 18:50:15 +08004295
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004296 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004297 public void testNattSocketKeepalives() throws Exception {
4298 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4299 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulaie4135282019-01-03 18:50:15 +08004300 }
4301
4302 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004303 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulaie4135282019-01-03 18:50:15 +08004304 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004305 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004306 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4307 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4308 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4309 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4310 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4311
4312 final int validKaInterval = 15;
4313 final int invalidKaInterval = 9;
4314
4315 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004316 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4317 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004318
junyulai48eac1d42018-12-27 17:25:29 +08004319 LinkProperties lp = new LinkProperties();
4320 lp.setInterfaceName("wlan12");
4321 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4322 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4323 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4324 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4325
4326 Network notMyNet = new Network(61234);
4327 Network myNet = connectKeepaliveNetwork(lp);
4328
junyulai7c469172019-01-16 20:23:34 +08004329 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004330
4331 // Attempt to start keepalives with invalid parameters and check for errors.
4332 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004333 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4334 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4335 ka.start(validKaInterval);
4336 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4337 }
junyulai48eac1d42018-12-27 17:25:29 +08004338
4339 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004340 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4341 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4342 ka.start(invalidKaInterval);
4343 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4344 }
junyulai48eac1d42018-12-27 17:25:29 +08004345
4346 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004347 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4348 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4349 ka.start(validKaInterval);
4350 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4351 }
junyulai48eac1d42018-12-27 17:25:29 +08004352
4353 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004354 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4355 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4356 ka.start(validKaInterval);
4357 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4358 }
junyulai48eac1d42018-12-27 17:25:29 +08004359
4360 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004361 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4362 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4363 ka.start(validKaInterval);
4364 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4365 }
junyulai48eac1d42018-12-27 17:25:29 +08004366
4367 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004368 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4369 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4370 ka.start(validKaInterval);
4371 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4372 }
junyulai48eac1d42018-12-27 17:25:29 +08004373
4374 // Check that a started keepalive can be stopped.
4375 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004376 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4377 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4378 ka.start(validKaInterval);
4379 callback.expectStarted();
4380 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4381 ka.stop();
4382 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004383
junyulai0c666972019-03-04 22:45:36 +08004384 // Check that keepalive could be restarted.
4385 ka.start(validKaInterval);
4386 callback.expectStarted();
4387 ka.stop();
4388 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004389
junyulai0c666972019-03-04 22:45:36 +08004390 // Check that keepalive can be restarted without waiting for callback.
4391 ka.start(validKaInterval);
4392 callback.expectStarted();
4393 ka.stop();
4394 ka.start(validKaInterval);
4395 callback.expectStopped();
4396 callback.expectStarted();
4397 ka.stop();
4398 callback.expectStopped();
4399 }
junyulai7c469172019-01-16 20:23:34 +08004400
junyulai48eac1d42018-12-27 17:25:29 +08004401 // Check that deleting the IP address stops the keepalive.
4402 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004403 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4404 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4405 ka.start(validKaInterval);
4406 callback.expectStarted();
4407 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4408 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4409 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4410 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4411 mWiFiNetworkAgent.sendLinkProperties(lp);
4412 }
junyulai48eac1d42018-12-27 17:25:29 +08004413
4414 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004415 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4416 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4417 ka.start(validKaInterval);
4418 callback.expectStarted();
4419 mWiFiNetworkAgent.disconnect();
4420 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4421 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004422
junyulai0c666972019-03-04 22:45:36 +08004423 // ... and that stopping it after that has no adverse effects.
4424 waitForIdle();
4425 final Network myNetAlias = myNet;
4426 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4427 ka.stop();
4428 callback.assertNoCallback();
4429 }
junyulai48eac1d42018-12-27 17:25:29 +08004430
4431 // Reconnect.
4432 myNet = connectKeepaliveNetwork(lp);
4433 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4434
4435 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4436 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004437 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004438 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4439 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4440 ka.start(validKaInterval);
4441 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004442
junyulai0c666972019-03-04 22:45:36 +08004443 // The second one gets slot 2.
4444 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004445 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4446 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004447 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4448 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4449 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4450 ka2.start(validKaInterval);
4451 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004452
junyulai0c666972019-03-04 22:45:36 +08004453 ka.stop();
4454 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004455
junyulai0c666972019-03-04 22:45:36 +08004456 ka2.stop();
4457 callback2.expectStopped();
junyulaie4135282019-01-03 18:50:15 +08004458
junyulai0c666972019-03-04 22:45:36 +08004459 testSocket.close();
4460 testSocket2.close();
4461 }
4462 }
junyulaie4135282019-01-03 18:50:15 +08004463
junyulai15178152019-03-27 11:00:37 +08004464 // Check that there is no port leaked after all keepalives and sockets are closed.
Junyu Laifd850fd2019-04-15 23:00:02 -07004465 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4466 // assertFalse(isUdpPortInUse(srcPort));
4467 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004468
junyulaie4135282019-01-03 18:50:15 +08004469 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004470 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Xiao Maa4637112019-02-07 15:03:57 +09004471 mWiFiNetworkAgent = null;
4472 }
4473
4474 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004475 public void testTcpSocketKeepalives() throws Exception {
4476 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004477 }
4478
4479 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4480 final int srcPortV4 = 12345;
4481 final int srcPortV6 = 23456;
4482 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4483 final InetAddress myIPv6 = InetAddress.getByName("::1");
4484
4485 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004486
4487 final LinkProperties lp = new LinkProperties();
4488 lp.setInterfaceName("wlan12");
4489 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4490 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4491 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4492 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4493
4494 final Network notMyNet = new Network(61234);
4495 final Network myNet = connectKeepaliveNetwork(lp);
4496
4497 final Socket testSocketV4 = new Socket();
4498 final Socket testSocketV6 = new Socket();
4499
junyulai7c469172019-01-16 20:23:34 +08004500 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004501
4502 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4503 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004504 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4505 notMyNet, testSocketV4, executor, callback)) {
4506 ka.start(validKaInterval);
4507 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4508 }
Xiao Maa4637112019-02-07 15:03:57 +09004509
4510 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004511 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4512 myNet, testSocketV4, executor, callback)) {
4513 ka.start(validKaInterval);
4514 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4515 }
Xiao Maa4637112019-02-07 15:03:57 +09004516
4517 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004518 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4519 myNet, testSocketV6, executor, callback)) {
4520 ka.start(validKaInterval);
4521 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4522 }
Xiao Maa4637112019-02-07 15:03:57 +09004523
4524 // Bind the socket address
4525 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4526 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4527
4528 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004529 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4530 myNet, testSocketV4, executor, callback)) {
4531 ka.start(validKaInterval);
4532 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4533 }
Xiao Maa4637112019-02-07 15:03:57 +09004534
4535 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004536 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4537 myNet, testSocketV6, executor, callback)) {
4538 ka.start(validKaInterval);
4539 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4540 }
Xiao Maa4637112019-02-07 15:03:57 +09004541
4542 testSocketV4.close();
4543 testSocketV6.close();
4544
4545 mWiFiNetworkAgent.disconnect();
4546 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4547 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004548 }
4549
junyulai0c666972019-03-04 22:45:36 +08004550 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004551 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4552 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4553 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4554 final int validKaInterval = 15;
4555
4556 // Prepare the target network.
4557 LinkProperties lp = new LinkProperties();
4558 lp.setInterfaceName("wlan12");
4559 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4560 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4561 Network myNet = connectKeepaliveNetwork(lp);
4562 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4563 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4564
4565 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4566
4567 // Prepare the target file descriptor, keep only one instance.
4568 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004569 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4570 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004571 final ParcelFileDescriptor testPfd =
4572 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4573 testSocket.close();
4574 assertTrue(isUdpPortInUse(srcPort));
4575
4576 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4577 // block.
4578 try (SocketKeepalive ka = mCm.createNattKeepalive(
4579 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4580 ka.start(validKaInterval);
4581 callback.expectStarted();
4582 ka.stop();
4583 callback.expectStopped();
4584 }
4585
4586 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4587 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4588 // address.
4589 assertTrue(isUdpPortInUse(srcPort));
4590 final InetSocketAddress sa =
4591 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4592 assertEquals(anyIPv4, sa.getAddress());
4593
4594 testPfd.close();
Junyu Laifd850fd2019-04-15 23:00:02 -07004595 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4596 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004597
4598 mWiFiNetworkAgent.disconnect();
4599 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4600 mWiFiNetworkAgent = null;
4601 }
4602
4603 private static boolean isUdpPortInUse(int port) {
4604 try (DatagramSocket ignored = new DatagramSocket(port)) {
4605 return false;
4606 } catch (IOException ignored) {
4607 return true;
4608 }
4609 }
4610
junyulai48eac1d42018-12-27 17:25:29 +08004611 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004612 public void testGetCaptivePortalServerUrl() throws Exception {
4613 String url = mCm.getCaptivePortalServerUrl();
4614 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4615 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004616
4617 private static class TestNetworkPinner extends NetworkPinner {
4618 public static boolean awaitPin(int timeoutMs) {
4619 synchronized(sLock) {
4620 if (sNetwork == null) {
4621 try {
4622 sLock.wait(timeoutMs);
4623 } catch (InterruptedException e) {}
4624 }
4625 return sNetwork != null;
4626 }
4627 }
4628
4629 public static boolean awaitUnpin(int timeoutMs) {
4630 synchronized(sLock) {
4631 if (sNetwork != null) {
4632 try {
4633 sLock.wait(timeoutMs);
4634 } catch (InterruptedException e) {}
4635 }
4636 return sNetwork == null;
4637 }
4638 }
4639 }
4640
4641 private void assertPinnedToWifiWithCellDefault() {
4642 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4643 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4644 }
4645
4646 private void assertPinnedToWifiWithWifiDefault() {
4647 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4648 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4649 }
4650
4651 private void assertNotPinnedToWifi() {
4652 assertNull(mCm.getBoundNetworkForProcess());
4653 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4654 }
4655
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004656 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004657 public void testNetworkPinner() {
4658 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4659 .addTransportType(TRANSPORT_WIFI)
4660 .build();
4661 assertNull(mCm.getBoundNetworkForProcess());
4662
4663 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4664 assertNull(mCm.getBoundNetworkForProcess());
4665
4666 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4667 mCellNetworkAgent.connect(true);
4668 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4669 mWiFiNetworkAgent.connect(false);
4670
4671 // When wi-fi connects, expect to be pinned.
4672 assertTrue(TestNetworkPinner.awaitPin(100));
4673 assertPinnedToWifiWithCellDefault();
4674
4675 // Disconnect and expect the pin to drop.
4676 mWiFiNetworkAgent.disconnect();
4677 assertTrue(TestNetworkPinner.awaitUnpin(100));
4678 assertNotPinnedToWifi();
4679
4680 // Reconnecting does not cause the pin to come back.
4681 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4682 mWiFiNetworkAgent.connect(false);
4683 assertFalse(TestNetworkPinner.awaitPin(100));
4684 assertNotPinnedToWifi();
4685
4686 // Pinning while connected causes the pin to take effect immediately.
4687 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4688 assertTrue(TestNetworkPinner.awaitPin(100));
4689 assertPinnedToWifiWithCellDefault();
4690
4691 // Explicitly unpin and expect to use the default network again.
4692 TestNetworkPinner.unpin();
4693 assertNotPinnedToWifi();
4694
4695 // Disconnect cell and wifi.
4696 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4697 mCellNetworkAgent.disconnect();
4698 mWiFiNetworkAgent.disconnect();
4699 waitFor(cv);
4700
4701 // Pinning takes effect even if the pinned network is the default when the pin is set...
4702 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4703 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4704 mWiFiNetworkAgent.connect(false);
4705 assertTrue(TestNetworkPinner.awaitPin(100));
4706 assertPinnedToWifiWithWifiDefault();
4707
4708 // ... and is maintained even when that network is no longer the default.
4709 cv = waitForConnectivityBroadcasts(1);
4710 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4711 mCellNetworkAgent.connect(true);
4712 waitFor(cv);
4713 assertPinnedToWifiWithCellDefault();
4714 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004715
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004716 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004717 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004718 // We can only have 99 callbacks, because MultipathPolicyTracker is
4719 // already one of them.
4720 final int MAX_REQUESTS = 99;
4721 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004722 final int INTENTS = 10;
4723 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4724
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004725 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004726 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004727
Hugo Benichi893a7622017-09-29 09:34:08 +09004728 int j = 0;
4729 while (j++ < CALLBACKS / 2) {
4730 NetworkCallback cb = new NetworkCallback();
4731 mCm.requestNetwork(networkRequest, cb);
4732 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004733 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004734 while (j++ < CALLBACKS) {
4735 NetworkCallback cb = new NetworkCallback();
4736 mCm.registerNetworkCallback(networkRequest, cb);
4737 registered.add(cb);
4738 }
4739 j = 0;
4740 while (j++ < INTENTS / 2) {
4741 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4742 mCm.requestNetwork(networkRequest, pi);
4743 registered.add(pi);
4744 }
4745 while (j++ < INTENTS) {
4746 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4747 mCm.registerNetworkCallback(networkRequest, pi);
4748 registered.add(pi);
4749 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004750
Hugo Benichi893a7622017-09-29 09:34:08 +09004751 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004752 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004753 mCm.requestNetwork(networkRequest, new NetworkCallback());
4754 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004755 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004756 try {
4757 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4758 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4759 } catch (TooManyRequestsException expected) {}
4760 try {
4761 mCm.requestNetwork(networkRequest,
4762 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4763 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4764 } catch (TooManyRequestsException expected) {}
4765 try {
4766 mCm.registerNetworkCallback(networkRequest,
4767 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4768 fail("Registering " + MAX_REQUESTS
4769 + " PendingIntent callbacks did not throw exception");
4770 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004771
Hugo Benichi893a7622017-09-29 09:34:08 +09004772 for (Object o : registered) {
4773 if (o instanceof NetworkCallback) {
4774 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004775 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004776 if (o instanceof PendingIntent) {
4777 mCm.unregisterNetworkCallback((PendingIntent)o);
4778 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004779 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004780 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004781
4782 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4783 for (int i = 0; i < MAX_REQUESTS; i++) {
4784 NetworkCallback networkCallback = new NetworkCallback();
4785 mCm.requestNetwork(networkRequest, networkCallback);
4786 mCm.unregisterNetworkCallback(networkCallback);
4787 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004788 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004789
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004790 for (int i = 0; i < MAX_REQUESTS; i++) {
4791 NetworkCallback networkCallback = new NetworkCallback();
4792 mCm.registerNetworkCallback(networkRequest, networkCallback);
4793 mCm.unregisterNetworkCallback(networkCallback);
4794 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004795 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004796
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004797 for (int i = 0; i < MAX_REQUESTS; i++) {
4798 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004799 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004800 mCm.requestNetwork(networkRequest, pendingIntent);
4801 mCm.unregisterNetworkCallback(pendingIntent);
4802 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004803 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004804
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004805 for (int i = 0; i < MAX_REQUESTS; i++) {
4806 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004807 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004808 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4809 mCm.unregisterNetworkCallback(pendingIntent);
4810 }
4811 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004812
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004813 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004814 public void testNetworkInfoOfTypeNone() {
4815 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4816
4817 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004818 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004819 assertNull(mCm.getActiveNetworkInfo());
4820
4821 Network[] allNetworks = mCm.getAllNetworks();
4822 assertLength(1, allNetworks);
4823 Network network = allNetworks[0];
4824 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4825 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4826
4827 final NetworkRequest request =
4828 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4829 final TestNetworkCallback callback = new TestNetworkCallback();
4830 mCm.registerNetworkCallback(request, callback);
4831
Hugo Benichic1014502017-07-19 10:10:52 +09004832 // Bring up wifi aware network.
4833 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004834 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004835
4836 assertNull(mCm.getActiveNetworkInfo());
4837 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004838 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004839 // of this test. Fix it and uncomment the assert below.
4840 //assertEmpty(mCm.getAllNetworkInfo());
4841
Hugo Benichic1014502017-07-19 10:10:52 +09004842 // Disconnect wifi aware network.
4843 wifiAware.disconnect();
4844 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004845 mCm.unregisterNetworkCallback(callback);
4846
4847 verifyNoNetwork();
4848 if (broadcastCV.block(10)) {
4849 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4850 }
4851 }
4852
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004853 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004854 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4855 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4856 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4857 assertNull(mCm.getNetworkForType(TYPE_NONE));
4858 assertNull(mCm.getLinkProperties(TYPE_NONE));
4859 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4860
4861 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4862 IllegalArgumentException.class);
4863
4864 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4865 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4866 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4867 // TODO: let test context have configuration application target sdk version
4868 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4869 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4870 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4871 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4872 }
4873
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004874 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004875 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4876 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4877 .addTransportType(TRANSPORT_WIFI).build();
4878 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4879 mCm.registerNetworkCallback(networkRequest, networkCallback);
4880
4881 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004882 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004883 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4884 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4885 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4886 lp.addLinkAddress(myIpv4Address);
4887 lp.addRoute(myIpv4DefaultRoute);
4888
4889 // Verify direct routes are added when network agent is first registered in
4890 // ConnectivityService.
4891 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4892 networkAgent.connect(true);
4893 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4894 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4895 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4896 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004897 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004898 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4899 networkCallback.assertNoCallback();
4900 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4901 Arrays.asList(myIpv4DefaultRoute));
4902 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4903 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4904
4905 // Verify direct routes are added during subsequent link properties updates.
4906 LinkProperties newLp = new LinkProperties(lp);
4907 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4908 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4909 newLp.addLinkAddress(myIpv6Address1);
4910 newLp.addLinkAddress(myIpv6Address2);
4911 networkAgent.sendLinkProperties(newLp);
4912 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4913 networkCallback.assertNoCallback();
4914 checkDirectlyConnectedRoutes(cbi.arg,
4915 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4916 Arrays.asList(myIpv4DefaultRoute));
4917 mCm.unregisterNetworkCallback(networkCallback);
4918 }
4919
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004920 @Test
4921 public void testStatsIfacesChanged() throws Exception {
4922 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004923 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4924
Varun Anand02c50ef2019-02-07 14:13:13 -08004925 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4926 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4927
4928 LinkProperties cellLp = new LinkProperties();
4929 cellLp.setInterfaceName(MOBILE_IFNAME);
4930 LinkProperties wifiLp = new LinkProperties();
4931 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004932
4933 // Simple connection should have updated ifaces
4934 mCellNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004935 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004936 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004937 verify(mStatsService, atLeastOnce())
4938 .forceUpdateIfaces(
4939 eq(onlyCell),
Varun Anand02c50ef2019-02-07 14:13:13 -08004940 any(NetworkState[].class),
4941 eq(MOBILE_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00004942 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Lorenzo Colittic78da292018-01-19 00:50:48 +09004943 reset(mStatsService);
4944
4945 // Default network switch should update ifaces.
4946 mWiFiNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004947 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004948 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004949 assertEquals(wifiLp, mService.getActiveLinkProperties());
4950 verify(mStatsService, atLeastOnce())
4951 .forceUpdateIfaces(
4952 eq(onlyWifi),
Varun Anand02c50ef2019-02-07 14:13:13 -08004953 any(NetworkState[].class),
4954 eq(WIFI_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00004955 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Lorenzo Colittic78da292018-01-19 00:50:48 +09004956 reset(mStatsService);
4957
4958 // Disconnect should update ifaces.
4959 mWiFiNetworkAgent.disconnect();
4960 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004961 verify(mStatsService, atLeastOnce())
4962 .forceUpdateIfaces(
4963 eq(onlyCell),
Varun Anand02c50ef2019-02-07 14:13:13 -08004964 any(NetworkState[].class),
4965 eq(MOBILE_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00004966 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004967 reset(mStatsService);
4968
4969 // Metered change should update ifaces
4970 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4971 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004972 verify(mStatsService, atLeastOnce())
4973 .forceUpdateIfaces(
4974 eq(onlyCell),
Varun Anand02c50ef2019-02-07 14:13:13 -08004975 any(NetworkState[].class),
4976 eq(MOBILE_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00004977 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004978 reset(mStatsService);
4979
4980 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4981 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004982 verify(mStatsService, atLeastOnce())
4983 .forceUpdateIfaces(
4984 eq(onlyCell),
Varun Anand02c50ef2019-02-07 14:13:13 -08004985 any(NetworkState[].class),
4986 eq(MOBILE_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00004987 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004988 reset(mStatsService);
4989
4990 // Captive portal change shouldn't update ifaces
4991 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4992 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004993 verify(mStatsService, never())
4994 .forceUpdateIfaces(
4995 eq(onlyCell),
Varun Anand02c50ef2019-02-07 14:13:13 -08004996 any(NetworkState[].class),
4997 eq(MOBILE_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00004998 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004999 reset(mStatsService);
5000
5001 // Roaming change should update ifaces
5002 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
5003 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08005004 verify(mStatsService, atLeastOnce())
5005 .forceUpdateIfaces(
5006 eq(onlyCell),
Varun Anand02c50ef2019-02-07 14:13:13 -08005007 any(NetworkState[].class),
5008 eq(MOBILE_IFNAME));
Benedict Wongc9511e72019-06-12 17:46:31 +00005009 assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
Jeff Sharkey72f9c422017-10-27 17:22:59 -06005010 reset(mStatsService);
5011 }
5012
Erik Klinee89953b2018-01-11 16:11:10 +09005013 @Test
5014 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07005015 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07005016
5017 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08005018 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005019
Erik Klinee89953b2018-01-11 16:11:10 +09005020 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5021 waitForIdle();
Wayne Ma28417f42019-04-17 08:03:59 -07005022 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005023 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005024
5025 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07005026 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09005027 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5028 // "is-reachable" testing in order to not program netd with unreachable
5029 // nameservers that it might try repeated to validate.
5030 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07005031 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5032 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09005033 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07005034 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5035 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09005036 mCellNetworkAgent.sendLinkProperties(cellLp);
5037 mCellNetworkAgent.connect(false);
5038 waitForIdle();
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07005039
5040 verify(mMockDnsResolver, times(1)).createNetworkCache(
5041 eq(mCellNetworkAgent.getNetwork().netId));
5042 // CS tells dnsresolver about the empty DNS config for this network.
Wayne Ma28417f42019-04-17 08:03:59 -07005043 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005044 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005045
5046 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5047 mCellNetworkAgent.sendLinkProperties(cellLp);
5048 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005049 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005050 mResolverParamsParcelCaptor.capture());
5051 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5052 assertEquals(1, resolvrParams.servers.length);
5053 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07005054 // Opportunistic mode.
Wayne Ma28417f42019-04-17 08:03:59 -07005055 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08005056 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005057
5058 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5059 mCellNetworkAgent.sendLinkProperties(cellLp);
5060 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005061 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005062 mResolverParamsParcelCaptor.capture());
5063 resolvrParams = mResolverParamsParcelCaptor.getValue();
5064 assertEquals(2, resolvrParams.servers.length);
5065 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09005066 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07005067 // Opportunistic mode.
Wayne Ma28417f42019-04-17 08:03:59 -07005068 assertEquals(2, resolvrParams.tlsServers.length);
5069 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005070 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005071 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09005072
5073 final String TLS_SPECIFIER = "tls.example.com";
5074 final String TLS_SERVER6 = "2001:db8:53::53";
5075 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
5076 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005077 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
5078 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
5079
Erik Kline117e7f32018-03-04 21:01:01 +09005080 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005081 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005082 mResolverParamsParcelCaptor.capture());
5083 resolvrParams = mResolverParamsParcelCaptor.getValue();
5084 assertEquals(2, resolvrParams.servers.length);
5085 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09005086 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005087 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005088 }
5089
Erik Kline79c6d052018-03-21 07:18:33 -07005090 @Test
5091 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07005092 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08005093 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005094
5095 // The default on Android is opportunistic mode ("Automatic").
5096 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5097
dalyk1fcb7392018-03-05 12:42:22 -05005098 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5099 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5100 .addTransportType(TRANSPORT_CELLULAR).build();
5101 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5102
Erik Kline79c6d052018-03-21 07:18:33 -07005103 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5104 waitForIdle();
5105 // CS tells netd about the empty DNS config for this network.
Wayne Ma28417f42019-04-17 08:03:59 -07005106 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005107 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005108
5109 final LinkProperties cellLp = new LinkProperties();
5110 cellLp.setInterfaceName(MOBILE_IFNAME);
5111 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5112 // "is-reachable" testing in order to not program netd with unreachable
5113 // nameservers that it might try repeated to validate.
5114 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5115 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5116 MOBILE_IFNAME));
5117 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5118 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5119 MOBILE_IFNAME));
5120 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5121 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5122
5123 mCellNetworkAgent.sendLinkProperties(cellLp);
5124 mCellNetworkAgent.connect(false);
5125 waitForIdle();
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07005126 verify(mMockDnsResolver, times(1)).createNetworkCache(
5127 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08005128 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005129 mResolverParamsParcelCaptor.capture());
5130 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5131 assertEquals(2, resolvrParams.tlsServers.length);
5132 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005133 new String[]{"2001:db8::1", "192.0.2.1"}));
5134 // Opportunistic mode.
Wayne Ma28417f42019-04-17 08:03:59 -07005135 assertEquals(2, resolvrParams.tlsServers.length);
5136 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005137 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005138 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005139 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5140 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5141 mCellNetworkAgent);
5142 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5143 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005144 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005145 cellNetworkCallback.assertNoCallback();
5146 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5147 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07005148
5149 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005150 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005151 mResolverParamsParcelCaptor.capture());
5152 resolvrParams = mResolverParamsParcelCaptor.getValue();
5153 assertEquals(2, resolvrParams.servers.length);
5154 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005155 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005156 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005157 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005158
5159 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005160 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005161 mResolverParamsParcelCaptor.capture());
5162 resolvrParams = mResolverParamsParcelCaptor.getValue();
5163 assertEquals(2, resolvrParams.servers.length);
5164 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005165 new String[]{"2001:db8::1", "192.0.2.1"}));
Wayne Ma28417f42019-04-17 08:03:59 -07005166 assertEquals(2, resolvrParams.tlsServers.length);
5167 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005168 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005169 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005170 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005171
dalyk1fcb7392018-03-05 12:42:22 -05005172 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5173 // Can't test dns configuration for strict mode without properly mocking
5174 // out the DNS lookups, but can test that LinkProperties is updated.
5175 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5176 mCellNetworkAgent);
5177 cellNetworkCallback.assertNoCallback();
5178 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5179 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
5180 }
5181
5182 @Test
5183 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5184 // The default on Android is opportunistic mode ("Automatic").
5185 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5186
5187 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5188 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5189 .addTransportType(TRANSPORT_CELLULAR).build();
5190 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5191
5192 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5193 waitForIdle();
5194 LinkProperties lp = new LinkProperties();
5195 mCellNetworkAgent.sendLinkProperties(lp);
5196 mCellNetworkAgent.connect(false);
5197 waitForIdle();
5198 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5199 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5200 mCellNetworkAgent);
5201 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5202 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005203 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005204 cellNetworkCallback.assertNoCallback();
5205 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5206 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5207 Set<InetAddress> dnsServers = new HashSet<>();
5208 checkDnsServers(cbi.arg, dnsServers);
5209
5210 // Send a validation event for a server that is not part of the current
5211 // resolver config. The validation event should be ignored.
5212 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5213 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5214 cellNetworkCallback.assertNoCallback();
5215
5216 // Add a dns server to the LinkProperties.
5217 LinkProperties lp2 = new LinkProperties(lp);
5218 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5219 mCellNetworkAgent.sendLinkProperties(lp2);
5220 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5221 mCellNetworkAgent);
5222 cellNetworkCallback.assertNoCallback();
5223 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5224 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5225 dnsServers.add(InetAddress.getByName("145.100.185.16"));
5226 checkDnsServers(cbi.arg, dnsServers);
5227
5228 // Send a validation event containing a hostname that is not part of
5229 // the current resolver config. The validation event should be ignored.
5230 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5231 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5232 cellNetworkCallback.assertNoCallback();
5233
5234 // Send a validation event where validation failed.
5235 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5236 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5237 cellNetworkCallback.assertNoCallback();
5238
5239 // Send a validation event where validation succeeded for a server in
5240 // the current resolver config. A LinkProperties callback with updated
5241 // private dns fields should be sent.
5242 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5243 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5244 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5245 mCellNetworkAgent);
5246 cellNetworkCallback.assertNoCallback();
5247 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5248 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5249 checkDnsServers(cbi.arg, dnsServers);
5250
5251 // The private dns fields in LinkProperties should be preserved when
5252 // the network agent sends unrelated changes.
5253 LinkProperties lp3 = new LinkProperties(lp2);
5254 lp3.setMtu(1300);
5255 mCellNetworkAgent.sendLinkProperties(lp3);
5256 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5257 mCellNetworkAgent);
5258 cellNetworkCallback.assertNoCallback();
5259 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5260 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5261 checkDnsServers(cbi.arg, dnsServers);
5262 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5263
5264 // Removing the only validated server should affect the private dns
5265 // fields in LinkProperties.
5266 LinkProperties lp4 = new LinkProperties(lp3);
5267 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5268 mCellNetworkAgent.sendLinkProperties(lp4);
5269 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5270 mCellNetworkAgent);
5271 cellNetworkCallback.assertNoCallback();
5272 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5273 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5274 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5275 checkDnsServers(cbi.arg, dnsServers);
5276 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005277 }
5278
Rubin Xu1bb5c082017-09-05 18:40:49 +01005279 private void checkDirectlyConnectedRoutes(Object callbackObj,
5280 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5281 assertTrue(callbackObj instanceof LinkProperties);
5282 LinkProperties lp = (LinkProperties) callbackObj;
5283
5284 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5285 expectedRoutes.addAll(otherRoutes);
5286 for (LinkAddress address : linkAddresses) {
5287 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5288 // Duplicates in linkAddresses are considered failures
5289 assertTrue(expectedRoutes.add(localRoute));
5290 }
5291 List<RouteInfo> observedRoutes = lp.getRoutes();
5292 assertEquals(expectedRoutes.size(), observedRoutes.size());
5293 assertTrue(observedRoutes.containsAll(expectedRoutes));
5294 }
5295
dalyk1fcb7392018-03-05 12:42:22 -05005296 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5297 assertTrue(callbackObj instanceof LinkProperties);
5298 LinkProperties lp = (LinkProperties) callbackObj;
5299 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5300 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5301 }
5302
Hugo Benichifed512a2017-06-26 10:06:49 +09005303 private static <T> void assertEmpty(T[] ts) {
5304 int length = ts.length;
5305 assertEquals("expected empty array, but length was " + length, 0, length);
5306 }
5307
5308 private static <T> void assertLength(int expected, T[] got) {
5309 int length = got.length;
5310 assertEquals(String.format("expected array of length %s, but length was %s for %s",
5311 expected, length, Arrays.toString(got)), expected, length);
5312 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09005313
5314 private static <T> void assertException(Runnable block, Class<T> expected) {
5315 try {
5316 block.run();
5317 fail("Expected exception of type " + expected);
5318 } catch (Exception got) {
5319 if (!got.getClass().equals(expected)) {
5320 fail("Expected exception of type " + expected + " but got " + got);
5321 }
5322 return;
5323 }
5324 }
Chalard Jean0b214af2018-01-12 17:22:49 +09005325
5326 @Test
5327 public void testVpnNetworkActive() {
5328 final int uid = Process.myUid();
5329
5330 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005331 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005332 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5333 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005334 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005335 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5336 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5337 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005338 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5339 .addTransportType(TRANSPORT_WIFI).build();
5340 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005341 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005342 .addTransportType(TRANSPORT_VPN).build();
5343 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005344 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005345 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5346 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005347 mCm.registerDefaultNetworkCallback(defaultCallback);
5348 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005349
5350 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5351 mWiFiNetworkAgent.connect(false);
5352
5353 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005354 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005355 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005356 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005357 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005358 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005359
5360 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5361 final ArraySet<UidRange> ranges = new ArraySet<>();
5362 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005363 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5364 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005365 // VPN networks do not satisfy the default request and are automatically validated
5366 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09005367 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005368 vpnNetworkAgent.setNetworkValid();
5369
Chalard Jean0b214af2018-01-12 17:22:49 +09005370 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005371 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005372 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005373
5374 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005375 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005376 wifiNetworkCallback.assertNoCallback();
5377 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005378 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5379 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005380
5381 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005382 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09005383 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005384 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5385 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005386
5387 ranges.clear();
5388 vpnNetworkAgent.setUids(ranges);
5389
5390 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005391 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005392 wifiNetworkCallback.assertNoCallback();
5393 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5394
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005395 // TODO : The default network callback should actually get a LOST call here (also see the
5396 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5397 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5398 // can't currently update their UIDs without disconnecting, so this does not matter too
5399 // much, but that is the reason the test here has to check for an update to the
5400 // capabilities instead of the expected LOST then AVAILABLE.
5401 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5402
Chalard Jean0b214af2018-01-12 17:22:49 +09005403 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005404 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005405 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005406
5407 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005408 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005409 wifiNetworkCallback.assertNoCallback();
5410 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005411 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5412 // happen outside of the test, ConnectivityService does not rematch callbacks.
5413 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005414
5415 mWiFiNetworkAgent.disconnect();
5416
5417 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005418 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005419 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5420 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005421 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005422
5423 vpnNetworkAgent.disconnect();
5424
5425 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005426 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005427 wifiNetworkCallback.assertNoCallback();
5428 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005429 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5430 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005431
5432 mCm.unregisterNetworkCallback(genericNetworkCallback);
5433 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5434 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005435 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005436 }
Chalard Jean26400492018-04-18 20:18:38 +09005437
5438 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005439 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09005440 final int uid = Process.myUid();
5441
5442 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5443 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005444
5445 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5446 mWiFiNetworkAgent.connect(true);
5447
5448 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5449 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5450
5451 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5452 final ArraySet<UidRange> ranges = new ArraySet<>();
5453 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005454 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5455 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005456 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005457 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005458
5459 defaultCallback.assertNoCallback();
5460 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5461
5462 vpnNetworkAgent.disconnect();
5463 defaultCallback.assertNoCallback();
5464
Varun Anand4fa80e82019-02-06 10:13:38 -08005465 mCm.unregisterNetworkCallback(defaultCallback);
5466 }
5467
5468 @Test
5469 public void testVpnWithInternet() {
5470 final int uid = Process.myUid();
5471
5472 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5473 mCm.registerDefaultNetworkCallback(defaultCallback);
5474
5475 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5476 mWiFiNetworkAgent.connect(true);
5477
5478 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5479 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5480
5481 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5482 final ArraySet<UidRange> ranges = new ArraySet<>();
5483 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005484 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5485 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005486 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005487 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005488
Chalard Jean26400492018-04-18 20:18:38 +09005489 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5490 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5491
5492 vpnNetworkAgent.disconnect();
5493 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5494 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5495
Chalard Jean26400492018-04-18 20:18:38 +09005496 mCm.unregisterNetworkCallback(defaultCallback);
5497 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005498
5499 @Test
Chalard Jeanf9861102019-05-10 04:33:43 -07005500 public void testVpnUnvalidated() throws Exception {
5501 final TestNetworkCallback callback = new TestNetworkCallback();
5502 mCm.registerDefaultNetworkCallback(callback);
5503
5504 // Bring up Ethernet.
5505 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
5506 mEthernetNetworkAgent.connect(true);
5507 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5508 callback.assertNoCallback();
5509
5510 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5511 final int uid = Process.myUid();
5512 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5513 final ArraySet<UidRange> ranges = new ArraySet<>();
5514 ranges.add(new UidRange(uid, uid));
5515 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5516 mMockVpn.setUids(ranges);
5517 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
5518 mMockVpn.connect();
5519
5520 // Even though the VPN is unvalidated, it becomes the default network for our app.
5521 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5522 // TODO: this looks like a spurious callback.
5523 callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5524 callback.assertNoCallback();
5525
5526 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5527 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5528 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5529
5530 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5531 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5532 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5533
5534 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
5535 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
5536 vpnNetworkAgent.mNetworkCapabilities));
5537
5538 // Pretend that the VPN network validates.
5539 vpnNetworkAgent.setNetworkValid();
5540 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5541 // Expect to see the validated capability, but no other changes, because the VPN is already
5542 // the default network for the app.
5543 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5544 callback.assertNoCallback();
5545
5546 vpnNetworkAgent.disconnect();
5547 callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5548 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5549 }
5550
5551 @Test
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005552 public void testVpnSetUnderlyingNetworks() {
5553 final int uid = Process.myUid();
5554
5555 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5556 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5557 .removeCapability(NET_CAPABILITY_NOT_VPN)
5558 .addTransportType(TRANSPORT_VPN)
5559 .build();
5560 NetworkCapabilities nc;
5561 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5562 vpnNetworkCallback.assertNoCallback();
5563
5564 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5565 final ArraySet<UidRange> ranges = new ArraySet<>();
5566 ranges.add(new UidRange(uid, uid));
5567 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5568 mMockVpn.connect();
5569 mMockVpn.setUids(ranges);
5570 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5571
5572 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5573 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5574 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5575 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5576 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5577 // For safety reasons a VPN without underlying networks is considered metered.
5578 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5579
5580 // Connect cell and use it as an underlying network.
5581 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5582 mCellNetworkAgent.connect(true);
5583
5584 mService.setUnderlyingNetworksForVpn(
5585 new Network[] { mCellNetworkAgent.getNetwork() });
5586
5587 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5588 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5589 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5590 vpnNetworkAgent);
5591
5592 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5593 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5594 mWiFiNetworkAgent.connect(true);
5595
5596 mService.setUnderlyingNetworksForVpn(
5597 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5598
5599 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5600 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5601 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5602 vpnNetworkAgent);
5603
5604 // Don't disconnect, but note the VPN is not using wifi any more.
5605 mService.setUnderlyingNetworksForVpn(
5606 new Network[] { mCellNetworkAgent.getNetwork() });
5607
5608 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5609 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5610 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5611 vpnNetworkAgent);
5612
5613 // Use Wifi but not cell. Note the VPN is now unmetered.
5614 mService.setUnderlyingNetworksForVpn(
5615 new Network[] { mWiFiNetworkAgent.getNetwork() });
5616
5617 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5618 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5619 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5620 vpnNetworkAgent);
5621
5622 // Use both again.
5623 mService.setUnderlyingNetworksForVpn(
5624 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5625
5626 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5627 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5628 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5629 vpnNetworkAgent);
5630
Chalard Jean6b65ec72018-05-18 22:02:56 +09005631 // Disconnect cell. Receive update without even removing the dead network from the
5632 // underlying networks – it's dead anyway. Not metered any more.
5633 mCellNetworkAgent.disconnect();
5634 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5635 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5636 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5637 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005638
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005639 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005640 mWiFiNetworkAgent.disconnect();
5641 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5642 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005643 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09005644 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005645
5646 mMockVpn.disconnect();
5647 }
junyulai4a192e22018-06-13 15:00:37 +08005648
Mike Yuf9729752018-08-17 15:22:05 +08005649 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005650 public void testNullUnderlyingNetworks() {
5651 final int uid = Process.myUid();
5652
5653 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5654 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5655 .removeCapability(NET_CAPABILITY_NOT_VPN)
5656 .addTransportType(TRANSPORT_VPN)
5657 .build();
5658 NetworkCapabilities nc;
5659 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5660 vpnNetworkCallback.assertNoCallback();
5661
5662 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5663 final ArraySet<UidRange> ranges = new ArraySet<>();
5664 ranges.add(new UidRange(uid, uid));
5665 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5666 mMockVpn.connect();
5667 mMockVpn.setUids(ranges);
5668 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5669
5670 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5671 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5672 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5673 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5674 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5675 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5676 // In case of no default network, VPN is considered metered.
5677 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5678
5679 // Connect to Cell; Cell is the default network.
5680 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5681 mCellNetworkAgent.connect(true);
5682
5683 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5684 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5685 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5686 vpnNetworkAgent);
5687
5688 // Connect to WiFi; WiFi is the new default.
5689 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5690 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5691 mWiFiNetworkAgent.connect(true);
5692
5693 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5694 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5695 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5696 vpnNetworkAgent);
5697
5698 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5699 // the capabilities.
5700 mCellNetworkAgent.disconnect();
5701
5702 // Disconnect wifi too. Now we have no default network.
5703 mWiFiNetworkAgent.disconnect();
5704
5705 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5706 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5707 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5708 vpnNetworkAgent);
5709
5710 mMockVpn.disconnect();
5711 }
5712
5713 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005714 public void testIsActiveNetworkMeteredOverWifi() {
5715 // Returns true by default when no network is available.
5716 assertTrue(mCm.isActiveNetworkMetered());
5717 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5718 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5719 mWiFiNetworkAgent.connect(true);
5720 waitForIdle();
5721
5722 assertFalse(mCm.isActiveNetworkMetered());
5723 }
5724
5725 @Test
5726 public void testIsActiveNetworkMeteredOverCell() {
5727 // Returns true by default when no network is available.
5728 assertTrue(mCm.isActiveNetworkMetered());
5729 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5730 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5731 mCellNetworkAgent.connect(true);
5732 waitForIdle();
5733
5734 assertTrue(mCm.isActiveNetworkMetered());
5735 }
5736
5737 @Test
5738 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5739 // Returns true by default when no network is available.
5740 assertTrue(mCm.isActiveNetworkMetered());
5741 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5742 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5743 mCellNetworkAgent.connect(true);
5744 waitForIdle();
5745 assertTrue(mCm.isActiveNetworkMetered());
5746
5747 // Connect VPN network. By default it is using current default network (Cell).
5748 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5749 final ArraySet<UidRange> ranges = new ArraySet<>();
5750 final int uid = Process.myUid();
5751 ranges.add(new UidRange(uid, uid));
5752 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5753 mMockVpn.setUids(ranges);
5754 vpnNetworkAgent.connect(true);
5755 mMockVpn.connect();
5756 waitForIdle();
5757 // Ensure VPN is now the active network.
5758 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5759
5760 // Expect VPN to be metered.
5761 assertTrue(mCm.isActiveNetworkMetered());
5762
5763 // Connect WiFi.
5764 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5765 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5766 mWiFiNetworkAgent.connect(true);
5767 waitForIdle();
5768 // VPN should still be the active network.
5769 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5770
5771 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5772 assertFalse(mCm.isActiveNetworkMetered());
5773
5774 // Disconnecting Cell should not affect VPN's meteredness.
5775 mCellNetworkAgent.disconnect();
5776 waitForIdle();
5777
5778 assertFalse(mCm.isActiveNetworkMetered());
5779
5780 // Disconnect WiFi; Now there is no platform default network.
5781 mWiFiNetworkAgent.disconnect();
5782 waitForIdle();
5783
5784 // VPN without any underlying networks is treated as metered.
5785 assertTrue(mCm.isActiveNetworkMetered());
5786
5787 vpnNetworkAgent.disconnect();
5788 mMockVpn.disconnect();
5789 }
5790
5791 @Test
5792 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5793 // Returns true by default when no network is available.
5794 assertTrue(mCm.isActiveNetworkMetered());
5795 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5796 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5797 mCellNetworkAgent.connect(true);
5798 waitForIdle();
5799 assertTrue(mCm.isActiveNetworkMetered());
5800
5801 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5802 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5803 mWiFiNetworkAgent.connect(true);
5804 waitForIdle();
5805 assertFalse(mCm.isActiveNetworkMetered());
5806
5807 // Connect VPN network.
5808 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5809 final ArraySet<UidRange> ranges = new ArraySet<>();
5810 final int uid = Process.myUid();
5811 ranges.add(new UidRange(uid, uid));
5812 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5813 mMockVpn.setUids(ranges);
5814 vpnNetworkAgent.connect(true);
5815 mMockVpn.connect();
5816 waitForIdle();
5817 // Ensure VPN is now the active network.
5818 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5819 // VPN is using Cell
5820 mService.setUnderlyingNetworksForVpn(
5821 new Network[] { mCellNetworkAgent.getNetwork() });
5822 waitForIdle();
5823
5824 // Expect VPN to be metered.
5825 assertTrue(mCm.isActiveNetworkMetered());
5826
5827 // VPN is now using WiFi
5828 mService.setUnderlyingNetworksForVpn(
5829 new Network[] { mWiFiNetworkAgent.getNetwork() });
5830 waitForIdle();
5831
5832 // Expect VPN to be unmetered
5833 assertFalse(mCm.isActiveNetworkMetered());
5834
5835 // VPN is using Cell | WiFi.
5836 mService.setUnderlyingNetworksForVpn(
5837 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5838 waitForIdle();
5839
5840 // Expect VPN to be metered.
5841 assertTrue(mCm.isActiveNetworkMetered());
5842
5843 // VPN is using WiFi | Cell.
5844 mService.setUnderlyingNetworksForVpn(
5845 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5846 waitForIdle();
5847
5848 // Order should not matter and VPN should still be metered.
5849 assertTrue(mCm.isActiveNetworkMetered());
5850
5851 // VPN is not using any underlying networks.
5852 mService.setUnderlyingNetworksForVpn(new Network[0]);
5853 waitForIdle();
5854
5855 // VPN without underlying networks is treated as metered.
5856 assertTrue(mCm.isActiveNetworkMetered());
5857
5858 vpnNetworkAgent.disconnect();
5859 mMockVpn.disconnect();
5860 }
5861
5862 @Test
5863 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5864 // Returns true by default when no network is available.
5865 assertTrue(mCm.isActiveNetworkMetered());
5866 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5867 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5868 mWiFiNetworkAgent.connect(true);
5869 waitForIdle();
5870 assertFalse(mCm.isActiveNetworkMetered());
5871
5872 // Connect VPN network.
5873 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5874 final ArraySet<UidRange> ranges = new ArraySet<>();
5875 final int uid = Process.myUid();
5876 ranges.add(new UidRange(uid, uid));
5877 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5878 mMockVpn.setUids(ranges);
5879 vpnNetworkAgent.connect(true);
5880 mMockVpn.connectAsAlwaysMetered();
5881 waitForIdle();
5882 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5883
5884 // VPN is tracking current platform default (WiFi).
5885 mService.setUnderlyingNetworksForVpn(null);
5886 waitForIdle();
5887
5888 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5889 assertTrue(mCm.isActiveNetworkMetered());
5890
5891 // VPN explicitly declares WiFi as its underlying network.
5892 mService.setUnderlyingNetworksForVpn(
5893 new Network[] { mWiFiNetworkAgent.getNetwork() });
5894 waitForIdle();
5895
5896 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5897 assertTrue(mCm.isActiveNetworkMetered());
5898
5899 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5900 // anyways suppose to be metered.
5901 mWiFiNetworkAgent.disconnect();
5902 waitForIdle();
5903
5904 assertTrue(mCm.isActiveNetworkMetered());
5905
5906 vpnNetworkAgent.disconnect();
5907 }
5908
5909 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005910 public void testNetworkBlockedStatus() {
5911 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5912 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5913 .addTransportType(TRANSPORT_CELLULAR)
5914 .build();
5915 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5916
5917 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5918 mCellNetworkAgent.connect(true);
5919 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5920
5921 mService.setUidRulesChanged(RULE_REJECT_ALL);
5922 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5923
5924 // ConnectivityService should cache it not to invoke the callback again.
5925 mService.setUidRulesChanged(RULE_REJECT_METERED);
5926 cellNetworkCallback.assertNoCallback();
5927
5928 mService.setUidRulesChanged(RULE_NONE);
5929 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5930
5931 mService.setUidRulesChanged(RULE_REJECT_METERED);
5932 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5933
5934 // Restrict the network based on UID rule and NOT_METERED capability change.
5935 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5936 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5937 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5938 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5939 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5940 mCellNetworkAgent);
5941 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5942 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5943 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5944
5945 mService.setUidRulesChanged(RULE_NONE);
5946 cellNetworkCallback.assertNoCallback();
5947
5948 // Restrict the network based on BackgroundRestricted.
5949 mService.setRestrictBackgroundChanged(true);
5950 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5951 mService.setRestrictBackgroundChanged(true);
5952 cellNetworkCallback.assertNoCallback();
5953 mService.setRestrictBackgroundChanged(false);
5954 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5955 cellNetworkCallback.assertNoCallback();
5956
5957 mCm.unregisterNetworkCallback(cellNetworkCallback);
5958 }
5959
5960 @Test
5961 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5962 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5963 mCm.registerDefaultNetworkCallback(defaultCallback);
5964
5965 // No Networkcallbacks invoked before any network is active.
5966 mService.setUidRulesChanged(RULE_REJECT_ALL);
5967 mService.setUidRulesChanged(RULE_NONE);
5968 mService.setUidRulesChanged(RULE_REJECT_METERED);
5969 defaultCallback.assertNoCallback();
5970
5971 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5972 mCellNetworkAgent.connect(true);
5973 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5974 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5975
5976 // Allow to use the network after switching to NOT_METERED network.
5977 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5978 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5979 mWiFiNetworkAgent.connect(true);
5980 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5981
5982 // Switch to METERED network. Restrict the use of the network.
5983 mWiFiNetworkAgent.disconnect();
5984 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5985 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5986
5987 // Network becomes NOT_METERED.
5988 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5989 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5990 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5991
5992 // Verify there's no Networkcallbacks invoked after data saver on/off.
5993 mService.setRestrictBackgroundChanged(true);
5994 mService.setRestrictBackgroundChanged(false);
5995 defaultCallback.assertNoCallback();
5996
5997 mCellNetworkAgent.disconnect();
5998 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5999 defaultCallback.assertNoCallback();
6000
6001 mCm.unregisterNetworkCallback(defaultCallback);
6002 }
6003
junyulai4a192e22018-06-13 15:00:37 +08006004 /**
6005 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
6006 */
6007 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
6008 InterfaceConfiguration cfg = new InterfaceConfiguration();
6009 cfg.setHardwareAddress("11:22:33:44:55:66");
6010 cfg.setLinkAddress(la);
6011 return cfg;
6012 }
6013
6014 /**
6015 * Make expected stack link properties, copied from Nat464Xlat.
6016 */
6017 private LinkProperties makeClatLinkProperties(LinkAddress la) {
6018 LinkAddress clatAddress = la;
6019 LinkProperties stacked = new LinkProperties();
6020 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
6021 RouteInfo ipv4Default = new RouteInfo(
6022 new LinkAddress(Inet4Address.ANY, 0),
6023 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
6024 stacked.addRoute(ipv4Default);
6025 stacked.addLinkAddress(clatAddress);
6026 return stacked;
6027 }
6028
6029 @Test
6030 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
6031 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
6032 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006033 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
6034 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
6035
junyulai4a192e22018-06-13 15:00:37 +08006036 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6037 .addTransportType(TRANSPORT_CELLULAR)
6038 .addCapability(NET_CAPABILITY_INTERNET)
6039 .build();
6040 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6041 mCm.registerNetworkCallback(networkRequest, networkCallback);
6042
Lorenzo Colittid593e292019-02-19 13:21:56 +09006043 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08006044 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006045 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08006046 final LinkProperties cellLp = new LinkProperties();
6047 cellLp.setInterfaceName(MOBILE_IFNAME);
6048 cellLp.addLinkAddress(myIpv6);
6049 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
6050 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
6051 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006052 reset(mMockDnsResolver);
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07006053 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08006054 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6055 .thenReturn(getClatInterfaceConfig(myIpv4));
6056
Lorenzo Colittid593e292019-02-19 13:21:56 +09006057 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08006058 mCellNetworkAgent.sendLinkProperties(cellLp);
6059 mCellNetworkAgent.connect(true);
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07006060
6061 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
6062 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
6063
junyulai4a192e22018-06-13 15:00:37 +08006064 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006065 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006066
Lorenzo Colittid593e292019-02-19 13:21:56 +09006067 // Switching default network updates TCP buffer sizes.
6068 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6069
6070 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
6071 // the NAT64 prefix was removed because one was never discovered.
6072 cellLp.addLinkAddress(myIpv4);
6073 mCellNetworkAgent.sendLinkProperties(cellLp);
6074 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006075 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
Wayne Ma28417f42019-04-17 08:03:59 -07006076 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006077
6078 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006079 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006080 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006081 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006082
6083 // Remove IPv4 address. Expect prefix discovery to be started again.
6084 cellLp.removeLinkAddress(myIpv4);
6085 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6086 mCellNetworkAgent.sendLinkProperties(cellLp);
6087 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006088 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006089
6090 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006091 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
6092 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006093 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6094 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006095 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
6096 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
6097 assertEquals(0, lpBeforeClat.getStackedLinks().size());
6098 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6099 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6100
6101 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08006102 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006103 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006104 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6105 .getStackedLinks();
6106 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
6107
6108 // Change trivial linkproperties and see if stacked link is preserved.
6109 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6110 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006111 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6112
6113 List<LinkProperties> stackedLpsAfterChange =
6114 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6115 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6116 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6117
Luke Huang65914772019-03-16 00:31:46 +08006118 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07006119 mResolverParamsParcelCaptor.capture());
6120 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6121 assertEquals(1, resolvrParams.servers.length);
6122 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08006123
Lorenzo Colittid593e292019-02-19 13:21:56 +09006124 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6125 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08006126 cellLp.addLinkAddress(myIpv4);
6127 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6128 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006129 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09006130 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08006131 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006132
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006133 // As soon as stop is called, the linkproperties lose the stacked interface.
junyulai4a192e22018-06-13 15:00:37 +08006134 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6135 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006136 LinkProperties expected = new LinkProperties(cellLp);
6137 expected.setNat64Prefix(kNat64Prefix);
6138 assertEquals(expected, actualLpAfterIpv4);
6139 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
junyulai4a192e22018-06-13 15:00:37 +08006140
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006141 // The interface removed callback happens but has no effect after stop is called.
6142 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6143 networkCallback.assertNoCallback();
6144
Lorenzo Colittid593e292019-02-19 13:21:56 +09006145 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006146 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006147 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006148 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006149
Lorenzo Colittid593e292019-02-19 13:21:56 +09006150 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6151 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6152 kNat64PrefixString, 96);
6153 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
6154 mCellNetworkAgent);
6155
6156 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006157 cellLp.removeLinkAddress(myIpv4);
6158 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6159 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6160 mCellNetworkAgent.sendLinkProperties(cellLp);
6161 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006162 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006163 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6164 kNat64PrefixString, 96);
6165 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006166 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6167
Lorenzo Colittid593e292019-02-19 13:21:56 +09006168
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006169 // Clat iface comes up. Expect stacked link to be added.
6170 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006171 networkCallback.expectLinkPropertiesLike(
6172 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006173 mCellNetworkAgent);
6174
6175 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006176 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6177 kNat64PrefixString, 96);
6178 networkCallback.expectLinkPropertiesLike(
6179 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006180 mCellNetworkAgent);
6181 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6182 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
6183 mCellNetworkAgent);
6184
6185 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006186 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006187 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6188 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006189 mCm.unregisterNetworkCallback(networkCallback);
6190 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006191
6192 @Test
6193 public void testDataActivityTracking() throws RemoteException {
6194 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6195 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6196 .addCapability(NET_CAPABILITY_INTERNET)
6197 .build();
6198 mCm.registerNetworkCallback(networkRequest, networkCallback);
6199
6200 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6201 final LinkProperties cellLp = new LinkProperties();
6202 cellLp.setInterfaceName(MOBILE_IFNAME);
6203 mCellNetworkAgent.sendLinkProperties(cellLp);
6204 reset(mNetworkManagementService);
6205 mCellNetworkAgent.connect(true);
6206 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6207 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6208 eq(ConnectivityManager.TYPE_MOBILE));
6209
6210 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6211 final LinkProperties wifiLp = new LinkProperties();
6212 wifiLp.setInterfaceName(WIFI_IFNAME);
6213 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6214
6215 // Network switch
6216 reset(mNetworkManagementService);
6217 mWiFiNetworkAgent.connect(true);
6218 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6219 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6220 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6221 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6222 eq(ConnectivityManager.TYPE_WIFI));
6223 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6224
6225 // Disconnect wifi and switch back to cell
6226 reset(mNetworkManagementService);
6227 mWiFiNetworkAgent.disconnect();
6228 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
6229 assertNoCallbacks(networkCallback);
6230 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6231 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6232 eq(ConnectivityManager.TYPE_MOBILE));
6233
6234 // reconnect wifi
6235 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6236 wifiLp.setInterfaceName(WIFI_IFNAME);
6237 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6238 mWiFiNetworkAgent.connect(true);
6239 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6240 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6241 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6242
6243 // Disconnect cell
6244 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006245 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006246 mCellNetworkAgent.disconnect();
6247 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6248 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6249 // sent as network being switched. Ensure rule removal for cell will not be triggered
6250 // unexpectedly before network being removed.
6251 waitForIdle();
6252 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006253 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6254 verify(mMockDnsResolver, times(1))
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07006255 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006256
6257 // Disconnect wifi
6258 ConditionVariable cv = waitForConnectivityBroadcasts(1);
6259 reset(mNetworkManagementService);
6260 mWiFiNetworkAgent.disconnect();
6261 waitFor(cv);
6262 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6263
6264 // Clean up
6265 mCm.unregisterNetworkCallback(networkCallback);
6266 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006267
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006268 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006269 String[] values = tcpBufferSizes.split(",");
6270 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6271 String wmemValues = String.join(" ", values[3], values[4], values[5]);
6272 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006273 try {
6274 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
6275 } catch (RemoteException e) {
6276 fail("mMockNetd should never throw RemoteException");
6277 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006278 reset(mMockNetd);
6279 }
6280
6281 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006282 public void testTcpBufferReset() {
6283 final String testTcpBufferSizes = "1,2,3,4,5,6";
6284
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006285 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6286 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006287 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006288 mCellNetworkAgent.connect(false);
6289 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6290
6291 // Change link Properties should have updated tcp buffer size.
6292 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006293 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006294 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006295 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006296 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006297
6298 @Test
6299 public void testGetGlobalProxyForNetwork() {
6300 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6301 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6302 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6303 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6304 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6305 }
6306
6307 @Test
6308 public void testGetProxyForActiveNetwork() {
6309 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6310 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6311 mWiFiNetworkAgent.connect(true);
6312 waitForIdle();
6313 assertNull(mService.getProxyForNetwork(null));
6314
6315 final LinkProperties testLinkProperties = new LinkProperties();
6316 testLinkProperties.setHttpProxy(testProxyInfo);
6317
6318 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6319 waitForIdle();
6320
6321 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6322 }
6323
6324 @Test
6325 public void testGetProxyForVPN() {
6326 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6327
6328 // Set up a WiFi network with no proxy
6329 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6330 mWiFiNetworkAgent.connect(true);
6331 waitForIdle();
6332 assertNull(mService.getProxyForNetwork(null));
6333
6334 // Set up a VPN network with a proxy
6335 final int uid = Process.myUid();
6336 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
6337 final ArraySet<UidRange> ranges = new ArraySet<>();
6338 ranges.add(new UidRange(uid, uid));
6339 mMockVpn.setUids(ranges);
6340 LinkProperties testLinkProperties = new LinkProperties();
6341 testLinkProperties.setHttpProxy(testProxyInfo);
6342 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6343 waitForIdle();
6344
6345 // Connect to VPN with proxy
6346 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6347 vpnNetworkAgent.connect(true);
6348 mMockVpn.connect();
6349 waitForIdle();
6350
6351 // Test that the VPN network returns a proxy, and the WiFi does not.
6352 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6353 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6354 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6355
6356 // Test that the VPN network returns no proxy when it is set to null.
6357 testLinkProperties.setHttpProxy(null);
6358 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6359 waitForIdle();
6360 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6361 assertNull(mService.getProxyForNetwork(null));
6362
6363 // Set WiFi proxy and check that the vpn proxy is still null.
6364 testLinkProperties.setHttpProxy(testProxyInfo);
6365 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6366 waitForIdle();
6367 assertNull(mService.getProxyForNetwork(null));
6368
6369 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6370 // correct proxy setting.
6371 vpnNetworkAgent.disconnect();
6372 waitForIdle();
6373 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6374 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6375 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6376 }
Rubin Xu9a3f7242019-04-11 11:45:43 -07006377
6378 @Test
6379 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6380 LinkProperties lp = new LinkProperties();
6381 lp.setInterfaceName("tun0");
6382 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6383 // The uid range needs to cover the test app so the network is visible to it.
6384 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6385 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6386
6387 // Connected VPN should have interface rules set up. There are two expected invocations,
6388 // one during VPN uid update, one during VPN LinkProperties update
6389 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6390 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6391 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6392 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6393 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6394
6395 vpnNetworkAgent.disconnect();
6396 waitForIdle();
6397
6398 // Disconnected VPN should have interface rules removed
6399 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6400 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6401 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6402 }
6403
6404 @Test
6405 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6406 LinkProperties lp = new LinkProperties();
6407 lp.setInterfaceName("tun0");
6408 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6409 // The uid range needs to cover the test app so the network is visible to it.
6410 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6411 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6412
6413 // Legacy VPN should not have interface rules set up
6414 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6415 }
6416
Lorenzo Colittia6824cc2019-04-12 19:50:22 +09006417 @Test
Rubin Xu9a3f7242019-04-11 11:45:43 -07006418 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6419 throws Exception {
6420 LinkProperties lp = new LinkProperties();
6421 lp.setInterfaceName("tun0");
6422 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6423 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6424 // The uid range needs to cover the test app so the network is visible to it.
6425 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6426 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6427
6428 // IPv6 unreachable route should not be misinterpreted as a default route
6429 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6430 }
6431
6432 @Test
6433 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6434 LinkProperties lp = new LinkProperties();
6435 lp.setInterfaceName("tun0");
6436 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6437 // The uid range needs to cover the test app so the network is visible to it.
6438 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6439 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6440
6441 // Connected VPN should have interface rules set up. There are two expected invocations,
6442 // one during VPN uid update, one during VPN LinkProperties update
6443 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6444 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6445 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6446 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6447
6448 reset(mMockNetd);
6449 InOrder inOrder = inOrder(mMockNetd);
6450 lp.setInterfaceName("tun1");
6451 vpnNetworkAgent.sendLinkProperties(lp);
6452 waitForIdle();
6453 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6454 // removed first, then new rules added)
6455 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6456 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6457 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6458 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6459
6460 reset(mMockNetd);
6461 lp = new LinkProperties();
6462 lp.setInterfaceName("tun1");
6463 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6464 vpnNetworkAgent.sendLinkProperties(lp);
6465 waitForIdle();
6466 // VPN not routing everything should no longer have interface filtering rules
6467 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6468 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6469
6470 reset(mMockNetd);
6471 lp = new LinkProperties();
6472 lp.setInterfaceName("tun1");
6473 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6474 vpnNetworkAgent.sendLinkProperties(lp);
6475 waitForIdle();
6476 // Back to routing all IPv6 traffic should have filtering rules
6477 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6478 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6479 }
6480
6481 @Test
6482 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6483 LinkProperties lp = new LinkProperties();
6484 lp.setInterfaceName("tun0");
6485 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6486 // The uid range needs to cover the test app so the network is visible to it.
6487 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
6488 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
6489 Collections.singleton(vpnRange));
6490
6491 reset(mMockNetd);
6492 InOrder inOrder = inOrder(mMockNetd);
6493
6494 // Update to new range which is old range minus APP1, i.e. only APP2
6495 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6496 new UidRange(vpnRange.start, APP1_UID - 1),
6497 new UidRange(APP1_UID + 1, vpnRange.stop)));
6498 vpnNetworkAgent.setUids(newRanges);
6499 waitForIdle();
6500
6501 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6502 // Verify old rules are removed before new rules are added
6503 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6504 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6505 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6506 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6507 }
6508
6509
6510 private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
6511 Set<UidRange> vpnRange) {
6512 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
6513 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6514 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6515 mMockVpn.connect();
6516 mMockVpn.setUids(vpnRange);
6517 vpnNetworkAgent.connect(true);
6518 waitForIdle();
6519 return vpnNetworkAgent;
6520 }
6521
6522 private void assertContainsExactly(int[] actual, int... expected) {
6523 int[] sortedActual = Arrays.copyOf(actual, actual.length);
6524 int[] sortedExpected = Arrays.copyOf(expected, expected.length);
6525 Arrays.sort(sortedActual);
6526 Arrays.sort(sortedExpected);
6527 assertArrayEquals(sortedExpected, sortedActual);
6528 }
6529
6530 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6531 final PackageInfo packageInfo = new PackageInfo();
6532 packageInfo.requestedPermissions = new String[0];
6533 packageInfo.applicationInfo = new ApplicationInfo();
6534 packageInfo.applicationInfo.privateFlags = 0;
6535 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6536 UserHandle.getAppId(uid));
6537 return packageInfo;
6538 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006539}