blob: f9982f33e14a46b3e75c9cb05dfee82f8807bdef [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 Xu9e64dc02019-04-23 18:04:14 +010019import static android.content.pm.PackageManager.GET_PERMISSIONS;
20import static android.content.pm.PackageManager.MATCH_ANY_USER;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090021import 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;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070031import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080032import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
33import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
34import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
35import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
36import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
37import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060038import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
45import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090050import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060051import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080052import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060053import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
59import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
60import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090061import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060062import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
63import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080064import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
65import static android.net.NetworkPolicyManager.RULE_NONE;
66import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
67import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000068import static android.net.RouteInfo.RTN_UNREACHABLE;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060069
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090070import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090071import static com.android.testutils.ConcurrentUtilsKt.await;
72import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090073import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090074import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
75import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
76import static com.android.testutils.MiscAssertsKt.assertEmpty;
77import static com.android.testutils.MiscAssertsKt.assertLength;
78import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
79import static com.android.testutils.MiscAssertsKt.assertThrows;
80
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090081import static org.junit.Assert.assertEquals;
82import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080083import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090084import static org.junit.Assert.assertNotNull;
85import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060086import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090087import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090088import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090089import static org.mockito.ArgumentMatchers.anyString;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000090import static org.mockito.ArgumentMatchers.eq;
Erik Klinee89953b2018-01-11 16:11:10 +090091import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090092import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060093import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090094import static org.mockito.Mockito.doAnswer;
95import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090096import static org.mockito.Mockito.doReturn;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000097import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080098import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060099import static org.mockito.Mockito.never;
100import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900101import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900102import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900103import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600104import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700105import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900106import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700107
junyulai7c469172019-01-16 20:23:34 +0800108import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900109import android.app.AlarmManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900110import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400111import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400112import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900113import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900114import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700115import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400116import android.content.Intent;
117import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000118import android.content.pm.ApplicationInfo;
119import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100120import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000121import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900122import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400123import android.net.ConnectivityManager;
124import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900125import android.net.ConnectivityManager.PacketKeepalive;
126import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900127import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900128import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800129import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900130import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800131import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900132import android.net.INetworkMonitor;
133import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800134import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700135import android.net.INetworkPolicyManager;
136import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800137import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900138import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800139import android.net.IpSecManager;
140import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900141import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700142import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700143import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400144import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400145import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700146import android.net.NetworkFactory;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400147import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700148import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900149import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900150import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800151import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100152import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000153import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800154import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700155import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800156import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900157import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900158import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900159import android.net.shared.NetworkMonitorUtils;
160import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900161import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900162import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100163import android.os.Binder;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900164import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400165import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700166import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700167import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700168import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900169import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700170import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800171import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700172import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000173import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800174import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900175import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900176import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000177import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900178import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800179import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900180import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800181import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100182import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700183import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800184import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700185
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800186import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700187import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800188import androidx.test.filters.SmallTest;
189import androidx.test.runner.AndroidJUnit4;
190
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900191import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800192import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900193import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900194import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900195import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900196import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900197import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900198import com.android.server.connectivity.DefaultNetworkMetrics;
199import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900200import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800201import com.android.server.connectivity.Nat464Xlat;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900202import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000203import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800204import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900205import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900206import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900207import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900208import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900209import com.android.testutils.HandlerUtilsKt;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900210import com.android.testutils.RecorderCallback.CallbackRecord;
211import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400212
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900213import org.junit.After;
214import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900215import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900216import org.junit.Test;
217import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900218import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000219import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900220import org.mockito.Mock;
221import org.mockito.MockitoAnnotations;
222import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900223import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900224
junyulai0c666972019-03-04 22:45:36 +0800225import java.io.IOException;
226import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800227import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000228import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700229import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900230import java.net.InetSocketAddress;
231import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400232import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900233import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100234import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800235import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500236import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100237import java.util.List;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100238import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900239import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800240import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800241import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800242import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900243import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900244import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700245import java.util.concurrent.atomic.AtomicBoolean;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900246
247import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700248
249/**
250 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400251 *
252 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900253 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700254 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900255@RunWith(AndroidJUnit4.class)
256@SmallTest
257public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700258 private static final String TAG = "ConnectivityServiceTest";
259
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900260 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900261 private static final int TEST_LINGER_DELAY_MS = 250;
262 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
263 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
264 // timeout. For this, our assertions should run fast enough to leave less than
265 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
266 // supposedly fired, and the time we call expectCallback.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900267 private static final int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900268 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
269 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900270 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
271
272 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900273
junyulai4a192e22018-06-13 15:00:37 +0800274 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700275 private static final String MOBILE_IFNAME = "test_rmnet_data0";
276 private static final String WIFI_IFNAME = "test_wlan0";
Luke Huang65914772019-03-16 00:31:46 +0800277 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700278
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900279 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900280 private HandlerThread mCsHandlerThread;
281 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900282 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900283 private TestNetworkAgentWrapper mWiFiNetworkAgent;
284 private TestNetworkAgentWrapper mCellNetworkAgent;
285 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900286 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900287 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800288 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900289 private WrappedMultinetworkPolicyTracker mPolicyTracker;
290 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700291
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900292 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900293 @Mock IpConnectivityMetrics.Logger mMetricsService;
294 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900295 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600296 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800297 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800298 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800299 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900300 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100301 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000302 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900303 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900304 @Mock AlarmManager mAlarmManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900305
waynema13516842019-03-12 18:13:49 +0800306 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
307 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900308
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900309 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
310 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
311 // reflect the state of our test ConnectivityService.
312 private class WrappedConnectivityManager extends ConnectivityManager {
313 private Network mFakeBoundNetwork;
314
315 public synchronized boolean bindProcessToNetwork(Network network) {
316 mFakeBoundNetwork = network;
317 return true;
318 }
319
320 public synchronized Network getBoundNetworkForProcess() {
321 return mFakeBoundNetwork;
322 }
323
324 public WrappedConnectivityManager(Context context, ConnectivityService service) {
325 super(context, service);
326 }
327 }
328
Paul Jensend7b6ca92015-05-13 14:05:12 -0400329 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900330 private final MockContentResolver mContentResolver;
331
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900332 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900333 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900334
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900335 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400336 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900337
338 mResources = spy(base.getResources());
339 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
340 thenReturn(new String[] {
341 "wifi,1,1,1,-1,true",
342 "mobile,0,0,0,-1,true",
343 "mobile_mms,2,0,2,60000,true",
344 });
345
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900346 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900347 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400348 }
349
350 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900351 public void startActivityAsUser(Intent intent, UserHandle handle) {
352 mStartedActivities.offer(intent);
353 }
354
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000355 public Intent expectStartActivityIntent(int timeoutMs) {
356 Intent intent = null;
357 try {
358 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
359 } catch (InterruptedException e) {}
360 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
361 return intent;
362 }
363
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900364 public void expectNoStartActivityIntent(int timeoutMs) {
365 try {
366 assertNull("Received unexpected Intent to start activity",
367 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
368 } catch (InterruptedException e) {}
369 }
370
371 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900372 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900373 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900374 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900375 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000376 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900377 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400378 return super.getSystemService(name);
379 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900380
381 @Override
382 public ContentResolver getContentResolver() {
383 return mContentResolver;
384 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900385
386 @Override
387 public Resources getResources() {
388 return mResources;
389 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100390
391 @Override
392 public PackageManager getPackageManager() {
393 return mPackageManager;
394 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900395
396 @Override
397 public void enforceCallingOrSelfPermission(String permission, String message) {
398 // The mainline permission can only be held if signed with the network stack certificate
399 // Skip testing for this permission.
400 if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
401 // All other permissions should be held by the test or unnecessary: check as normal to
402 // make sure the code does not rely on unexpected permissions.
403 super.enforceCallingOrSelfPermission(permission, message);
404 }
405 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400406
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900407 private void waitForIdle() {
408 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
409 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
410 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
411 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
412 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
413 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900414 }
415
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900416 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900417 if (agent == null) {
418 return;
419 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900420 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900421 }
422
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900423 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900424 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900425 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
426
427 // Tests that waitForIdle returns immediately if the service is already idle.
428 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900429 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900430 }
431
432 // Bring up a network that we can use to send messages to ConnectivityService.
433 ConditionVariable cv = waitForConnectivityBroadcasts(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900434 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900435 mWiFiNetworkAgent.connect(false);
436 waitFor(cv);
437 Network n = mWiFiNetworkAgent.getNetwork();
438 assertNotNull(n);
439
440 // Tests that calling waitForIdle waits for messages to be processed.
441 for (int i = 0; i < attempts; i++) {
442 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900443 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900444 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
445 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900446 }
447
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900448 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
449 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800450 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900451 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900452 // Bring up a network that we can use to send messages to ConnectivityService.
453 ConditionVariable cv = waitForConnectivityBroadcasts(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900454 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900455 mWiFiNetworkAgent.connect(false);
456 waitFor(cv);
457 Network n = mWiFiNetworkAgent.getNetwork();
458 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900459
460 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900461 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900462 for (int i = 0; i < attempts; i++) {
463 mWiFiNetworkAgent.setSignalStrength(i);
464 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
465 // We hit a race condition, as expected. Pass the test.
466 return;
467 }
468 }
469
470 // No race? There is a bug in this test.
471 fail("expected race condition at least once in " + attempts + " attempts");
472 }
473
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900474 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800475 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
476 | NETWORK_VALIDATION_PROBE_HTTP
477 | NETWORK_VALIDATION_PROBE_HTTPS;
478 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
479 | NETWORK_VALIDATION_RESULT_VALID;
480 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
481 | NETWORK_VALIDATION_PROBE_FALLBACK
482 | NETWORK_VALIDATION_RESULT_PARTIAL;
483 private static final int VALIDATION_RESULT_INVALID = 0;
484
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900485 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900486 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800487 private int mNmValidationResult = VALIDATION_RESULT_BASE;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900488 private String mNmValidationRedirectUrl = null;
489 private boolean mNmProvNotificationRequested = false;
490
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900491 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
492 // Contains the redirectUrl from networkStatus(). Before reading, wait for
493 // mNetworkStatusReceived.
494 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900495
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900496 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100497 this(transport, new LinkProperties());
498 }
499
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900500 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
501 throws Exception {
502 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900503
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900504 // Waits for the NetworkAgent to be registered, which includes the creation of the
505 // NetworkMonitor.
506 waitForIdle(TIMEOUT_MS);
507 }
508
509 @Override
510 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
511 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900512 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900513
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900514 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900515 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900516 return null;
517 };
518
Chalard Jeane7b24752019-06-20 16:01:19 +0900519 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
520 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900521
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900522 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900523 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
524 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
525 doNothing().when(mNetworkStack).makeNetworkMonitor(
526 nmNetworkCaptor.capture(),
527 any() /* name */,
528 nmCbCaptor.capture());
529
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900530 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400531 @Override
532 public void networkStatus(int status, String redirectUrl) {
533 mRedirectUrl = redirectUrl;
534 mNetworkStatusReceived.open();
535 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400536 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900537
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900538 assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900539 mNmCallbacks = nmCbCaptor.getValue();
540
Chalard Jeane7b24752019-06-20 16:01:19 +0900541 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900542
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900543 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900544 }
545
Chalard Jeane7b24752019-06-20 16:01:19 +0900546 private void onValidationRequested() throws Exception {
547 if (mNmProvNotificationRequested
548 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
549 mNmCallbacks.hideProvisioningNotification();
550 mNmProvNotificationRequested = false;
551 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900552
Chalard Jeane7b24752019-06-20 16:01:19 +0900553 mNmCallbacks.notifyNetworkTested(
554 mNmValidationResult, mNmValidationRedirectUrl);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900555
Chalard Jeane7b24752019-06-20 16:01:19 +0900556 if (mNmValidationRedirectUrl != null) {
557 mNmCallbacks.showProvisioningNotification(
558 "test_provisioning_notif_action", "com.android.test.package");
559 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900560 }
Paul Jensen3d911462015-06-12 06:40:24 -0400561 }
562
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900563 /**
564 * Connect without adding any internet capability.
565 */
Paul Jensene0988542015-06-25 15:30:08 -0400566 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900567 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400568 }
569
Paul Jensend7b6ca92015-05-13 14:05:12 -0400570 /**
Paul Jensene0988542015-06-25 15:30:08 -0400571 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400572 * @param validated Indicate if network should pretend to be validated.
573 */
574 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900575 connect(validated, true);
576 }
577
578 /**
579 * Transition this NetworkAgent to CONNECTED state.
580 * @param validated Indicate if network should pretend to be validated.
581 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
582 */
583 public void connect(boolean validated, boolean hasInternet) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900584 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400585
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900586 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400587 final ConditionVariable validatedCv = new ConditionVariable();
588 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900589 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400590 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900591 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900592 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400593 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900594 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400595 public void onCapabilitiesChanged(Network network,
596 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400597 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900598 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400599 validatedCv.open();
600 }
601 }
602 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400603 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400604 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900605 if (hasInternet) {
606 addCapability(NET_CAPABILITY_INTERNET);
607 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400608
Paul Jensene0988542015-06-25 15:30:08 -0400609 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400610
611 if (validated) {
612 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400613 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900614 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400615 }
616
617 if (callback != null) mCm.unregisterNetworkCallback(callback);
618 }
619
Paul Jensen232437312016-04-06 09:51:26 -0400620 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900621 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400622 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400623 }
624
lucasline252a742019-03-12 13:08:03 +0800625 public void connectWithPartialConnectivity() {
626 setNetworkPartial();
627 connect(false);
628 }
629
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900630 public void connectWithPartialValidConnectivity() {
631 setNetworkPartialValid();
632 connect(false);
633 }
634
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900635 void setNetworkValid() {
636 mNmValidationResult = VALIDATION_RESULT_VALID;
637 mNmValidationRedirectUrl = null;
Erik Kline1d3db322017-02-28 16:20:20 +0900638 }
639
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900640 void setNetworkInvalid() {
641 mNmValidationResult = VALIDATION_RESULT_INVALID;
642 mNmValidationRedirectUrl = null;
Chalard Jean804b8fb2018-01-30 22:41:41 +0900643 }
644
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900645 void setNetworkPortal(String redirectUrl) {
646 setNetworkInvalid();
647 mNmValidationRedirectUrl = redirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400648 }
649
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900650 void setNetworkPartial() {
651 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
652 mNmValidationRedirectUrl = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400653 }
Paul Jensene0988542015-06-25 15:30:08 -0400654
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900655 void setNetworkPartialValid() {
656 mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
657 mNmValidationRedirectUrl = null;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900658 }
Paul Jensen232437312016-04-06 09:51:26 -0400659
660 public String waitForRedirectUrl() {
661 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
662 return mRedirectUrl;
663 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900664
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900665 public void expectDisconnected() {
666 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900667 }
668
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900669 public void expectPreventReconnectReceived() {
670 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900671 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400672 }
673
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900674 /**
675 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
676 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900677 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900678 * expectRemoveRequests.
679 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700680 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400681 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
682 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400683 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700684
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900685 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900686 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
687 // once, then cause some other thread to add or remove requests, then call
688 // waitForRequests().
689 // It is not possible to wait for both add and remove requests. When adding, the queue
690 // contains the expected score. When removing, the value is unused, all matters is the
691 // number of objects in the queue.
692 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900693
694 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900695 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900696 private boolean mExpectingAdditions;
697
Etan Cohenddb720a2019-01-08 12:09:18 -0800698 // Used to collect the networks requests managed by this factory. This is a duplicate of
699 // the internal information stored in the NetworkFactory (which is private).
700 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
701
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700702 public MockNetworkFactory(Looper looper, Context context, String logTag,
703 NetworkCapabilities filter) {
704 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900705 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700706 }
707
708 public int getMyRequestCount() {
709 return getRequestCount();
710 }
711
712 protected void startNetwork() {
713 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400714 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700715 }
716
717 protected void stopNetwork() {
718 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400719 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700720 }
721
722 public boolean getMyStartRequested() {
723 return mNetworkStarted.get();
724 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400725
726 public ConditionVariable getNetworkStartedCV() {
727 mNetworkStartedCV.close();
728 return mNetworkStartedCV;
729 }
730
731 public ConditionVariable getNetworkStoppedCV() {
732 mNetworkStoppedCV.close();
733 return mNetworkStoppedCV;
734 }
735
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900736 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900737 protected void handleAddRequest(NetworkRequest request, int score,
738 int factorySerialNumber) {
739 synchronized (mExpectations) {
740 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900741
Chalard Jean05ab6812018-05-02 21:14:54 +0900742 assertNotNull("Added more requests than expected (" + request + " score : "
743 + score + ")", expectedScore);
744 // If we're expecting anything, we must be expecting additions.
745 if (!mExpectingAdditions) {
746 fail("Can't add requests while expecting requests to be removed");
747 }
748 if (expectedScore != score) {
749 fail("Expected score was " + expectedScore + " but actual was " + score
750 + " in added request");
751 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900752
Chalard Jean05ab6812018-05-02 21:14:54 +0900753 // Add the request.
754 mNetworkRequests.put(request.requestId, request);
755 super.handleAddRequest(request, score, factorySerialNumber);
756 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900757 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400758 }
759
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900760 @Override
761 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900762 synchronized (mExpectations) {
763 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900764
Chalard Jean05ab6812018-05-02 21:14:54 +0900765 assertTrue("Removed more requests than expected", expectedScore != null);
766 // If we're expecting anything, we must be expecting removals.
767 if (mExpectingAdditions) {
768 fail("Can't remove requests while expecting requests to be added");
769 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900770
Chalard Jean05ab6812018-05-02 21:14:54 +0900771 // Remove the request.
772 mNetworkRequests.remove(request.requestId);
773 super.handleRemoveRequest(request);
774 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900775 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400776 }
777
Etan Cohenddb720a2019-01-08 12:09:18 -0800778 // Trigger releasing the request as unfulfillable
779 public void triggerUnfulfillable(NetworkRequest r) {
780 super.releaseRequestAsUnfulfillableByAnyFactory(r);
781 }
782
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900783 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900784 if (mExpectations.size() != 0) {
785 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900786 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400787 }
788
Chalard Jean05ab6812018-05-02 21:14:54 +0900789 // Expects that requests with the specified scores will be added.
790 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900791 assertNoExpectations();
792 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900793 for (int score : scores) {
794 mExpectations.add(score);
795 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400796 }
797
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900798 // Expects that count requests will be removed.
799 public void expectRemoveRequests(final int count) {
800 assertNoExpectations();
801 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900802 for (int i = 0; i < count; ++i) {
803 mExpectations.add(0); // For removals the score is ignored so any value will do.
804 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900805 }
806
807 // Waits for the expected request additions or removals to happen within a timeout.
808 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900809 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
810 synchronized (mExpectations) {
811 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
812 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
813 }
814 }
815 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900816 final String msg = count + " requests still not " +
817 (mExpectingAdditions ? "added" : "removed") +
818 " after " + TIMEOUT_MS + " ms";
819 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900820 }
821
Etan Cohenddb720a2019-01-08 12:09:18 -0800822 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
823 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900824 waitForRequests();
825 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800826 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400827 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700828 }
829
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900830 private static Looper startHandlerThreadAndReturnLooper() {
831 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
832 handlerThread.start();
833 return handlerThread.getLooper();
834 }
835
836 private class MockVpn extends Vpn {
837 // TODO : the interactions between this mock and the mock network agent are too
838 // hard to get right at this moment, because it's unclear in which case which
839 // target needs to get a method call or both, and in what order. It's because
840 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
841 // parent class of MockVpn agent wants that responsibility.
842 // That being said inside the test it should be possible to make the interactions
843 // harder to get wrong with precise speccing, judicious comments, helper methods
844 // and a few sprinkled assertions.
845
846 private boolean mConnected = false;
847 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
848 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900849 private TestNetworkAgentWrapper mMockNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900850
851 public MockVpn(int userId) {
852 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
853 userId);
854 }
855
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900856 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
857 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900858 mMockNetworkAgent = agent;
859 mNetworkAgent = agent.getNetworkAgent();
860 mNetworkCapabilities.set(agent.getNetworkCapabilities());
861 }
862
863 public void setUids(Set<UidRange> uids) {
864 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800865 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900866 }
867
868 @Override
869 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800870 if (mMockNetworkAgent == null) {
871 return NETID_UNSET;
872 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900873 return mMockNetworkAgent.getNetwork().netId;
874 }
875
876 @Override
877 public boolean appliesToUid(int uid) {
878 return mConnected; // Trickery to simplify testing.
879 }
880
881 @Override
882 protected boolean isCallerEstablishedOwnerLocked() {
883 return mConnected; // Similar trickery
884 }
885
Varun Anandc51b06d2019-02-25 17:22:02 -0800886 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900887 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
888 mConnected = true;
889 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800890 mConfig.isMetered = isAlwaysMetered;
891 }
892
893 public void connectAsAlwaysMetered() {
894 connect(true /* isAlwaysMetered */);
895 }
896
897 public void connect() {
898 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900899 }
900
901 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800902 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
903 if (!mConnected) return null;
904 super.updateCapabilities(defaultNetwork);
905 // Because super.updateCapabilities will update the capabilities of the agent but
906 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900907 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800908 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900909 }
910
911 private void copyCapabilitiesToNetworkAgent() {
912 if (null != mMockNetworkAgent) {
913 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
914 false /* sendToConnectivityService */);
915 }
916 }
917
918 public void disconnect() {
919 mConnected = false;
920 mConfig = null;
921 }
922 }
923
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900924 private void mockVpn(int uid) {
925 synchronized (mService.mVpns) {
926 int userId = UserHandle.getUserId(uid);
927 mMockVpn = new MockVpn(userId);
928 // This has no effect unless the VPN is actually connected, because things like
929 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
930 // netId, and check if that network is actually connected.
931 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900932 }
933 }
934
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900935 private void setUidRulesChanged(int uidRules) throws RemoteException {
936 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
937 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400938
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900939 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
940 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
941 }
942
943 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
944 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
945 }
946
947 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
948 volatile boolean mConfigRestrictsAvoidBadWifi;
949 volatile int mConfigMeteredMultipathPreference;
950
951 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900952 super(c, h, r);
953 }
954
955 @Override
956 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900957 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +0900958 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900959
960 @Override
961 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900962 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +0800963 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400964 }
965
Paul Jensen3d911462015-06-12 06:40:24 -0400966 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900967 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
968 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400969 */
970 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900971 if (conditionVariable.block(TIMEOUT_MS)) {
972 return;
973 }
974 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -0400975 }
976
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000977 private static final int VPN_USER = 0;
978 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
979 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
980 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
981
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900982 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -0400983 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900984 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400985
Hugo Benichi64901e52017-10-19 14:42:40 +0900986 MockitoAnnotations.initMocks(this);
987 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
988
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000989 when(mUserManager.getUsers(eq(true))).thenReturn(
990 Arrays.asList(new UserInfo[] {
991 new UserInfo(VPN_USER, "", 0),
992 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000993
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900994 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
995 // http://b/25897652 .
996 if (Looper.myLooper() == null) {
997 Looper.prepare();
998 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100999 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001000
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001001 FakeSettingsProvider.clearSettingsProvider();
1002 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1003 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001004 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1005 LocalServices.addService(
1006 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001007
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001008 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1009 mAlarmManagerThread.start();
1010 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1011
1012 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1013 final ConnectivityService.Dependencies deps = makeDependencies();
1014 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001015 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001016 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001017 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001018 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001019 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001020 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001021 deps);
1022 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1023 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001024
Mike Yuf9729752018-08-17 15:22:05 +08001025 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1026 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1027 verify(mNpm).registerListener(policyListenerCaptor.capture());
1028 mPolicyListener = policyListenerCaptor.getValue();
1029
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001030 // Create local CM before sending system ready so that we can answer
1031 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001032 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001033 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001034 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001035 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001036
1037 // Ensure that the default setting for Captive Portals is used for most tests
1038 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001039 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001040 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001041 }
1042
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001043 private ConnectivityService.Dependencies makeDependencies() {
1044 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1045 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1046 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1047
1048 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1049 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1050 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1051 doReturn(mNetworkStack).when(deps).getNetworkStack();
1052 doReturn(systemProperties).when(deps).getSystemProperties();
1053 doReturn(mock(Tethering.class)).when(deps).makeTethering(any(), any(), any(), any(), any());
1054 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1055 doReturn(mMetricsService).when(deps).getMetricsLogger();
1056 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1057 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
1058 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1059 doAnswer(inv -> {
1060 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1061 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1062 return mPolicyTracker;
1063 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1064
1065 return deps;
1066 }
1067
1068 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1069 doAnswer(inv -> {
1070 final long when = inv.getArgument(1);
1071 final WakeupMessage wakeupMsg = inv.getArgument(3);
1072 final Handler handler = inv.getArgument(4);
1073
1074 long delayMs = when - SystemClock.elapsedRealtime();
1075 if (delayMs < 0) delayMs = 0;
1076 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1077 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1078 + "ms into the future: " + delayMs);
1079 }
1080 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1081 delayMs);
1082
1083 return null;
1084 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1085 any(WakeupMessage.class), any());
1086
1087 doAnswer(inv -> {
1088 final WakeupMessage wakeupMsg = inv.getArgument(0);
1089 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1090 return null;
1091 }).when(am).cancel(any(WakeupMessage.class));
1092 }
1093
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001094 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001095 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001096 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001097 if (mCellNetworkAgent != null) {
1098 mCellNetworkAgent.disconnect();
1099 mCellNetworkAgent = null;
1100 }
1101 if (mWiFiNetworkAgent != null) {
1102 mWiFiNetworkAgent.disconnect();
1103 mWiFiNetworkAgent = null;
1104 }
1105 if (mEthernetNetworkAgent != null) {
1106 mEthernetNetworkAgent.disconnect();
1107 mEthernetNetworkAgent = null;
1108 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001109 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001110
1111 mCsHandlerThread.quitSafely();
1112 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001113 }
1114
Rubin Xu9e64dc02019-04-23 18:04:14 +01001115 private void mockDefaultPackages() throws Exception {
1116 final String testPackageName = mContext.getPackageName();
1117 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1118 testPackageName, PackageManager.GET_PERMISSIONS);
1119 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1120 new String[] {testPackageName});
1121 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1122 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1123
1124 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1125 Arrays.asList(new PackageInfo[] {
1126 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1127 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1128 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1129 }));
1130 }
1131
Paul Jensend7b6ca92015-05-13 14:05:12 -04001132 private void verifyActiveNetwork(int transport) {
1133 // Test getActiveNetworkInfo()
1134 assertNotNull(mCm.getActiveNetworkInfo());
1135 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1136 // Test getActiveNetwork()
1137 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001138 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001139 if (!NetworkCapabilities.isValidTransport(transport)) {
1140 throw new IllegalStateException("Unknown transport " + transport);
1141 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001142 switch (transport) {
1143 case TRANSPORT_WIFI:
1144 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1145 break;
1146 case TRANSPORT_CELLULAR:
1147 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1148 break;
1149 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001150 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001151 }
1152 // Test getNetworkInfo(Network)
1153 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001154 assertEquals(transportToLegacyType(transport),
1155 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001156 // Test getNetworkCapabilities(Network)
1157 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1158 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1159 }
1160
1161 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001162 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001163 // Test getActiveNetworkInfo()
1164 assertNull(mCm.getActiveNetworkInfo());
1165 // Test getActiveNetwork()
1166 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001167 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001168 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001169 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001170 }
1171
1172 /**
1173 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1174 * broadcasts are received.
1175 */
1176 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1177 final ConditionVariable cv = new ConditionVariable();
1178 mServiceContext.registerReceiver(new BroadcastReceiver() {
1179 private int remaining = count;
1180 public void onReceive(Context context, Intent intent) {
1181 if (--remaining == 0) {
1182 cv.open();
1183 mServiceContext.unregisterReceiver(this);
1184 }
1185 }
1186 }, new IntentFilter(CONNECTIVITY_ACTION));
1187 return cv;
1188 }
1189
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001190 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001191 public void testNetworkTypes() {
1192 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1193 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1194 // will fail. Failing here is much easier to debug.
1195 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1196 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001197 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1198 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1199
1200 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1201 // mocks, this assert exercises the ConnectivityService code path that ensures that
1202 // TYPE_ETHERNET is supported if the ethernet service is running.
1203 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001204 }
1205
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001206 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001207 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001208 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001209 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1210 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001211 assertNull(mCm.getActiveNetworkInfo());
1212 assertNull(mCm.getActiveNetwork());
1213 // Test bringing up validated cellular.
1214 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1215 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001216 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001217 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001218 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001219 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1220 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1221 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1222 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1223 // Test bringing up validated WiFi.
1224 cv = waitForConnectivityBroadcasts(2);
1225 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001226 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001227 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001228 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001229 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1230 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1231 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1232 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1233 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001234 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001235 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001236 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001237 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001238 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001239 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1240 // Test WiFi disconnect.
1241 cv = waitForConnectivityBroadcasts(1);
1242 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001243 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001244 verifyNoNetwork();
1245 }
1246
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001247 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001248 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1249 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001250 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001251 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1252 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001253 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001254 verifyActiveNetwork(TRANSPORT_WIFI);
1255 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001256 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001257 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001258 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001259 verifyActiveNetwork(TRANSPORT_WIFI);
1260 // Test cellular disconnect.
1261 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001262 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001263 verifyActiveNetwork(TRANSPORT_WIFI);
1264 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001265 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001266 cv = waitForConnectivityBroadcasts(2);
1267 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001268 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001269 verifyActiveNetwork(TRANSPORT_CELLULAR);
1270 // Test cellular disconnect.
1271 cv = waitForConnectivityBroadcasts(2);
1272 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001273 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001274 verifyActiveNetwork(TRANSPORT_WIFI);
1275 // Test WiFi disconnect.
1276 cv = waitForConnectivityBroadcasts(1);
1277 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001278 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001279 verifyNoNetwork();
1280 }
1281
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001282 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001283 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1284 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001285 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001286 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1287 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001288 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001289 verifyActiveNetwork(TRANSPORT_CELLULAR);
1290 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001291 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001292 cv = waitForConnectivityBroadcasts(2);
1293 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001294 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001295 verifyActiveNetwork(TRANSPORT_WIFI);
1296 // Test WiFi disconnect.
1297 cv = waitForConnectivityBroadcasts(2);
1298 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001299 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001300 verifyActiveNetwork(TRANSPORT_CELLULAR);
1301 // Test cellular disconnect.
1302 cv = waitForConnectivityBroadcasts(1);
1303 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001304 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001305 verifyNoNetwork();
1306 }
1307
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001308 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001309 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001310 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001311 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001312 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1313 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001314 waitFor(cv);
1315 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001316 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001317 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001318 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001319 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001320 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001321 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001322 waitFor(cv);
1323 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001324 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1325 NET_CAPABILITY_VALIDATED));
1326 // Test cellular disconnect.
1327 cv = waitForConnectivityBroadcasts(2);
1328 mCellNetworkAgent.disconnect();
1329 waitFor(cv);
1330 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001331 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001332 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001333 NET_CAPABILITY_VALIDATED));
1334 }
1335
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001336 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001337 public void testCellularOutscoresWeakWifi() throws Exception {
1338 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001339 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001340 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1341 mCellNetworkAgent.connect(true);
1342 waitFor(cv);
1343 verifyActiveNetwork(TRANSPORT_CELLULAR);
1344 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001345 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001346 cv = waitForConnectivityBroadcasts(2);
1347 mWiFiNetworkAgent.connect(true);
1348 waitFor(cv);
1349 verifyActiveNetwork(TRANSPORT_WIFI);
1350 // Test WiFi getting really weak.
1351 cv = waitForConnectivityBroadcasts(2);
1352 mWiFiNetworkAgent.adjustScore(-11);
1353 waitFor(cv);
1354 verifyActiveNetwork(TRANSPORT_CELLULAR);
1355 // Test WiFi restoring signal strength.
1356 cv = waitForConnectivityBroadcasts(2);
1357 mWiFiNetworkAgent.adjustScore(11);
1358 waitFor(cv);
1359 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001360 }
1361
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001362 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001363 public void testReapingNetwork() throws Exception {
1364 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1365 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001366 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001367 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001368 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001369 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1370 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001371 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001372 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001373 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001374 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001375 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1376 final ConditionVariable cv = waitForConnectivityBroadcasts(1);
Paul Jensene0988542015-06-25 15:30:08 -04001377 mWiFiNetworkAgent.connect(true);
1378 waitFor(cv);
1379 verifyActiveNetwork(TRANSPORT_WIFI);
1380 // Test bringing up unvalidated cellular.
1381 // Expect it to be torn down because it could never be the highest scoring network
1382 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001383 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001384 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001385 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001386 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001387 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001388 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001389 }
1390
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001391 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001392 public void testCellularFallback() throws Exception {
1393 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001394 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001395 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1396 mCellNetworkAgent.connect(true);
1397 waitFor(cv);
1398 verifyActiveNetwork(TRANSPORT_CELLULAR);
1399 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001400 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001401 cv = waitForConnectivityBroadcasts(2);
1402 mWiFiNetworkAgent.connect(true);
1403 waitFor(cv);
1404 verifyActiveNetwork(TRANSPORT_WIFI);
1405 // Reevaluate WiFi (it'll instantly fail DNS).
1406 cv = waitForConnectivityBroadcasts(2);
1407 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1408 NET_CAPABILITY_VALIDATED));
1409 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1410 // Should quickly fall back to Cellular.
1411 waitFor(cv);
1412 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1413 NET_CAPABILITY_VALIDATED));
1414 verifyActiveNetwork(TRANSPORT_CELLULAR);
1415 // Reevaluate cellular (it'll instantly fail DNS).
1416 cv = waitForConnectivityBroadcasts(2);
1417 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1418 NET_CAPABILITY_VALIDATED));
1419 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1420 // Should quickly fall back to WiFi.
1421 waitFor(cv);
1422 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1423 NET_CAPABILITY_VALIDATED));
1424 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1425 NET_CAPABILITY_VALIDATED));
1426 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001427 }
1428
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001429 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001430 public void testWiFiFallback() throws Exception {
1431 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001432 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001433 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1434 mWiFiNetworkAgent.connect(false);
1435 waitFor(cv);
1436 verifyActiveNetwork(TRANSPORT_WIFI);
1437 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001438 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001439 cv = waitForConnectivityBroadcasts(2);
1440 mCellNetworkAgent.connect(true);
1441 waitFor(cv);
1442 verifyActiveNetwork(TRANSPORT_CELLULAR);
1443 // Reevaluate cellular (it'll instantly fail DNS).
1444 cv = waitForConnectivityBroadcasts(2);
1445 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1446 NET_CAPABILITY_VALIDATED));
1447 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1448 // Should quickly fall back to WiFi.
1449 waitFor(cv);
1450 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1451 NET_CAPABILITY_VALIDATED));
1452 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001453 }
1454
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001455 @Test
1456 public void testRequiresValidation() {
1457 assertTrue(NetworkMonitorUtils.isValidationRequired(
1458 mCm.getDefaultRequest().networkCapabilities));
1459 }
1460
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001461 /**
1462 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1463 * this class receives, by calling expectCallback() exactly once each time a callback is
1464 * received. assertNoCallback may be called at any time.
1465 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001466 private class TestNetworkCallback extends TestableNetworkCallback {
1467 @Override
1468 public void assertNoCallback() {
1469 // TODO: better support this use case in TestableNetworkCallback
1470 waitForIdle();
1471 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001472 }
Paul Jensen3d911462015-06-12 06:40:24 -04001473
Erik Klineacdd6392016-07-07 16:50:58 +09001474 @Override
Chalard Jean6f4216f2019-06-05 01:40:32 +09001475 public <T extends CallbackRecord> T expectCallback(final KClass<T> type, final HasNetwork n,
1476 final long timeoutMs) {
1477 final T callback = super.expectCallback(type, n, timeoutMs);
1478 if (callback instanceof CallbackRecord.Losing) {
1479 // TODO : move this to the specific test(s) needing this rather than here.
1480 final CallbackRecord.Losing losing = (CallbackRecord.Losing) callback;
1481 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001482 String msg = String.format(
1483 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001484 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001485 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001486 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001487 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001488 }
1489 }
1490
1491 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1492 // only be declared in a static or top level type".
1493 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1494 for (TestNetworkCallback c : callbacks) {
1495 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001496 }
1497 }
1498
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001499 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001500 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001501 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001502 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1503 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001504 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1505 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001506 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1507 .addTransportType(TRANSPORT_WIFI).build();
1508 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1509 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001510 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001511 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1512 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1513
1514 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001515 ConditionVariable cv = waitForConnectivityBroadcasts(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001516 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001517 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001518 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1519 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001520 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1521 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001522 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001523
Paul Jensen3d911462015-06-12 06:40:24 -04001524 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1525 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001526 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001527 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001528 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1529
Paul Jensen3d911462015-06-12 06:40:24 -04001530 cv = waitForConnectivityBroadcasts(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001531 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001532 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001533 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1534 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001535 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1536 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001537 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001538
Paul Jensen3d911462015-06-12 06:40:24 -04001539 cv = waitForConnectivityBroadcasts(2);
1540 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001541 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1542 wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001543 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001544 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001545 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001546
Paul Jensen3d911462015-06-12 06:40:24 -04001547 cv = waitForConnectivityBroadcasts(1);
1548 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001549 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
1550 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001551 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001552 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001553
1554 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001555 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001556 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001557 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1558 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001559 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001560 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001561
Paul Jensen3d911462015-06-12 06:40:24 -04001562 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1563 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001564 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001565 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001566 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1567
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001568 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001569 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001570 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001571 genericNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001572 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001573 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001574 cellNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001575 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001576 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001577
Paul Jensen3d911462015-06-12 06:40:24 -04001578 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001579 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1580 wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001581 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001582
Paul Jensen3d911462015-06-12 06:40:24 -04001583 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001584 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
1585 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001586 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001587 }
1588
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001589 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001590 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001591 // This test would be flaky with the default 120ms timer: that is short enough that
1592 // lingered networks are torn down before assertions can be run. We don't want to mock the
1593 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1594 // in detecting races.
1595 mService.mLingerDelayMs = 300;
1596
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001597 NetworkRequest request = new NetworkRequest.Builder()
1598 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1599 .build();
1600 TestNetworkCallback callback = new TestNetworkCallback();
1601 mCm.registerNetworkCallback(request, callback);
1602
1603 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1604 mCm.registerDefaultNetworkCallback(defaultCallback);
1605
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001606 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1607 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1608 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001609
1610 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1611 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1612 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1613
1614 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001615 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1616 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001617 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001618 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001619
1620 mWiFiNetworkAgent.connect(true);
1621 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1622 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001623 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001624 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001625 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001626 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001627 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001628 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001629 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001630
1631 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001632 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001633 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001634 callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001635 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001636 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001637 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001638 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001639
1640 mEthernetNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001641 callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
1642 defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001643 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001644 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001645
1646 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001647 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001648 if (i % 2 == 0) {
1649 mWiFiNetworkAgent.adjustScore(-15);
1650 oldNetwork = mWiFiNetworkAgent;
1651 newNetwork = mCellNetworkAgent;
1652 } else {
1653 mWiFiNetworkAgent.adjustScore(15);
1654 oldNetwork = mCellNetworkAgent;
1655 newNetwork = mWiFiNetworkAgent;
1656
1657 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001658 callback.expectCallback(CallbackRecord.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001659 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1660 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001661 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001662 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1663 }
1664 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1665
1666 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1667 // if the network is still up.
1668 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001669 // We expect a notification about the capabilities change, and nothing else.
1670 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1671 defaultCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001672 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001673 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001674
1675 // Wifi no longer satisfies our listen, which is for an unmetered network.
1676 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001677 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1678
1679 // Disconnect our test networks.
1680 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001681 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001682 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001683 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001684 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001685 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001686 waitForIdle();
1687 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001688
1689 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001690 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001691
1692 // Check that a network is only lingered or torn down if it would not satisfy a request even
1693 // if it validated.
1694 request = new NetworkRequest.Builder().clearCapabilities().build();
1695 callback = new TestNetworkCallback();
1696
1697 mCm.registerNetworkCallback(request, callback);
1698
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001699 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001700 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001701 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1702 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001703 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001704 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001705
1706 // Bring up wifi with a score of 20.
1707 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001708 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001709 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001710 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1711 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001712 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001713 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001714
1715 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001716 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1717 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001718 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001719 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001720 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001721
1722 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001723 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001724 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001725 mWiFiNetworkAgent.adjustScore(50);
1726 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001727 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001728 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001729 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001730 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001731 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001732
1733 // Tear down wifi.
1734 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001735 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1736 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001737 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001738 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001739 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001740
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001741 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1742 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001743 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001744 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001745 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001746 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001747 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001748 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001749 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001750 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001751 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001752
1753 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001754 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1755 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001756 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001757 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001758 callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
1759 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001760 waitForIdle();
1761 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001762
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001763 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001764 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001765 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001766 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1767 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001768 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001769 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001770 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001771 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1772 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001773 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001774 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001775 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001776 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001777
1778 NetworkRequest cellRequest = new NetworkRequest.Builder()
1779 .addTransportType(TRANSPORT_CELLULAR).build();
1780 NetworkCallback noopCallback = new NetworkCallback();
1781 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001782 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1783 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001784 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001785 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001786
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001787 // Similar to the above: lingering can start even after the lingered request is removed.
1788 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001789 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001790 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1791 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001792 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001793 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001794
1795 // Cell is now the default network. Pin it with a cell-specific request.
1796 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1797 mCm.requestNetwork(cellRequest, noopCallback);
1798
1799 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001800 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001801 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001802 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1803 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001804 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001805 // The default request is lingering on cell, but nothing happens to cell, and we send no
1806 // callbacks for it, because it's kept up by cellRequest.
1807 callback.assertNoCallback();
1808 // Now unregister cellRequest and expect cell to start lingering.
1809 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001810 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001811
1812 // Let linger run its course.
1813 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001814 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001815 callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001816
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001817 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
1818 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
1819 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001820 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001821 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001822 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001823 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001824 callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001825 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001826 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
1827 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001828 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001829
1830 // Let linger run its course.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001831 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001832
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001833 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001834 mEthernetNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001835 callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
1836 defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
1837 trackDefaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001838
1839 mCm.unregisterNetworkCallback(callback);
1840 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001841 mCm.unregisterNetworkCallback(trackDefaultCallback);
1842 }
1843
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001844 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001845 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001846 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001847 NetworkRequest request = new NetworkRequest.Builder()
1848 .clearCapabilities()
1849 .build();
1850 TestNetworkCallback callback = new TestNetworkCallback();
1851 mCm.registerNetworkCallback(request, callback);
1852
1853 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1854 mCm.registerDefaultNetworkCallback(defaultCallback);
1855
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001856 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1857 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001858
1859 mCellNetworkAgent.connect(true);
1860 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1861 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1862
1863 // Wifi comes up and cell lingers.
1864 mWiFiNetworkAgent.connect(true);
1865 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1866 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001867 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001868 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1869
1870 // File a request for cellular, then release it.
1871 NetworkRequest cellRequest = new NetworkRequest.Builder()
1872 .addTransportType(TRANSPORT_CELLULAR).build();
1873 NetworkCallback noopCallback = new NetworkCallback();
1874 mCm.requestNetwork(cellRequest, noopCallback);
1875 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001876 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001877
1878 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09001879 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09001880 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
1881 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
1882 lingerTimeoutMs);
1883
1884 // Clean up.
1885 mCm.unregisterNetworkCallback(defaultCallback);
1886 mCm.unregisterNetworkCallback(callback);
1887 }
1888
1889 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001890 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001891 NetworkRequest request = new NetworkRequest.Builder()
1892 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
1893 .build();
1894 TestNetworkCallback callback = new TestNetworkCallback();
1895 mCm.registerNetworkCallback(request, callback);
1896
1897 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001898 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001899 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001900 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001901
1902 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001903 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001904 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001905 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001906 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001907
1908 // Cell Remains the default.
1909 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1910
1911 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
1912 // it's explicitly selected.
1913 mWiFiNetworkAgent.adjustScore(-40);
1914 mWiFiNetworkAgent.adjustScore(40);
1915 callback.assertNoCallback();
1916
1917 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
1918 // wifi even though it's unvalidated.
1919 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001920 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001921 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1922
1923 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
1924 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001925 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001926 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001927 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001928 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001929 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001930
1931 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
1932 // network to disconnect.
1933 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001934 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001935
1936 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001937 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001938 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001939 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001940 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001941 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001942 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1943 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1944
1945 // BUG: the network will no longer linger, even though it's validated and outscored.
1946 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001947 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001948 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001949 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001950 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1951 callback.assertNoCallback();
1952
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001953 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
1954 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
1955 // wifi immediately.
1956 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001957 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001958 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001959 mWiFiNetworkAgent.explicitlySelected(true, true);
1960 mWiFiNetworkAgent.connect(false);
1961 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001962 callback.expectCallback(CallbackRecord.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001963 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1964 mEthernetNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001965 callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001966
1967 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
1968 // Check that the network is not scored specially and that the device prefers cell data.
1969 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001970 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001971 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001972 mWiFiNetworkAgent.explicitlySelected(false, true);
1973 mWiFiNetworkAgent.connect(false);
1974 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1975 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1976
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001977 // Clean up.
1978 mWiFiNetworkAgent.disconnect();
1979 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001980
Chalard Jean6f4216f2019-06-05 01:40:32 +09001981 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1982 callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001983 }
1984
Chalard Jean05ab6812018-05-02 21:14:54 +09001985 private int[] makeIntArray(final int size, final int value) {
1986 final int[] array = new int[size];
1987 Arrays.fill(array, value);
1988 return array;
1989 }
1990
Paul Jensen85cf78e2015-06-25 13:25:07 -04001991 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001992 // Verify NOT_RESTRICTED is set appropriately
1993 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1994 .build().networkCapabilities;
1995 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1996 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1997 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001998 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001999 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2000 } else {
2001 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2002 }
2003
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002004 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002005 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002006 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2007 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002008 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002009 mServiceContext, "testFactory", filter);
2010 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002011 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002012 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002013 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002014 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002015 int expectedRequestCount = 1;
2016 NetworkCallback networkCallback = null;
2017 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2018 // add one.
2019 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002020 assertFalse(testFactory.getMyStartRequested());
2021 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2022 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002023 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002024 mCm.requestNetwork(request, networkCallback);
2025 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002026 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002027 }
Paul Jensen3d911462015-06-12 06:40:24 -04002028 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002029 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2030 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002031
Paul Jensen85cf78e2015-06-25 13:25:07 -04002032 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002033 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002034 // Rather than create a validated network which complicates things by registering it's
2035 // own NetworkRequest during startup, just bump up the score to cancel out the
2036 // unvalidated penalty.
2037 testAgent.adjustScore(40);
2038 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002039
2040 // When testAgent connects, ConnectivityService will re-send us all current requests with
2041 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2042 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002043 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002044 testAgent.connect(false);
2045 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002046 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002047 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002048 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002049
Paul Jensen85cf78e2015-06-25 13:25:07 -04002050 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002051 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002052 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002053 ConnectivityManager.NetworkCallback[] networkCallbacks =
2054 new ConnectivityManager.NetworkCallback[10];
2055 for (int i = 0; i< networkCallbacks.length; i++) {
2056 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2057 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002058 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002059 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2060 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002061 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2062 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002063
Paul Jensen85cf78e2015-06-25 13:25:07 -04002064 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002065 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002066 for (int i = 0; i < networkCallbacks.length; i++) {
2067 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2068 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002069 testFactory.waitForNetworkRequests(expectedRequestCount);
2070 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002071
Paul Jensen85cf78e2015-06-25 13:25:07 -04002072 // Drop the higher scored network.
2073 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002074 // With the default network disconnecting, the requests are sent with score 0 to factories.
2075 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002076 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002077 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002078 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002079 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2080 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002081
2082 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002083 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002084 handlerThread.quit();
2085 }
2086
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002087 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002088 public void testNetworkFactoryRequests() throws Exception {
2089 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2090 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2091 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2092 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2093 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2094 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2095 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2096 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2097 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2098 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2099 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2100 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2101 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2102 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2103 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2104 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2105 }
2106
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002107 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002108 public void testNoMutableNetworkRequests() throws Exception {
2109 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002110 NetworkRequest request1 = new NetworkRequest.Builder()
2111 .addCapability(NET_CAPABILITY_VALIDATED)
2112 .build();
2113 NetworkRequest request2 = new NetworkRequest.Builder()
2114 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2115 .build();
2116
2117 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002118 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2119 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2120 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2121 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002122 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002123
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002124 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002125 public void testMMSonWiFi() throws Exception {
2126 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002127 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002128 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002129 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002130 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002131 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002132 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002133 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002134
Paul Jensene0988542015-06-25 15:30:08 -04002135 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002136 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2137 final ConditionVariable cv = waitForConnectivityBroadcasts(1);
Paul Jensene0988542015-06-25 15:30:08 -04002138 mWiFiNetworkAgent.connect(true);
2139 waitFor(cv);
2140 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002141
Paul Jensene0988542015-06-25 15:30:08 -04002142 // Register MMS NetworkRequest
2143 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2144 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2145 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2146 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002147
Paul Jensene0988542015-06-25 15:30:08 -04002148 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002149 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002150 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002151 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002152 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002153 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002154
Paul Jensene0988542015-06-25 15:30:08 -04002155 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002156 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002157 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002158 verifyActiveNetwork(TRANSPORT_WIFI);
2159 }
2160
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002161 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002162 public void testMMSonCell() throws Exception {
2163 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002164 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002165 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2166 mCellNetworkAgent.connect(false);
2167 waitFor(cv);
2168 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002169
Paul Jensene0988542015-06-25 15:30:08 -04002170 // Register MMS NetworkRequest
2171 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2172 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2173 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2174 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002175
Paul Jensene0988542015-06-25 15:30:08 -04002176 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002177 TestNetworkAgentWrapper
2178 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002179 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2180 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002181 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002182 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002183
Paul Jensene0988542015-06-25 15:30:08 -04002184 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002185 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002186 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002187 verifyActiveNetwork(TRANSPORT_CELLULAR);
2188 }
2189
lucaslinf3b59b32019-03-26 17:49:49 +08002190 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07002191 @FlakyTest(bugId = 140306320)
Chalard Jeane7b24752019-06-20 16:01:19 +09002192 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002193 // Register network callback.
2194 NetworkRequest request = new NetworkRequest.Builder()
2195 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2196 .build();
2197 TestNetworkCallback callback = new TestNetworkCallback();
2198 mCm.registerNetworkCallback(request, callback);
2199
2200 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002201 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002202 mCellNetworkAgent.connect(true);
2203 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2204
2205 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002206 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002207 mWiFiNetworkAgent.connectWithPartialConnectivity();
2208 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2209 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2210
2211 // Mobile data should be the default network.
2212 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2213 callback.assertNoCallback();
2214
lucaslinf3b59b32019-03-26 17:49:49 +08002215 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2216 // probe.
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002217 mWiFiNetworkAgent.setNetworkPartialValid();
lucasline252a742019-03-12 13:08:03 +08002218 // If the user chooses yes to use this partial connectivity wifi, switch the default
2219 // network to wifi and check if wifi becomes valid or not.
2220 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2221 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002222 // If user accepts partial connectivity network,
2223 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002224 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002225 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002226
lucaslinf3b59b32019-03-26 17:49:49 +08002227 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2228 // validated.
2229 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002230 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002231 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2232 mWiFiNetworkAgent);
2233 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2234 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2235
2236 // Disconnect and reconnect wifi with partial connectivity again.
2237 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002238 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002239 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002240 mWiFiNetworkAgent.connectWithPartialConnectivity();
2241 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2242 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2243
2244 // Mobile data should be the default network.
2245 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2246
2247 // If the user chooses no, disconnect wifi immediately.
2248 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2249 false /* always */);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002250 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002251
2252 // If user accepted partial connectivity before, and device reconnects to that network
2253 // again, but now the network has full connectivity. The network shouldn't contain
2254 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002255 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002256 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002257 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2258 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002259 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002260
lucaslinf3b59b32019-03-26 17:49:49 +08002261 // If user accepted partial connectivity network before,
2262 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2263 // ConnectivityService#updateNetworkInfo().
2264 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002265 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002266 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002267 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002268 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2269 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002270
lucasline252a742019-03-12 13:08:03 +08002271 // Wifi should be the default network.
2272 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2273 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002274 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002275
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002276 // The user accepted partial connectivity and selected "don't ask again". Now the user
2277 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2278 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002279 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002280 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2281 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002282 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002283 // If user accepted partial connectivity network before,
2284 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2285 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002286 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002287 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002288 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002289 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002290 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002291 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2292 mWiFiNetworkAgent.setNetworkValid();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002293
lucaslinf3b59b32019-03-26 17:49:49 +08002294 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2295 // validated.
2296 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2297 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2298 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002299 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002300
2301 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2302 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002303 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002304 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2305 true /* acceptUnvalidated */);
2306
2307 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2308 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2309 // notifyNetworkConnected.
2310 mWiFiNetworkAgent.connectWithPartialValidConnectivity();
2311 waitForIdle();
2312 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2313 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002314 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002315 callback.expectCapabilitiesWith(
2316 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2317 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002318 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002319 }
2320
2321 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002322 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002323 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2324 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2325 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2326 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2327
2328 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2329 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2330 .addCapability(NET_CAPABILITY_VALIDATED).build();
2331 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2332
2333 // Bring up a network with a captive portal.
2334 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002335 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002336 String redirectUrl = "http://android.com/path";
2337 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002338 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002339 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002340
2341 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2342 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2343 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2344 .launchCaptivePortalApp();
2345
2346 // Report that the captive portal is dismissed with partial connectivity, and check that
2347 // callbacks are fired.
2348 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002349 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002350 waitForIdle();
2351 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2352 mWiFiNetworkAgent);
2353
2354 // Report partial connectivity is accepted.
2355 mWiFiNetworkAgent.setNetworkPartialValid();
2356 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2357 false /* always */);
2358 waitForIdle();
2359 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002360 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002361 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2362 NetworkCapabilities nc =
2363 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2364 mWiFiNetworkAgent);
2365
2366 mCm.unregisterNetworkCallback(captivePortalCallback);
2367 mCm.unregisterNetworkCallback(validatedCallback);
2368 }
2369
2370 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002371 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002372 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2373 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2374 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2375 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2376
2377 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2378 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2379 .addCapability(NET_CAPABILITY_VALIDATED).build();
2380 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002381
2382 // Bring up a network with a captive portal.
2383 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002384 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002385 String firstRedirectUrl = "http://example.com/firstPath";
2386 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002387 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002388 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002389
2390 // Take down network.
2391 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002392 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002393 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002394
2395 // Bring up a network with a captive portal.
2396 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002397 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002398 String secondRedirectUrl = "http://example.com/secondPath";
2399 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002400 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002401 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002402
2403 // Make captive portal disappear then revalidate.
2404 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002405 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002406 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002407 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002408
2409 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002410 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002411 // Expect no notification to be shown when captive portal disappears by itself
2412 verify(mNotificationManager, never()).notifyAsUser(
2413 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002414
2415 // Break network connectivity.
2416 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002417 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002418 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002419 validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002420 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002421
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002422 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002423 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002424 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2425 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2426 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2427 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2428
2429 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2430 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2431 .addCapability(NET_CAPABILITY_VALIDATED).build();
2432 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2433
2434 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002435 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002436 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002437 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002438 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2439
2440 // Check that calling startCaptivePortalApp does nothing.
2441 final int fastTimeoutMs = 100;
2442 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002443 waitForIdle();
2444 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002445 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2446
2447 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002448 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002449 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002450 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002451 validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002452
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002453 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002454 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002455 waitForIdle();
2456 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2457
2458 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2459 final Bundle testBundle = new Bundle();
2460 final String testKey = "testkey";
2461 final String testValue = "testvalue";
2462 testBundle.putString(testKey, testValue);
2463 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2464 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2465 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2466 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002467
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002468 // Report that the captive portal is dismissed, and check that callbacks are fired
2469 mWiFiNetworkAgent.setNetworkValid();
2470 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002471 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002472 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002473 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2474 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002475
2476 mCm.unregisterNetworkCallback(validatedCallback);
2477 mCm.unregisterNetworkCallback(captivePortalCallback);
2478 }
2479
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002480 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002481 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002482 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2483 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2484 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2485 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2486
2487 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2488 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2489 .addCapability(NET_CAPABILITY_VALIDATED).build();
2490 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2491
2492 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2493 // Bring up a network with a captive portal.
2494 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002495 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002496 String firstRedirectUrl = "http://example.com/firstPath";
2497
Calvin On1f64f3f2016-10-11 15:10:46 -07002498 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002499 mWiFiNetworkAgent.expectDisconnected();
2500 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002501
2502 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002503 }
2504
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002505 private NetworkRequest.Builder newWifiRequestBuilder() {
2506 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2507 }
2508
Etan Cohen836ad572018-12-30 17:59:59 -08002509 /**
2510 * Verify request matching behavior with network specifiers.
2511 *
2512 * Note: this test is somewhat problematic since it involves removing capabilities from
2513 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2514 * as a WTF bug in
2515 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2516 * does work.
2517 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002518 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002519 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002520 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2521 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2522 Parcelable {
2523 @Override
2524 public boolean satisfiedBy(NetworkSpecifier other) {
2525 return true;
2526 }
2527
2528 @Override
2529 public int describeContents() {
2530 return 0;
2531 }
2532
2533 @Override
2534 public void writeToParcel(Parcel dest, int flags) {}
2535
2536 @Override
2537 public NetworkSpecifier redact() {
2538 return null;
2539 }
2540 }
2541
2542 // A network specifier that matches either another LocalNetworkSpecifier with the same
2543 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2544 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2545 private String mString;
2546
2547 LocalStringNetworkSpecifier(String string) {
2548 mString = string;
2549 }
2550
2551 @Override
2552 public boolean satisfiedBy(NetworkSpecifier other) {
2553 if (other instanceof LocalStringNetworkSpecifier) {
2554 return TextUtils.equals(mString,
2555 ((LocalStringNetworkSpecifier) other).mString);
2556 }
2557 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2558 return false;
2559 }
2560
2561 @Override
2562 public int describeContents() {
2563 return 0;
2564 }
2565 @Override
2566 public void writeToParcel(Parcel dest, int flags) {}
2567 }
2568
2569
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002570 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002571 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002572 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002573 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2574 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002575 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2576 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002577 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002578 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002579
2580 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2581 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2582 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002583 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002584 TestNetworkCallback cFoo = new TestNetworkCallback();
2585 TestNetworkCallback cBar = new TestNetworkCallback();
2586 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002587 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002588
2589 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2590 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2591 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002592 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002593 mCm.registerNetworkCallback(rFoo, cFoo);
2594 mCm.registerNetworkCallback(rBar, cBar);
2595
Etan Cohen836ad572018-12-30 17:59:59 -08002596 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2597 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2598
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002599 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002600 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002601 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2602 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2603 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2604 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002605 assertNoCallbacks(cFoo, cBar);
2606
Etan Cohen836ad572018-12-30 17:59:59 -08002607 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002608 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002609 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002610 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2611 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002612 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002613 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2614 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002615 assertEquals(nsFoo,
2616 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002617 cFoo.assertNoCallback();
2618
Etan Cohen836ad572018-12-30 17:59:59 -08002619 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002620 cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002621 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002622 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002623 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2624 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002625 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002626 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2627 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08002628 assertEquals(nsBar,
2629 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2630 cBar.assertNoCallback();
2631
2632 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2633 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2634 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002635 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2636 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002637 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002638 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2639 (caps) -> caps.getNetworkSpecifier() == null);
2640 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2641 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002642 assertNull(
2643 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2644 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002645 cBar.assertNoCallback();
2646
2647 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002648 cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
2649 cBar.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002650 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002651 c.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002652 }
2653
Etan Cohen836ad572018-12-30 17:59:59 -08002654 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002655 }
2656
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002657 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002658 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09002659 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002660 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002661 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09002662 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002663
Chalard Jean751bb3f2019-06-19 23:29:58 +09002664 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002665 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2666 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002667 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002668 mService.requestNetwork(networkCapabilities, null, 0, null,
2669 ConnectivityManager.TYPE_WIFI);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002670 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002671
Etan Cohena7434272017-04-03 12:17:51 -07002672 class NonParcelableSpecifier extends NetworkSpecifier {
2673 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2674 };
2675 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2676 @Override public int describeContents() { return 0; }
2677 @Override public void writeToParcel(Parcel p, int flags) {}
2678 }
Etan Cohena7434272017-04-03 12:17:51 -07002679
Chalard Jean751bb3f2019-06-19 23:29:58 +09002680 final NetworkRequest.Builder builder =
2681 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2682 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002683 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2684 Parcel parcelW = Parcel.obtain();
2685 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002686 });
Etan Cohena7434272017-04-03 12:17:51 -07002687
Chalard Jean751bb3f2019-06-19 23:29:58 +09002688 final NetworkRequest nr =
2689 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
2690 .setNetworkSpecifier(new ParcelableSpecifier())
2691 .build();
Etan Cohena7434272017-04-03 12:17:51 -07002692 assertNotNull(nr);
2693
Chalard Jean751bb3f2019-06-19 23:29:58 +09002694 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002695 Parcel parcelW = Parcel.obtain();
2696 nr.writeToParcel(parcelW, 0);
2697 byte[] bytes = parcelW.marshall();
2698 parcelW.recycle();
2699
2700 Parcel parcelR = Parcel.obtain();
2701 parcelR.unmarshall(bytes, 0, bytes.length);
2702 parcelR.setDataPosition(0);
2703 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002704 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002705 }
2706
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002707 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002708 public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
Etan Cohen859748f2017-04-03 17:42:34 -07002709 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2710 @Override
2711 public boolean satisfiedBy(NetworkSpecifier other) {
2712 return true;
2713 }
2714
2715 @Override
2716 public void assertValidFromUid(int requestorUid) {
2717 throw new SecurityException("failure");
2718 }
2719
2720 @Override
2721 public int describeContents() { return 0; }
2722 @Override
2723 public void writeToParcel(Parcel dest, int flags) {}
2724 }
2725
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002726 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07002727 mWiFiNetworkAgent.connect(false);
2728
2729 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2730 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2731 networkSpecifier).build();
2732 TestNetworkCallback networkCallback = new TestNetworkCallback();
Chalard Jean751bb3f2019-06-19 23:29:58 +09002733 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07002734 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002735 });
Etan Cohen859748f2017-04-03 17:42:34 -07002736 }
2737
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002738 @Test
paulhu3d67f532019-03-22 16:35:06 +08002739 public void testInvalidSignalStrength() {
2740 NetworkRequest r = new NetworkRequest.Builder()
2741 .addCapability(NET_CAPABILITY_INTERNET)
2742 .addTransportType(TRANSPORT_WIFI)
2743 .setSignalStrength(-75)
2744 .build();
2745 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
2746 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002747 assertThrows(SecurityException.class, () ->
2748 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002749
Chalard Jean751bb3f2019-06-19 23:29:58 +09002750 assertThrows(SecurityException.class, () ->
2751 mCm.registerNetworkCallback(r, PendingIntent.getService(
2752 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002753
2754 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002755 assertThrows(IllegalArgumentException.class, () ->
2756 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002757
Chalard Jean751bb3f2019-06-19 23:29:58 +09002758 assertThrows(IllegalArgumentException.class, () ->
2759 mCm.requestNetwork(r, PendingIntent.getService(
2760 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002761 }
2762
2763 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002764 public void testRegisterDefaultNetworkCallback() throws Exception {
2765 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2766 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2767 defaultNetworkCallback.assertNoCallback();
2768
2769 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2770 // whenever Wi-Fi is up. Without this, the mobile network agent is
2771 // reaped before any other activity can take place.
2772 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2773 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2774 .addTransportType(TRANSPORT_CELLULAR).build();
2775 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2776 cellNetworkCallback.assertNoCallback();
2777
2778 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002779 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002780 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002781 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2782 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002783 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002784
2785 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002786 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09002787 mWiFiNetworkAgent.connect(true);
2788 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002789 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002790 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002791
2792 // Bring down cell. Expect no default network callback, since it wasn't the default.
2793 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002794 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002795 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002796 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002797
2798 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002799 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002800 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002801 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002802 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002803 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002804
2805 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2806 // followed by AVAILABLE cell.
2807 mWiFiNetworkAgent.disconnect();
2808 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002809 defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002810 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002811 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002812 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
2813 defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002814 waitForIdle();
2815 assertEquals(null, mCm.getActiveNetwork());
2816
2817 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002818 final TestNetworkAgentWrapper
2819 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002820 final ArraySet<UidRange> ranges = new ArraySet<>();
2821 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002822 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2823 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002824 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002825 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002826 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2827 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2828
2829 vpnNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002830 defaultNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002831 waitForIdle();
2832 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002833 }
2834
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002835 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002836 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002837 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002838 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002839 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2840 .addTransportType(TRANSPORT_CELLULAR).build();
2841 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2842
2843 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002844 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09002845 mCellNetworkAgent.connect(true);
2846
Erik Kline1d3db322017-02-28 16:20:20 +09002847 // We should get onAvailable(), onCapabilitiesChanged(), and
2848 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2849 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002850 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002851 cellNetworkCallback.assertNoCallback();
2852
2853 // Update LinkProperties.
2854 final LinkProperties lp = new LinkProperties();
2855 lp.setInterfaceName("foonet_data0");
2856 mCellNetworkAgent.sendLinkProperties(lp);
2857 // We should get onLinkPropertiesChanged().
Chalard Jean6f4216f2019-06-05 01:40:32 +09002858 cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
2859 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002860 cellNetworkCallback.assertNoCallback();
2861
Erik Kline1d3db322017-02-28 16:20:20 +09002862 // Suspend the network.
2863 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002864 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
2865 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002866 cellNetworkCallback.expectCallback(CallbackRecord.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002867 cellNetworkCallback.assertNoCallback();
2868
Erik Klineacdd6392016-07-07 16:50:58 +09002869 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09002870 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002871 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002872 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2873 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002874 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09002875 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002876 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2877
2878 mCellNetworkAgent.resume();
2879 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
2880 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002881 cellNetworkCallback.expectCallback(CallbackRecord.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09002882 cellNetworkCallback.assertNoCallback();
2883
2884 dfltNetworkCallback = new TestNetworkCallback();
2885 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2886 // This time onNetworkSuspended should not be called.
2887 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2888 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002889
Erik Klineacdd6392016-07-07 16:50:58 +09002890 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2891 mCm.unregisterNetworkCallback(cellNetworkCallback);
2892 }
2893
Calvin On1f64f3f2016-10-11 15:10:46 -07002894 private void setCaptivePortalMode(int mode) {
2895 ContentResolver cr = mServiceContext.getContentResolver();
2896 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2897 }
2898
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002899 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002900 ContentResolver cr = mServiceContext.getContentResolver();
2901 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002902 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09002903 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002904 }
2905
Erik Kline79c6d052018-03-21 07:18:33 -07002906 private void setPrivateDnsSettings(String mode, String specifier) {
2907 final ContentResolver cr = mServiceContext.getContentResolver();
2908 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
2909 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
2910 mService.updatePrivateDnsSettings();
2911 waitForIdle();
2912 }
2913
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002914 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002915 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2916 assertNotNull(nc);
2917 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2918 }
2919
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002920 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002921 public void testBackgroundNetworks() throws Exception {
2922 // Create a background request. We can't do this ourselves because ConnectivityService
2923 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002924 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002925 final NetworkRequest request = new NetworkRequest.Builder().build();
2926 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2927 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2928 final TestNetworkCallback callback = new TestNetworkCallback();
2929 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2930 mCm.registerNetworkCallback(request, callback);
2931 mCm.registerNetworkCallback(fgRequest, fgCallback);
2932
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002933 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002934 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002935 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2936 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002937 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2938
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002939 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002940 mWiFiNetworkAgent.connect(true);
2941
2942 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002943 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002944 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002945 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002946 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002947 fgCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002948 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002949 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2950 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2951
2952 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09002953 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002954 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean6f4216f2019-06-05 01:40:32 +09002955 fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09002956 // Expect a network capabilities update sans FOREGROUND.
2957 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002958 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2959 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2960
2961 // File a cell request and check that cell comes into the foreground.
2962 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2963 .addTransportType(TRANSPORT_CELLULAR).build();
2964 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2965 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002966 // NOTE: This request causes the network's capabilities to change. This
2967 // is currently delivered before the onAvailable() callbacks.
2968 // TODO: Fix this.
2969 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002970 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2971 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002972 // Expect a network capabilities update with FOREGROUND, because the most recent
2973 // request causes its state to change.
2974 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002975 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2976 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2977
2978 // Release the request. The network immediately goes into the background, since it was not
2979 // lingering.
2980 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002981 fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002982 // Expect a network capabilities update sans FOREGROUND.
2983 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002984 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2985 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2986
2987 // Disconnect wifi and check that cell is foreground again.
2988 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002989 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
2990 fgCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002991 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002992 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2993
2994 mCm.unregisterNetworkCallback(callback);
2995 mCm.unregisterNetworkCallback(fgCallback);
2996 }
2997
Hugo Benichi849b81b2017-05-25 13:42:31 +09002998 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09002999 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003000 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003001 // Benchmarks connecting and switching performance in the presence of a large number of
3002 // NetworkRequests.
3003 // 1. File NUM_REQUESTS requests.
3004 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3005 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3006 // and NUM_REQUESTS onAvailable callbacks to fire.
3007 // See how long it took.
3008 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003009 final int REGISTER_TIME_LIMIT_MS = 200;
3010 final int CONNECT_TIME_LIMIT_MS = 60;
3011 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003012 final int UNREGISTER_TIME_LIMIT_MS = 20;
3013
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003014 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3015 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3016 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3017 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3018
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003019 for (int i = 0; i < NUM_REQUESTS; i++) {
3020 callbacks[i] = new NetworkCallback() {
3021 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3022 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3023 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003024 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003025
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003026 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003027 for (NetworkCallback cb : callbacks) {
3028 mCm.registerNetworkCallback(request, cb);
3029 }
3030 });
3031
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003032 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003033 // Don't request that the network validate, because otherwise connect() will block until
3034 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3035 // and we won't actually measure anything.
3036 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003037
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003038 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003039 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003040 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003041 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3042 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3043 onAvailableDispatchingDuration));
3044 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3045 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3046 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003047
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003048 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003049 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003050 mWiFiNetworkAgent.adjustScore(40);
3051 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003052
3053 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003054 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003055 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003056 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3057 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3058 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3059 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3060 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003061
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003062 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003063 for (NetworkCallback cb : callbacks) {
3064 mCm.unregisterNetworkCallback(cb);
3065 }
3066 });
3067 }
3068
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003069 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003070 public void testMobileDataAlwaysOn() throws Exception {
3071 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3072 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3073 .addTransportType(TRANSPORT_CELLULAR).build();
3074 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3075
3076 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3077 handlerThread.start();
3078 NetworkCapabilities filter = new NetworkCapabilities()
3079 .addTransportType(TRANSPORT_CELLULAR)
3080 .addCapability(NET_CAPABILITY_INTERNET);
3081 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3082 mServiceContext, "testFactory", filter);
3083 testFactory.setScoreFilter(40);
3084
3085 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003086 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003087 testFactory.register();
3088 testFactory.waitForNetworkRequests(1);
3089 assertTrue(testFactory.getMyStartRequested());
3090
3091 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003092 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003093 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3094 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003095 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003096 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003097 assertFalse(testFactory.getMyStartRequested());
3098
3099 ContentResolver cr = mServiceContext.getContentResolver();
3100
3101 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003102 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003103 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003104 testFactory.waitForNetworkRequests(2);
3105 assertTrue(testFactory.getMyStartRequested());
3106
3107 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003108 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003109 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003110 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003111 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003112 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003113 testFactory.waitForNetworkRequests(2);
3114 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3115
3116 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003117 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003118 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003119 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003120
3121 // Turn off mobile data always on and expect the request to disappear...
3122 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003123 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003124 testFactory.waitForNetworkRequests(1);
3125
3126 // ... and cell data to be torn down.
Chalard Jean6f4216f2019-06-05 01:40:32 +09003127 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003128 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003129
3130 testFactory.unregister();
3131 mCm.unregisterNetworkCallback(cellNetworkCallback);
3132 handlerThread.quit();
3133 }
3134
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003135 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003136 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003137 final ContentResolver cr = mServiceContext.getContentResolver();
3138 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3139
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003140 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003141 String[] values = new String[] {null, "0", "1"};
3142 for (int i = 0; i < values.length; i++) {
3143 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003144 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003145 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003146 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003147 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003148 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003149 }
3150
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003151 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003152
3153 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003154 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003155 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003156 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003157 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003158
3159 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003160 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003161 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003162 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003163 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003164
3165 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003166 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003167 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003168 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003169 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003170 }
3171
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003172 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003173 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003174 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003175
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003176 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003177 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003178
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003179 // File a request for cell to ensure it doesn't go down.
3180 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3181 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3182 .addTransportType(TRANSPORT_CELLULAR).build();
3183 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3184
3185 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3186 mCm.registerDefaultNetworkCallback(defaultCallback);
3187
3188 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3189 .addTransportType(TRANSPORT_WIFI)
3190 .addCapability(NET_CAPABILITY_VALIDATED)
3191 .build();
3192 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3193 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3194
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003195 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003196 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003197
3198 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003199 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003200 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003201 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3202 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003203 Network cellNetwork = mCellNetworkAgent.getNetwork();
3204
3205 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003206 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003207 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003208 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3209 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003210 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3211
3212 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003213 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003214 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003215 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09003216 validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003217
3218 // Because avoid bad wifi is off, we don't switch to cellular.
3219 defaultCallback.assertNoCallback();
3220 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3221 NET_CAPABILITY_VALIDATED));
3222 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3223 NET_CAPABILITY_VALIDATED));
3224 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3225
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003226 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3227 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003228 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3229 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003230 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003231 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3232
3233 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003234 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3235 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003236 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003237 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3238
3239 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3240 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003241 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003242 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3243 NET_CAPABILITY_VALIDATED));
3244 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3245 NET_CAPABILITY_VALIDATED));
3246 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3247
3248 // Disconnect and reconnect wifi to clear the one-time switch above.
3249 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003250 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003251 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003252 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3253 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003254 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3255
3256 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003257 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003258 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003259 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09003260 validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003261
3262 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003263 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003264 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003265
3266 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003267 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003268 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3269 NET_CAPABILITY_VALIDATED));
3270 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3271 NET_CAPABILITY_VALIDATED));
3272 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3273
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003274 // Simulate the user turning the cellular fallback setting off and then on.
3275 // We switch to wifi and then to cell.
3276 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003277 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003278 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003279 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3280 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003281 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003282 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003283 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3284
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003285 // If cell goes down, we switch to wifi.
3286 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09003287 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003288 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003289 validatedWifiCallback.assertNoCallback();
3290
3291 mCm.unregisterNetworkCallback(cellNetworkCallback);
3292 mCm.unregisterNetworkCallback(validatedWifiCallback);
3293 mCm.unregisterNetworkCallback(defaultCallback);
3294 }
3295
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003296 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003297 public void testMeteredMultipathPreferenceSetting() throws Exception {
3298 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003299 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3300
3301 for (int config : Arrays.asList(0, 3, 2)) {
3302 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003303 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003304 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003305 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003306 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003307
3308 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3309 String msg = String.format("config=%d, setting=%s", config, setting);
3310 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3311 }
3312 }
3313 }
3314
Erik Kline3841a482015-11-25 12:49:38 +09003315 /**
3316 * Validate that a satisfied network request does not trigger onUnavailable() once the
3317 * time-out period expires.
3318 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003319 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003320 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003321 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3322 NetworkCapabilities.TRANSPORT_WIFI).build();
3323 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003324 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003325
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003326 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003327 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003328 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003329 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003330
3331 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003332 networkCallback.assertNoCallback();
3333 }
3334
3335 /**
3336 * Validate that a satisfied network request followed by a disconnected (lost) network does
3337 * not trigger onUnavailable() once the time-out period expires.
3338 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003339 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003340 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003341 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3342 NetworkCapabilities.TRANSPORT_WIFI).build();
3343 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003344 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003345
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003346 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003347 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003348 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003349 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003350 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09003351 networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003352
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003353 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003354 networkCallback.assertNoCallback();
3355 }
3356
3357 /**
3358 * Validate that when a time-out is specified for a network request the onUnavailable()
3359 * callback is called when time-out expires. Then validate that if network request is
3360 * (somehow) satisfied - the callback isn't called later.
3361 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003362 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003363 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003364 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3365 NetworkCapabilities.TRANSPORT_WIFI).build();
3366 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003367 final int timeoutMs = 10;
3368 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003369
3370 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean6f4216f2019-06-05 01:40:32 +09003371 networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003372
3373 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003374 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003375 mWiFiNetworkAgent.connect(false);
3376 networkCallback.assertNoCallback();
3377 }
3378
3379 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003380 * Validate that when a network request is unregistered (cancelled), no posterior event can
3381 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003382 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003383 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003384 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003385 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3386 NetworkCapabilities.TRANSPORT_WIFI).build();
3387 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003388 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003389
Hugo Benichidfb559a2016-12-20 14:57:49 +09003390 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003391 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003392 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3393 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003394 networkCallback.assertNoCallback();
3395
3396 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003397 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003398 mWiFiNetworkAgent.connect(false);
3399 networkCallback.assertNoCallback();
3400 }
3401
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003402 @Test
3403 public void testUnfulfillableNetworkRequest() throws Exception {
3404 runUnfulfillableNetworkRequest(false);
3405 }
3406
3407 @Test
3408 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3409 runUnfulfillableNetworkRequest(true);
3410 }
3411
Etan Cohenddb720a2019-01-08 12:09:18 -08003412 /**
3413 * Validate the callback flow for a factory releasing a request as unfulfillable.
3414 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003415 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003416 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3417 NetworkCapabilities.TRANSPORT_WIFI).build();
3418 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3419
3420 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3421 handlerThread.start();
3422 NetworkCapabilities filter = new NetworkCapabilities()
3423 .addTransportType(TRANSPORT_WIFI)
3424 .addCapability(NET_CAPABILITY_INTERNET);
3425 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3426 mServiceContext, "testFactory", filter);
3427 testFactory.setScoreFilter(40);
3428
3429 // Register the factory and expect it to receive the default request.
Chalard Jean05ab6812018-05-02 21:14:54 +09003430 testFactory.expectAddRequestsWithScores(0); // default request score is 0, not served yet
Etan Cohenddb720a2019-01-08 12:09:18 -08003431 testFactory.register();
3432 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3433
3434 assertEquals(1, requests.size()); // have 1 request at this point
3435 int origRequestId = requests.valueAt(0).requestId;
3436
3437 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003438 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003439 mCm.requestNetwork(nr, networkCallback);
3440 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3441
3442 int newRequestId = 0;
3443 for (int i = 0; i < requests.size(); ++i) {
3444 if (requests.valueAt(i).requestId != origRequestId) {
3445 newRequestId = requests.valueAt(i).requestId;
3446 break;
3447 }
3448 }
3449
Etan Cohen22e0fc12019-05-23 08:16:20 -07003450 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003451 if (preUnregister) {
3452 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003453
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003454 // Simulate the factory releasing the request as unfulfillable: no-op since
3455 // the callback has already been unregistered (but a test that no exceptions are
3456 // thrown).
3457 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3458 } else {
3459 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003460 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3461
Chalard Jean6f4216f2019-06-05 01:40:32 +09003462 networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003463 testFactory.waitForRequests();
3464
3465 // unregister network callback - a no-op (since already freed by the
3466 // on-unavailable), but should not fail or throw exceptions.
3467 mCm.unregisterNetworkCallback(networkCallback);
3468 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003469
Etan Cohenddb720a2019-01-08 12:09:18 -08003470 testFactory.unregister();
3471 handlerThread.quit();
3472 }
3473
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003474 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3475
Chalard Jeane7b24752019-06-20 16:01:19 +09003476 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003477
3478 private class CallbackValue {
3479 public CallbackType callbackType;
3480 public int error;
3481
3482 public CallbackValue(CallbackType type) {
3483 this.callbackType = type;
3484 this.error = PacketKeepalive.SUCCESS;
3485 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3486 }
3487
3488 public CallbackValue(CallbackType type, int error) {
3489 this.callbackType = type;
3490 this.error = error;
3491 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3492 }
3493
3494 @Override
3495 public boolean equals(Object o) {
3496 return o instanceof CallbackValue &&
3497 this.callbackType == ((CallbackValue) o).callbackType &&
3498 this.error == ((CallbackValue) o).error;
3499 }
3500
3501 @Override
3502 public String toString() {
3503 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3504 }
3505 }
3506
junyulai7c469172019-01-16 20:23:34 +08003507 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003508
3509 @Override
3510 public void onStarted() {
3511 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3512 }
3513
3514 @Override
3515 public void onStopped() {
3516 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3517 }
3518
3519 @Override
3520 public void onError(int error) {
3521 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3522 }
3523
Chalard Jeane7b24752019-06-20 16:01:19 +09003524 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3525 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003526 }
3527
Chalard Jeane7b24752019-06-20 16:01:19 +09003528 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003529 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3530 }
3531
Chalard Jeane7b24752019-06-20 16:01:19 +09003532 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003533 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3534 }
3535
Chalard Jeane7b24752019-06-20 16:01:19 +09003536 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003537 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3538 }
3539 }
3540
junyulai48eac1d42018-12-27 17:25:29 +08003541 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3542
3543 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3544
3545 private class CallbackValue {
3546 public CallbackType callbackType;
3547 public int error;
3548
3549 CallbackValue(CallbackType type) {
3550 this.callbackType = type;
3551 this.error = SocketKeepalive.SUCCESS;
3552 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3553 }
3554
3555 CallbackValue(CallbackType type, int error) {
3556 this.callbackType = type;
3557 this.error = error;
3558 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3559 }
3560
3561 @Override
3562 public boolean equals(Object o) {
3563 return o instanceof CallbackValue
3564 && this.callbackType == ((CallbackValue) o).callbackType
3565 && this.error == ((CallbackValue) o).error;
3566 }
3567
3568 @Override
3569 public String toString() {
3570 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3571 error);
3572 }
3573 }
3574
3575 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003576 private final Executor mExecutor;
3577
3578 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3579 mExecutor = executor;
3580 }
junyulai48eac1d42018-12-27 17:25:29 +08003581
3582 @Override
3583 public void onStarted() {
3584 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3585 }
3586
3587 @Override
3588 public void onStopped() {
3589 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3590 }
3591
3592 @Override
3593 public void onError(int error) {
3594 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3595 }
3596
Chalard Jeane7b24752019-06-20 16:01:19 +09003597 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3598 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3599
junyulai48eac1d42018-12-27 17:25:29 +08003600 }
3601
Chalard Jeane7b24752019-06-20 16:01:19 +09003602 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003603 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3604 }
3605
Chalard Jeane7b24752019-06-20 16:01:19 +09003606 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003607 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3608 }
3609
Chalard Jeane7b24752019-06-20 16:01:19 +09003610 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003611 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3612 }
junyulai7c469172019-01-16 20:23:34 +08003613
3614 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003615 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003616 CallbackValue cv = mCallbacks.peek();
3617 assertNull("Unexpected callback: " + cv, cv);
3618 }
junyulai48eac1d42018-12-27 17:25:29 +08003619 }
3620
Chalard Jeane7b24752019-06-20 16:01:19 +09003621 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003622 // Ensure the network is disconnected before we do anything.
3623 if (mWiFiNetworkAgent != null) {
3624 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3625 }
3626
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003627 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003628 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3629 mWiFiNetworkAgent.connect(true);
3630 waitFor(cv);
3631 verifyActiveNetwork(TRANSPORT_WIFI);
3632 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003633 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003634 return mWiFiNetworkAgent.getNetwork();
3635 }
3636
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003637 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003638 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003639 public void testPacketKeepalives() throws Exception {
3640 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3641 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3642 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3643 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3644 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3645
Nathan Harold63dd8132018-02-14 13:09:45 -08003646 final int validKaInterval = 15;
3647 final int invalidKaInterval = 9;
3648
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003649 LinkProperties lp = new LinkProperties();
3650 lp.setInterfaceName("wlan12");
3651 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3652 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3653 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3654 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3655
3656 Network notMyNet = new Network(61234);
3657 Network myNet = connectKeepaliveNetwork(lp);
3658
3659 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3660 PacketKeepalive ka;
3661
3662 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003663 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003664 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3665
Nathan Harold63dd8132018-02-14 13:09:45 -08003666 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003667 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3668
Nathan Harold63dd8132018-02-14 13:09:45 -08003669 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003670 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3671
Nathan Harold63dd8132018-02-14 13:09:45 -08003672 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003673 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3674
Nathan Harold63dd8132018-02-14 13:09:45 -08003675 // NAT-T is only supported for IPv4.
3676 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3677 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003678
Nathan Harold63dd8132018-02-14 13:09:45 -08003679 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003680 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3681
Nathan Harold63dd8132018-02-14 13:09:45 -08003682 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003683 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3684
Nathan Harold63dd8132018-02-14 13:09:45 -08003685 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003686 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3687
Nathan Harold63dd8132018-02-14 13:09:45 -08003688 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003689 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3690
3691 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003692 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003693 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003694 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003695 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003696 ka.stop();
3697 callback.expectStopped();
3698
3699 // Check that deleting the IP address stops the keepalive.
3700 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003701 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003702 callback.expectStarted();
3703 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3704 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3705 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3706 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3707 mWiFiNetworkAgent.sendLinkProperties(lp);
3708
3709 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003710 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003711 callback.expectStarted();
3712 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003713 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003714 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3715
3716 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003717 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003718 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003719 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003720 ka.stop();
3721
3722 // Reconnect.
3723 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003724 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003725
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003726 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3727 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003728 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003729 callback.expectStarted();
3730
3731 // The second one gets slot 2.
3732 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3733 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003734 PacketKeepalive ka2 = mCm.startNattKeepalive(
3735 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003736 callback2.expectStarted();
3737
3738 // Now stop the first one and create a third. This also gets slot 1.
3739 ka.stop();
3740 callback.expectStopped();
3741
3742 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3743 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003744 PacketKeepalive ka3 = mCm.startNattKeepalive(
3745 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003746 callback3.expectStarted();
3747
3748 ka2.stop();
3749 callback2.expectStopped();
3750
3751 ka3.stop();
3752 callback3.expectStopped();
3753 }
Udam Sainib7c24872016-01-04 12:16:14 -08003754
Xiao Maa4637112019-02-07 15:03:57 +09003755 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09003756 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
3757 throws Exception {
junyulai06835112019-01-03 18:50:15 +08003758 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09003759 final Executor executorInline = (Runnable r) -> r.run();
3760 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08003761 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09003762 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003763 }
junyulai06835112019-01-03 18:50:15 +08003764
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003765 @Test
junyulaiafe9b492019-03-19 18:50:23 +08003766 public void testNattSocketKeepalives() throws Exception {
3767 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
3768 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08003769 }
3770
3771 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003772 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08003773 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08003774 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08003775 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3776 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3777 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3778 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3779 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3780
3781 final int validKaInterval = 15;
3782 final int invalidKaInterval = 9;
3783
3784 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08003785 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
3786 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08003787
junyulai48eac1d42018-12-27 17:25:29 +08003788 LinkProperties lp = new LinkProperties();
3789 lp.setInterfaceName("wlan12");
3790 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3791 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3792 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3793 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3794
3795 Network notMyNet = new Network(61234);
3796 Network myNet = connectKeepaliveNetwork(lp);
3797
junyulai7c469172019-01-16 20:23:34 +08003798 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08003799
3800 // Attempt to start keepalives with invalid parameters and check for errors.
3801 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08003802 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3803 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3804 ka.start(validKaInterval);
3805 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3806 }
junyulai48eac1d42018-12-27 17:25:29 +08003807
3808 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08003809 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3810 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3811 ka.start(invalidKaInterval);
3812 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3813 }
junyulai48eac1d42018-12-27 17:25:29 +08003814
3815 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08003816 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3817 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
3818 ka.start(validKaInterval);
3819 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3820 }
junyulai48eac1d42018-12-27 17:25:29 +08003821
3822 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08003823 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3824 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
3825 ka.start(validKaInterval);
3826 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3827 }
junyulai48eac1d42018-12-27 17:25:29 +08003828
3829 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08003830 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3831 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
3832 ka.start(validKaInterval);
3833 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3834 }
junyulai48eac1d42018-12-27 17:25:29 +08003835
3836 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08003837 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3838 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3839 ka.start(validKaInterval);
3840 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
3841 }
junyulai48eac1d42018-12-27 17:25:29 +08003842
3843 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003844 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08003845 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3846 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3847 ka.start(validKaInterval);
3848 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003849 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08003850 ka.stop();
3851 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08003852
junyulai0c666972019-03-04 22:45:36 +08003853 // Check that keepalive could be restarted.
3854 ka.start(validKaInterval);
3855 callback.expectStarted();
3856 ka.stop();
3857 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08003858
junyulai0c666972019-03-04 22:45:36 +08003859 // Check that keepalive can be restarted without waiting for callback.
3860 ka.start(validKaInterval);
3861 callback.expectStarted();
3862 ka.stop();
3863 ka.start(validKaInterval);
3864 callback.expectStopped();
3865 callback.expectStarted();
3866 ka.stop();
3867 callback.expectStopped();
3868 }
junyulai7c469172019-01-16 20:23:34 +08003869
junyulai48eac1d42018-12-27 17:25:29 +08003870 // Check that deleting the IP address stops the keepalive.
3871 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08003872 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3873 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3874 ka.start(validKaInterval);
3875 callback.expectStarted();
3876 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3877 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3878 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3879 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3880 mWiFiNetworkAgent.sendLinkProperties(lp);
3881 }
junyulai48eac1d42018-12-27 17:25:29 +08003882
3883 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08003884 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3885 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3886 ka.start(validKaInterval);
3887 callback.expectStarted();
3888 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003889 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08003890 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08003891
junyulai0c666972019-03-04 22:45:36 +08003892 // ... and that stopping it after that has no adverse effects.
3893 waitForIdle();
3894 final Network myNetAlias = myNet;
3895 assertNull(mCm.getNetworkCapabilities(myNetAlias));
3896 ka.stop();
3897 callback.assertNoCallback();
3898 }
junyulai48eac1d42018-12-27 17:25:29 +08003899
3900 // Reconnect.
3901 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003902 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08003903
3904 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3905 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08003906 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08003907 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3908 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3909 ka.start(validKaInterval);
3910 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08003911
junyulai0c666972019-03-04 22:45:36 +08003912 // The second one gets slot 2.
3913 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08003914 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
3915 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08003916 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
3917 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
3918 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
3919 ka2.start(validKaInterval);
3920 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08003921
junyulai0c666972019-03-04 22:45:36 +08003922 ka.stop();
3923 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08003924
junyulai0c666972019-03-04 22:45:36 +08003925 ka2.stop();
3926 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08003927
junyulai0c666972019-03-04 22:45:36 +08003928 testSocket.close();
3929 testSocket2.close();
3930 }
3931 }
junyulai06835112019-01-03 18:50:15 +08003932
junyulai15178152019-03-27 11:00:37 +08003933 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08003934 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
3935 // assertFalse(isUdpPortInUse(srcPort));
3936 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08003937
junyulai06835112019-01-03 18:50:15 +08003938 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003939 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09003940 mWiFiNetworkAgent = null;
3941 }
3942
3943 @Test
junyulaiafe9b492019-03-19 18:50:23 +08003944 public void testTcpSocketKeepalives() throws Exception {
3945 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09003946 }
3947
3948 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
3949 final int srcPortV4 = 12345;
3950 final int srcPortV6 = 23456;
3951 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
3952 final InetAddress myIPv6 = InetAddress.getByName("::1");
3953
3954 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09003955
3956 final LinkProperties lp = new LinkProperties();
3957 lp.setInterfaceName("wlan12");
3958 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3959 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3960 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3961 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
3962
3963 final Network notMyNet = new Network(61234);
3964 final Network myNet = connectKeepaliveNetwork(lp);
3965
3966 final Socket testSocketV4 = new Socket();
3967 final Socket testSocketV6 = new Socket();
3968
junyulai7c469172019-01-16 20:23:34 +08003969 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09003970
3971 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
3972 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08003973 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3974 notMyNet, testSocketV4, executor, callback)) {
3975 ka.start(validKaInterval);
3976 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3977 }
Xiao Maa4637112019-02-07 15:03:57 +09003978
3979 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08003980 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3981 myNet, testSocketV4, executor, callback)) {
3982 ka.start(validKaInterval);
3983 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
3984 }
Xiao Maa4637112019-02-07 15:03:57 +09003985
3986 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08003987 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3988 myNet, testSocketV6, executor, callback)) {
3989 ka.start(validKaInterval);
3990 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
3991 }
Xiao Maa4637112019-02-07 15:03:57 +09003992
3993 // Bind the socket address
3994 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
3995 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
3996
3997 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08003998 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3999 myNet, testSocketV4, executor, callback)) {
4000 ka.start(validKaInterval);
4001 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4002 }
Xiao Maa4637112019-02-07 15:03:57 +09004003
4004 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004005 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4006 myNet, testSocketV6, executor, callback)) {
4007 ka.start(validKaInterval);
4008 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4009 }
Xiao Maa4637112019-02-07 15:03:57 +09004010
4011 testSocketV4.close();
4012 testSocketV6.close();
4013
4014 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004015 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004016 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004017 }
4018
junyulai0c666972019-03-04 22:45:36 +08004019 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004020 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4021 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4022 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4023 final int validKaInterval = 15;
4024
4025 // Prepare the target network.
4026 LinkProperties lp = new LinkProperties();
4027 lp.setInterfaceName("wlan12");
4028 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4029 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4030 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004031 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4032 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004033
4034 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4035
4036 // Prepare the target file descriptor, keep only one instance.
4037 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004038 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4039 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004040 final ParcelFileDescriptor testPfd =
4041 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4042 testSocket.close();
4043 assertTrue(isUdpPortInUse(srcPort));
4044
4045 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4046 // block.
4047 try (SocketKeepalive ka = mCm.createNattKeepalive(
4048 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4049 ka.start(validKaInterval);
4050 callback.expectStarted();
4051 ka.stop();
4052 callback.expectStopped();
4053 }
4054
4055 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4056 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4057 // address.
4058 assertTrue(isUdpPortInUse(srcPort));
4059 final InetSocketAddress sa =
4060 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4061 assertEquals(anyIPv4, sa.getAddress());
4062
4063 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004064 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4065 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004066
4067 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004068 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004069 mWiFiNetworkAgent = null;
4070 }
4071
4072 private static boolean isUdpPortInUse(int port) {
4073 try (DatagramSocket ignored = new DatagramSocket(port)) {
4074 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004075 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004076 return true;
4077 }
4078 }
4079
junyulai48eac1d42018-12-27 17:25:29 +08004080 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004081 public void testGetCaptivePortalServerUrl() throws Exception {
4082 String url = mCm.getCaptivePortalServerUrl();
4083 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4084 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004085
4086 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004087 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004088 synchronized(sLock) {
4089 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004090 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004091 }
4092 return sNetwork != null;
4093 }
4094 }
4095
Chalard Jeane7b24752019-06-20 16:01:19 +09004096 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004097 synchronized(sLock) {
4098 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004099 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004100 }
4101 return sNetwork == null;
4102 }
4103 }
4104 }
4105
4106 private void assertPinnedToWifiWithCellDefault() {
4107 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4108 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4109 }
4110
4111 private void assertPinnedToWifiWithWifiDefault() {
4112 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4113 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4114 }
4115
4116 private void assertNotPinnedToWifi() {
4117 assertNull(mCm.getBoundNetworkForProcess());
4118 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4119 }
4120
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004121 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004122 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004123 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4124 .addTransportType(TRANSPORT_WIFI)
4125 .build();
4126 assertNull(mCm.getBoundNetworkForProcess());
4127
4128 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4129 assertNull(mCm.getBoundNetworkForProcess());
4130
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004131 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004132 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004133 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004134 mWiFiNetworkAgent.connect(false);
4135
4136 // When wi-fi connects, expect to be pinned.
4137 assertTrue(TestNetworkPinner.awaitPin(100));
4138 assertPinnedToWifiWithCellDefault();
4139
4140 // Disconnect and expect the pin to drop.
4141 mWiFiNetworkAgent.disconnect();
4142 assertTrue(TestNetworkPinner.awaitUnpin(100));
4143 assertNotPinnedToWifi();
4144
4145 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004146 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004147 mWiFiNetworkAgent.connect(false);
4148 assertFalse(TestNetworkPinner.awaitPin(100));
4149 assertNotPinnedToWifi();
4150
4151 // Pinning while connected causes the pin to take effect immediately.
4152 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4153 assertTrue(TestNetworkPinner.awaitPin(100));
4154 assertPinnedToWifiWithCellDefault();
4155
4156 // Explicitly unpin and expect to use the default network again.
4157 TestNetworkPinner.unpin();
4158 assertNotPinnedToWifi();
4159
4160 // Disconnect cell and wifi.
4161 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4162 mCellNetworkAgent.disconnect();
4163 mWiFiNetworkAgent.disconnect();
4164 waitFor(cv);
4165
4166 // Pinning takes effect even if the pinned network is the default when the pin is set...
4167 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004168 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004169 mWiFiNetworkAgent.connect(false);
4170 assertTrue(TestNetworkPinner.awaitPin(100));
4171 assertPinnedToWifiWithWifiDefault();
4172
4173 // ... and is maintained even when that network is no longer the default.
4174 cv = waitForConnectivityBroadcasts(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004175 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004176 mCellNetworkAgent.connect(true);
4177 waitFor(cv);
4178 assertPinnedToWifiWithCellDefault();
4179 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004180
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004181 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004182 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004183 // We can only have 99 callbacks, because MultipathPolicyTracker is
4184 // already one of them.
4185 final int MAX_REQUESTS = 99;
4186 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004187 final int INTENTS = 10;
4188 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4189
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004190 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004191 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004192
Hugo Benichi893a7622017-09-29 09:34:08 +09004193 int j = 0;
4194 while (j++ < CALLBACKS / 2) {
4195 NetworkCallback cb = new NetworkCallback();
4196 mCm.requestNetwork(networkRequest, cb);
4197 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004198 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004199 while (j++ < CALLBACKS) {
4200 NetworkCallback cb = new NetworkCallback();
4201 mCm.registerNetworkCallback(networkRequest, cb);
4202 registered.add(cb);
4203 }
4204 j = 0;
4205 while (j++ < INTENTS / 2) {
4206 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4207 mCm.requestNetwork(networkRequest, pi);
4208 registered.add(pi);
4209 }
4210 while (j++ < INTENTS) {
4211 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4212 mCm.registerNetworkCallback(networkRequest, pi);
4213 registered.add(pi);
4214 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004215
Hugo Benichi893a7622017-09-29 09:34:08 +09004216 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004217 assertThrows(TooManyRequestsException.class, () ->
4218 mCm.requestNetwork(networkRequest, new NetworkCallback())
4219 );
4220 assertThrows(TooManyRequestsException.class, () ->
4221 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4222 );
4223 assertThrows(TooManyRequestsException.class, () ->
4224 mCm.requestNetwork(networkRequest,
4225 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4226 );
4227 assertThrows(TooManyRequestsException.class, () ->
4228 mCm.registerNetworkCallback(networkRequest,
4229 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4230 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004231
Hugo Benichi893a7622017-09-29 09:34:08 +09004232 for (Object o : registered) {
4233 if (o instanceof NetworkCallback) {
4234 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004235 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004236 if (o instanceof PendingIntent) {
4237 mCm.unregisterNetworkCallback((PendingIntent)o);
4238 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004239 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004240 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004241
4242 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4243 for (int i = 0; i < MAX_REQUESTS; i++) {
4244 NetworkCallback networkCallback = new NetworkCallback();
4245 mCm.requestNetwork(networkRequest, networkCallback);
4246 mCm.unregisterNetworkCallback(networkCallback);
4247 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004248 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004249
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004250 for (int i = 0; i < MAX_REQUESTS; i++) {
4251 NetworkCallback networkCallback = new NetworkCallback();
4252 mCm.registerNetworkCallback(networkRequest, networkCallback);
4253 mCm.unregisterNetworkCallback(networkCallback);
4254 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004255 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004256
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004257 for (int i = 0; i < MAX_REQUESTS; i++) {
4258 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004259 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004260 mCm.requestNetwork(networkRequest, pendingIntent);
4261 mCm.unregisterNetworkCallback(pendingIntent);
4262 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004263 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004264
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004265 for (int i = 0; i < MAX_REQUESTS; i++) {
4266 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004267 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004268 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4269 mCm.unregisterNetworkCallback(pendingIntent);
4270 }
4271 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004272
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004273 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004274 public void testNetworkInfoOfTypeNone() throws Exception {
Hugo Benichi16f0a942017-06-20 14:07:59 +09004275 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4276
4277 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004278 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004279 assertNull(mCm.getActiveNetworkInfo());
4280
4281 Network[] allNetworks = mCm.getAllNetworks();
4282 assertLength(1, allNetworks);
4283 Network network = allNetworks[0];
4284 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4285 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4286
4287 final NetworkRequest request =
4288 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4289 final TestNetworkCallback callback = new TestNetworkCallback();
4290 mCm.registerNetworkCallback(request, callback);
4291
Hugo Benichic1014502017-07-19 10:10:52 +09004292 // Bring up wifi aware network.
4293 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004294 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004295
4296 assertNull(mCm.getActiveNetworkInfo());
4297 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004298 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004299 // of this test. Fix it and uncomment the assert below.
4300 //assertEmpty(mCm.getAllNetworkInfo());
4301
Hugo Benichic1014502017-07-19 10:10:52 +09004302 // Disconnect wifi aware network.
4303 wifiAware.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004304 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackRecord.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004305 mCm.unregisterNetworkCallback(callback);
4306
4307 verifyNoNetwork();
4308 if (broadcastCV.block(10)) {
4309 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4310 }
4311 }
4312
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004313 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004314 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4315 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4316 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4317 assertNull(mCm.getNetworkForType(TYPE_NONE));
4318 assertNull(mCm.getLinkProperties(TYPE_NONE));
4319 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4320
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004321 assertThrows(IllegalArgumentException.class,
4322 () -> { mCm.networkCapabilitiesForType(TYPE_NONE); });
Hugo Benichi16f0a942017-06-20 14:07:59 +09004323
4324 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004325 assertThrows(unsupported, () -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); });
4326 assertThrows(unsupported, () -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); });
Hugo Benichi16f0a942017-06-20 14:07:59 +09004327 // TODO: let test context have configuration application target sdk version
4328 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004329 assertThrows(unsupported, () -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); });
4330 assertThrows(unsupported, () -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); });
4331 assertThrows(unsupported, () -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); });
Hugo Benichi16f0a942017-06-20 14:07:59 +09004332 }
4333
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004334 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004335 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004336 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4337 .addTransportType(TRANSPORT_WIFI).build();
4338 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4339 mCm.registerNetworkCallback(networkRequest, networkCallback);
4340
4341 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004342 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004343 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4344 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4345 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4346 lp.addLinkAddress(myIpv4Address);
4347 lp.addRoute(myIpv4DefaultRoute);
4348
4349 // Verify direct routes are added when network agent is first registered in
4350 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004351 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004352 networkAgent.connect(true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004353 networkCallback.expectCallback(CallbackRecord.AVAILABLE, networkAgent);
4354 networkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, networkAgent);
4355 CallbackRecord.LinkPropertiesChanged cbi =
4356 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004357 networkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004358 networkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004359 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4360 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004361 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004362 Arrays.asList(myIpv4DefaultRoute));
4363 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4364 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4365
4366 // Verify direct routes are added during subsequent link properties updates.
4367 LinkProperties newLp = new LinkProperties(lp);
4368 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4369 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4370 newLp.addLinkAddress(myIpv6Address1);
4371 newLp.addLinkAddress(myIpv6Address2);
4372 networkAgent.sendLinkProperties(newLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004373 cbi = networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004374 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004375 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004376 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4377 Arrays.asList(myIpv4DefaultRoute));
4378 mCm.unregisterNetworkCallback(networkCallback);
4379 }
4380
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004381 @Test
4382 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004383 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4384 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004385
Varun Anandd33cbc62019-02-07 14:13:13 -08004386 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4387 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4388
4389 LinkProperties cellLp = new LinkProperties();
4390 cellLp.setInterfaceName(MOBILE_IFNAME);
4391 LinkProperties wifiLp = new LinkProperties();
4392 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004393
4394 // Simple connection should have updated ifaces
4395 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004396 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004397 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004398 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004399 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4400 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004401 reset(mStatsService);
4402
4403 // Default network switch should update ifaces.
4404 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004405 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004406 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004407 assertEquals(wifiLp, mService.getActiveLinkProperties());
4408 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004409 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4410 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004411 reset(mStatsService);
4412
4413 // Disconnect should update ifaces.
4414 mWiFiNetworkAgent.disconnect();
4415 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004416 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004417 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4418 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004419 reset(mStatsService);
4420
4421 // Metered change should update ifaces
4422 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4423 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004424 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004425 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4426 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004427 reset(mStatsService);
4428
4429 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4430 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004431 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004432 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4433 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004434 reset(mStatsService);
4435
4436 // Captive portal change shouldn't update ifaces
4437 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4438 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004439 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004440 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4441 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004442 reset(mStatsService);
4443
4444 // Roaming change should update ifaces
4445 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4446 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004447 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004448 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4449 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004450 reset(mStatsService);
4451 }
4452
Erik Klinee89953b2018-01-11 16:11:10 +09004453 @Test
4454 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004455 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004456
4457 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004458 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004459
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004460 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004461 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004462 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004463 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004464
4465 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004466 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004467 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4468 // "is-reachable" testing in order to not program netd with unreachable
4469 // nameservers that it might try repeated to validate.
4470 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004471 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4472 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004473 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004474 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4475 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004476 mCellNetworkAgent.sendLinkProperties(cellLp);
4477 mCellNetworkAgent.connect(false);
4478 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004479
4480 verify(mMockDnsResolver, times(1)).createNetworkCache(
4481 eq(mCellNetworkAgent.getNetwork().netId));
4482 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004483 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004484 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004485
4486 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4487 mCellNetworkAgent.sendLinkProperties(cellLp);
4488 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004489 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004490 mResolverParamsParcelCaptor.capture());
4491 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4492 assertEquals(1, resolvrParams.servers.length);
4493 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004494 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004495 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004496 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004497
4498 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4499 mCellNetworkAgent.sendLinkProperties(cellLp);
4500 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004501 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004502 mResolverParamsParcelCaptor.capture());
4503 resolvrParams = mResolverParamsParcelCaptor.getValue();
4504 assertEquals(2, resolvrParams.servers.length);
4505 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004506 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004507 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004508 assertEquals(2, resolvrParams.tlsServers.length);
4509 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004510 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004511 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004512
4513 final String TLS_SPECIFIER = "tls.example.com";
4514 final String TLS_SERVER6 = "2001:db8:53::53";
4515 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4516 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004517 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4518 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4519
Erik Kline117e7f32018-03-04 21:01:01 +09004520 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004521 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004522 mResolverParamsParcelCaptor.capture());
4523 resolvrParams = mResolverParamsParcelCaptor.getValue();
4524 assertEquals(2, resolvrParams.servers.length);
4525 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004526 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004527 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004528 }
4529
Erik Kline79c6d052018-03-21 07:18:33 -07004530 @Test
4531 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004532 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004533 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004534
4535 // The default on Android is opportunistic mode ("Automatic").
4536 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4537
dalyk1fcb7392018-03-05 12:42:22 -05004538 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4539 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4540 .addTransportType(TRANSPORT_CELLULAR).build();
4541 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4542
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004543 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004544 waitForIdle();
4545 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004546 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004547 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004548
4549 final LinkProperties cellLp = new LinkProperties();
4550 cellLp.setInterfaceName(MOBILE_IFNAME);
4551 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4552 // "is-reachable" testing in order to not program netd with unreachable
4553 // nameservers that it might try repeated to validate.
4554 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4555 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4556 MOBILE_IFNAME));
4557 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4558 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4559 MOBILE_IFNAME));
4560 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4561 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4562
4563 mCellNetworkAgent.sendLinkProperties(cellLp);
4564 mCellNetworkAgent.connect(false);
4565 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004566 verify(mMockDnsResolver, times(1)).createNetworkCache(
4567 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004568 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004569 mResolverParamsParcelCaptor.capture());
4570 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4571 assertEquals(2, resolvrParams.tlsServers.length);
4572 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004573 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004574 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004575 assertEquals(2, resolvrParams.tlsServers.length);
4576 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004577 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004578 reset(mMockDnsResolver);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004579 cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
4580 cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004581 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004582 CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4583 CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4584 cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004585 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004586 assertFalse(cbi.getLp().isPrivateDnsActive());
4587 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004588
4589 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004590 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004591 mResolverParamsParcelCaptor.capture());
4592 resolvrParams = mResolverParamsParcelCaptor.getValue();
4593 assertEquals(2, resolvrParams.servers.length);
4594 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004595 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004596 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004597 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004598
4599 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004600 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004601 mResolverParamsParcelCaptor.capture());
4602 resolvrParams = mResolverParamsParcelCaptor.getValue();
4603 assertEquals(2, resolvrParams.servers.length);
4604 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004605 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08004606 assertEquals(2, resolvrParams.tlsServers.length);
4607 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004608 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004609 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004610 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004611
dalyk1fcb7392018-03-05 12:42:22 -05004612 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4613 // Can't test dns configuration for strict mode without properly mocking
4614 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004615 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004616 mCellNetworkAgent);
4617 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004618 assertTrue(cbi.getLp().isPrivateDnsActive());
4619 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004620 }
4621
4622 @Test
4623 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4624 // The default on Android is opportunistic mode ("Automatic").
4625 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4626
4627 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4628 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4629 .addTransportType(TRANSPORT_CELLULAR).build();
4630 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4631
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004632 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05004633 waitForIdle();
4634 LinkProperties lp = new LinkProperties();
4635 mCellNetworkAgent.sendLinkProperties(lp);
4636 mCellNetworkAgent.connect(false);
4637 waitForIdle();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004638 cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
4639 cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004640 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004641 CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4642 CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4643 cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004644 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004645 assertFalse(cbi.getLp().isPrivateDnsActive());
4646 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004647 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004648 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004649
4650 // Send a validation event for a server that is not part of the current
4651 // resolver config. The validation event should be ignored.
4652 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4653 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4654 cellNetworkCallback.assertNoCallback();
4655
4656 // Add a dns server to the LinkProperties.
4657 LinkProperties lp2 = new LinkProperties(lp);
4658 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4659 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004660 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004661 mCellNetworkAgent);
4662 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004663 assertFalse(cbi.getLp().isPrivateDnsActive());
4664 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004665 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004666 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004667
4668 // Send a validation event containing a hostname that is not part of
4669 // the current resolver config. The validation event should be ignored.
4670 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4671 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4672 cellNetworkCallback.assertNoCallback();
4673
4674 // Send a validation event where validation failed.
4675 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4676 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4677 cellNetworkCallback.assertNoCallback();
4678
4679 // Send a validation event where validation succeeded for a server in
4680 // the current resolver config. A LinkProperties callback with updated
4681 // private dns fields should be sent.
4682 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4683 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004684 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004685 mCellNetworkAgent);
4686 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004687 assertTrue(cbi.getLp().isPrivateDnsActive());
4688 assertNull(cbi.getLp().getPrivateDnsServerName());
4689 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004690
4691 // The private dns fields in LinkProperties should be preserved when
4692 // the network agent sends unrelated changes.
4693 LinkProperties lp3 = new LinkProperties(lp2);
4694 lp3.setMtu(1300);
4695 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004696 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004697 mCellNetworkAgent);
4698 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004699 assertTrue(cbi.getLp().isPrivateDnsActive());
4700 assertNull(cbi.getLp().getPrivateDnsServerName());
4701 checkDnsServers(cbi.getLp(), dnsServers);
4702 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05004703
4704 // Removing the only validated server should affect the private dns
4705 // fields in LinkProperties.
4706 LinkProperties lp4 = new LinkProperties(lp3);
4707 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4708 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004709 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004710 mCellNetworkAgent);
4711 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004712 assertFalse(cbi.getLp().isPrivateDnsActive());
4713 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004714 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004715 checkDnsServers(cbi.getLp(), dnsServers);
4716 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004717 }
4718
Rubin Xu1bb5c082017-09-05 18:40:49 +01004719 private void checkDirectlyConnectedRoutes(Object callbackObj,
4720 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4721 assertTrue(callbackObj instanceof LinkProperties);
4722 LinkProperties lp = (LinkProperties) callbackObj;
4723
4724 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4725 expectedRoutes.addAll(otherRoutes);
4726 for (LinkAddress address : linkAddresses) {
4727 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4728 // Duplicates in linkAddresses are considered failures
4729 assertTrue(expectedRoutes.add(localRoute));
4730 }
4731 List<RouteInfo> observedRoutes = lp.getRoutes();
4732 assertEquals(expectedRoutes.size(), observedRoutes.size());
4733 assertTrue(observedRoutes.containsAll(expectedRoutes));
4734 }
4735
dalyk1fcb7392018-03-05 12:42:22 -05004736 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4737 assertTrue(callbackObj instanceof LinkProperties);
4738 LinkProperties lp = (LinkProperties) callbackObj;
4739 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4740 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4741 }
4742
Chalard Jean0b214af2018-01-12 17:22:49 +09004743 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004744 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09004745 final int uid = Process.myUid();
4746
4747 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004748 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004749 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4750 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004751 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004752 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4753 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4754 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004755 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4756 .addTransportType(TRANSPORT_WIFI).build();
4757 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004758 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004759 .addTransportType(TRANSPORT_VPN).build();
4760 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004761 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004762 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4763 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004764 mCm.registerDefaultNetworkCallback(defaultCallback);
4765 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004766
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004767 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09004768 mWiFiNetworkAgent.connect(false);
4769
4770 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004771 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004772 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004773 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004774 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004775 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004776
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004777 final TestNetworkAgentWrapper
4778 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09004779 final ArraySet<UidRange> ranges = new ArraySet<>();
4780 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004781 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4782 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004783 // VPN networks do not satisfy the default request and are automatically validated
4784 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004785 assertFalse(NetworkMonitorUtils.isValidationRequired(
4786 vpnNetworkAgent.getNetworkCapabilities()));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004787 vpnNetworkAgent.setNetworkValid();
4788
Chalard Jean0b214af2018-01-12 17:22:49 +09004789 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004790 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004791 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004792
4793 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004794 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004795 wifiNetworkCallback.assertNoCallback();
4796 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004797 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4798 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004799
Chalard Jean6f4216f2019-06-05 01:40:32 +09004800 genericNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004801 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004802 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
4803 defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004804 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004805
4806 ranges.clear();
4807 vpnNetworkAgent.setUids(ranges);
4808
Chalard Jean6f4216f2019-06-05 01:40:32 +09004809 genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004810 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004811 wifiNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004812 vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004813
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004814 // TODO : The default network callback should actually get a LOST call here (also see the
4815 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4816 // ranges at all when determining whether a network should be rematched. In practice, VPNs
4817 // can't currently update their UIDs without disconnecting, so this does not matter too
4818 // much, but that is the reason the test here has to check for an update to the
4819 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004820 defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004821
Chalard Jean0b214af2018-01-12 17:22:49 +09004822 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004823 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08004824 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004825
4826 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004827 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004828 wifiNetworkCallback.assertNoCallback();
4829 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004830 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4831 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004832 defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004833
4834 mWiFiNetworkAgent.disconnect();
4835
Chalard Jean6f4216f2019-06-05 01:40:32 +09004836 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
4837 genericNotVpnNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
4838 wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004839 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004840 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004841
4842 vpnNetworkAgent.disconnect();
4843
Chalard Jean6f4216f2019-06-05 01:40:32 +09004844 genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004845 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004846 wifiNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004847 vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
4848 defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004849 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004850
4851 mCm.unregisterNetworkCallback(genericNetworkCallback);
4852 mCm.unregisterNetworkCallback(wifiNetworkCallback);
4853 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004854 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004855 }
Chalard Jean26400492018-04-18 20:18:38 +09004856
4857 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004858 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09004859 final int uid = Process.myUid();
4860
4861 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4862 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09004863
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004864 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09004865 mWiFiNetworkAgent.connect(true);
4866
4867 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4868 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4869
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004870 TestNetworkAgentWrapper
4871 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09004872 final ArraySet<UidRange> ranges = new ArraySet<>();
4873 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004874 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4875 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004876 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004877 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004878
4879 defaultCallback.assertNoCallback();
4880 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4881
4882 vpnNetworkAgent.disconnect();
4883 defaultCallback.assertNoCallback();
4884
Varun Anand4fa80e82019-02-06 10:13:38 -08004885 mCm.unregisterNetworkCallback(defaultCallback);
4886 }
4887
4888 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004889 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08004890 final int uid = Process.myUid();
4891
4892 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4893 mCm.registerDefaultNetworkCallback(defaultCallback);
4894
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004895 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08004896 mWiFiNetworkAgent.connect(true);
4897
4898 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4899 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4900
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004901 TestNetworkAgentWrapper
4902 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08004903 final ArraySet<UidRange> ranges = new ArraySet<>();
4904 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004905 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4906 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004907 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004908 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004909
Chalard Jean26400492018-04-18 20:18:38 +09004910 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4911 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4912
4913 vpnNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004914 defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09004915 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4916
Chalard Jean26400492018-04-18 20:18:38 +09004917 mCm.unregisterNetworkCallback(defaultCallback);
4918 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004919
4920 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004921 public void testVpnUnvalidated() throws Exception {
4922 final TestNetworkCallback callback = new TestNetworkCallback();
4923 mCm.registerDefaultNetworkCallback(callback);
4924
4925 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004926 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004927 mEthernetNetworkAgent.connect(true);
4928 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
4929 callback.assertNoCallback();
4930
4931 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
4932 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004933 final TestNetworkAgentWrapper
4934 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004935 final ArraySet<UidRange> ranges = new ArraySet<>();
4936 ranges.add(new UidRange(uid, uid));
4937 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4938 mMockVpn.setUids(ranges);
4939 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
4940 mMockVpn.connect();
4941
4942 // Even though the VPN is unvalidated, it becomes the default network for our app.
4943 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4944 // TODO: this looks like a spurious callback.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004945 callback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004946 callback.assertNoCallback();
4947
4948 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
4949 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
4950 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4951
4952 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4953 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
4954 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
4955
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004956 assertFalse(NetworkMonitorUtils.isValidationRequired(
4957 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004958 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004959 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004960
4961 // Pretend that the VPN network validates.
4962 vpnNetworkAgent.setNetworkValid();
4963 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4964 // Expect to see the validated capability, but no other changes, because the VPN is already
4965 // the default network for the app.
4966 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
4967 callback.assertNoCallback();
4968
4969 vpnNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004970 callback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004971 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
4972 }
4973
4974 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004975 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004976 final int uid = Process.myUid();
4977
4978 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4979 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4980 .removeCapability(NET_CAPABILITY_NOT_VPN)
4981 .addTransportType(TRANSPORT_VPN)
4982 .build();
4983 NetworkCapabilities nc;
4984 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4985 vpnNetworkCallback.assertNoCallback();
4986
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004987 final TestNetworkAgentWrapper
4988 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004989 final ArraySet<UidRange> ranges = new ArraySet<>();
4990 ranges.add(new UidRange(uid, uid));
4991 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4992 mMockVpn.connect();
4993 mMockVpn.setUids(ranges);
4994 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4995
4996 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4997 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4998 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4999 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5000 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5001 // For safety reasons a VPN without underlying networks is considered metered.
5002 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5003
5004 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005005 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005006 mCellNetworkAgent.connect(true);
5007
5008 mService.setUnderlyingNetworksForVpn(
5009 new Network[] { mCellNetworkAgent.getNetwork() });
5010
Chalard Jean6f4216f2019-06-05 01:40:32 +09005011 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5012 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005013 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005014 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005015
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005016 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005017 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5018 mWiFiNetworkAgent.connect(true);
5019
5020 mService.setUnderlyingNetworksForVpn(
5021 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5022
Chalard Jean6f4216f2019-06-05 01:40:32 +09005023 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5024 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005025 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005026 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005027
5028 // Don't disconnect, but note the VPN is not using wifi any more.
5029 mService.setUnderlyingNetworksForVpn(
5030 new Network[] { mCellNetworkAgent.getNetwork() });
5031
Chalard Jean6f4216f2019-06-05 01:40:32 +09005032 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5033 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005034 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005035 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005036
5037 // Use Wifi but not cell. Note the VPN is now unmetered.
5038 mService.setUnderlyingNetworksForVpn(
5039 new Network[] { mWiFiNetworkAgent.getNetwork() });
5040
Chalard Jean6f4216f2019-06-05 01:40:32 +09005041 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5042 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005043 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005044 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005045
5046 // Use both again.
5047 mService.setUnderlyingNetworksForVpn(
5048 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5049
Chalard Jean6f4216f2019-06-05 01:40:32 +09005050 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5051 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005052 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005053 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005054
Chalard Jean6b65ec72018-05-18 22:02:56 +09005055 // Disconnect cell. Receive update without even removing the dead network from the
5056 // underlying networks – it's dead anyway. Not metered any more.
5057 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005058 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5059 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005060 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005061 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005062
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005063 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005064 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005065 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5066 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005067 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005068 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005069
5070 mMockVpn.disconnect();
5071 }
junyulai4a192e22018-06-13 15:00:37 +08005072
Mike Yuf9729752018-08-17 15:22:05 +08005073 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005074 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005075 final int uid = Process.myUid();
5076
5077 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5078 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5079 .removeCapability(NET_CAPABILITY_NOT_VPN)
5080 .addTransportType(TRANSPORT_VPN)
5081 .build();
5082 NetworkCapabilities nc;
5083 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5084 vpnNetworkCallback.assertNoCallback();
5085
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005086 final TestNetworkAgentWrapper
5087 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005088 final ArraySet<UidRange> ranges = new ArraySet<>();
5089 ranges.add(new UidRange(uid, uid));
5090 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5091 mMockVpn.connect();
5092 mMockVpn.setUids(ranges);
5093 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5094
5095 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5096 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5097 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5098 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5099 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5100 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5101 // In case of no default network, VPN is considered metered.
5102 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5103
5104 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005105 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005106 mCellNetworkAgent.connect(true);
5107
Chalard Jean6f4216f2019-06-05 01:40:32 +09005108 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5109 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005110 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005111 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005112
5113 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005114 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005115 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5116 mWiFiNetworkAgent.connect(true);
5117
Chalard Jean6f4216f2019-06-05 01:40:32 +09005118 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5119 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005120 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005121 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005122
5123 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5124 // the capabilities.
5125 mCellNetworkAgent.disconnect();
5126
5127 // Disconnect wifi too. Now we have no default network.
5128 mWiFiNetworkAgent.disconnect();
5129
Chalard Jean6f4216f2019-06-05 01:40:32 +09005130 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5131 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005132 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005133 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005134
5135 mMockVpn.disconnect();
5136 }
5137
5138 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005139 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005140 // Returns true by default when no network is available.
5141 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005142 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005143 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5144 mWiFiNetworkAgent.connect(true);
5145 waitForIdle();
5146
5147 assertFalse(mCm.isActiveNetworkMetered());
5148 }
5149
5150 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005151 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005152 // Returns true by default when no network is available.
5153 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005154 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005155 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5156 mCellNetworkAgent.connect(true);
5157 waitForIdle();
5158
5159 assertTrue(mCm.isActiveNetworkMetered());
5160 }
5161
5162 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005163 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005164 // Returns true by default when no network is available.
5165 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005166 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005167 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5168 mCellNetworkAgent.connect(true);
5169 waitForIdle();
5170 assertTrue(mCm.isActiveNetworkMetered());
5171
5172 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005173 TestNetworkAgentWrapper
5174 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005175 final ArraySet<UidRange> ranges = new ArraySet<>();
5176 final int uid = Process.myUid();
5177 ranges.add(new UidRange(uid, uid));
5178 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5179 mMockVpn.setUids(ranges);
5180 vpnNetworkAgent.connect(true);
5181 mMockVpn.connect();
5182 waitForIdle();
5183 // Ensure VPN is now the active network.
5184 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5185
5186 // Expect VPN to be metered.
5187 assertTrue(mCm.isActiveNetworkMetered());
5188
5189 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005190 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005191 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5192 mWiFiNetworkAgent.connect(true);
5193 waitForIdle();
5194 // VPN should still be the active network.
5195 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5196
5197 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5198 assertFalse(mCm.isActiveNetworkMetered());
5199
5200 // Disconnecting Cell should not affect VPN's meteredness.
5201 mCellNetworkAgent.disconnect();
5202 waitForIdle();
5203
5204 assertFalse(mCm.isActiveNetworkMetered());
5205
5206 // Disconnect WiFi; Now there is no platform default network.
5207 mWiFiNetworkAgent.disconnect();
5208 waitForIdle();
5209
5210 // VPN without any underlying networks is treated as metered.
5211 assertTrue(mCm.isActiveNetworkMetered());
5212
5213 vpnNetworkAgent.disconnect();
5214 mMockVpn.disconnect();
5215 }
5216
5217 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005218 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005219 // Returns true by default when no network is available.
5220 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005221 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005222 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5223 mCellNetworkAgent.connect(true);
5224 waitForIdle();
5225 assertTrue(mCm.isActiveNetworkMetered());
5226
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005227 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005228 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5229 mWiFiNetworkAgent.connect(true);
5230 waitForIdle();
5231 assertFalse(mCm.isActiveNetworkMetered());
5232
5233 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005234 TestNetworkAgentWrapper
5235 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005236 final ArraySet<UidRange> ranges = new ArraySet<>();
5237 final int uid = Process.myUid();
5238 ranges.add(new UidRange(uid, uid));
5239 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5240 mMockVpn.setUids(ranges);
5241 vpnNetworkAgent.connect(true);
5242 mMockVpn.connect();
5243 waitForIdle();
5244 // Ensure VPN is now the active network.
5245 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5246 // VPN is using Cell
5247 mService.setUnderlyingNetworksForVpn(
5248 new Network[] { mCellNetworkAgent.getNetwork() });
5249 waitForIdle();
5250
5251 // Expect VPN to be metered.
5252 assertTrue(mCm.isActiveNetworkMetered());
5253
5254 // VPN is now using WiFi
5255 mService.setUnderlyingNetworksForVpn(
5256 new Network[] { mWiFiNetworkAgent.getNetwork() });
5257 waitForIdle();
5258
5259 // Expect VPN to be unmetered
5260 assertFalse(mCm.isActiveNetworkMetered());
5261
5262 // VPN is using Cell | WiFi.
5263 mService.setUnderlyingNetworksForVpn(
5264 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5265 waitForIdle();
5266
5267 // Expect VPN to be metered.
5268 assertTrue(mCm.isActiveNetworkMetered());
5269
5270 // VPN is using WiFi | Cell.
5271 mService.setUnderlyingNetworksForVpn(
5272 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5273 waitForIdle();
5274
5275 // Order should not matter and VPN should still be metered.
5276 assertTrue(mCm.isActiveNetworkMetered());
5277
5278 // VPN is not using any underlying networks.
5279 mService.setUnderlyingNetworksForVpn(new Network[0]);
5280 waitForIdle();
5281
5282 // VPN without underlying networks is treated as metered.
5283 assertTrue(mCm.isActiveNetworkMetered());
5284
5285 vpnNetworkAgent.disconnect();
5286 mMockVpn.disconnect();
5287 }
5288
5289 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005290 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005291 // Returns true by default when no network is available.
5292 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005293 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005294 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5295 mWiFiNetworkAgent.connect(true);
5296 waitForIdle();
5297 assertFalse(mCm.isActiveNetworkMetered());
5298
5299 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005300 TestNetworkAgentWrapper
5301 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005302 final ArraySet<UidRange> ranges = new ArraySet<>();
5303 final int uid = Process.myUid();
5304 ranges.add(new UidRange(uid, uid));
5305 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5306 mMockVpn.setUids(ranges);
5307 vpnNetworkAgent.connect(true);
5308 mMockVpn.connectAsAlwaysMetered();
5309 waitForIdle();
5310 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5311
5312 // VPN is tracking current platform default (WiFi).
5313 mService.setUnderlyingNetworksForVpn(null);
5314 waitForIdle();
5315
5316 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5317 assertTrue(mCm.isActiveNetworkMetered());
5318
5319 // VPN explicitly declares WiFi as its underlying network.
5320 mService.setUnderlyingNetworksForVpn(
5321 new Network[] { mWiFiNetworkAgent.getNetwork() });
5322 waitForIdle();
5323
5324 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5325 assertTrue(mCm.isActiveNetworkMetered());
5326
5327 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5328 // anyways suppose to be metered.
5329 mWiFiNetworkAgent.disconnect();
5330 waitForIdle();
5331
5332 assertTrue(mCm.isActiveNetworkMetered());
5333
5334 vpnNetworkAgent.disconnect();
5335 }
5336
5337 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005338 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005339 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5340 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5341 .addTransportType(TRANSPORT_CELLULAR)
5342 .build();
5343 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5344
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005345 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005346 mCellNetworkAgent.connect(true);
5347 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5348
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005349 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005350 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5351
5352 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005353 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005354 cellNetworkCallback.assertNoCallback();
5355
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005356 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005357 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5358
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005359 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005360 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5361
5362 // Restrict the network based on UID rule and NOT_METERED capability change.
5363 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5364 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5365 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5366 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5367 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5368 mCellNetworkAgent);
5369 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005370 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005371 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5372
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005373 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005374 cellNetworkCallback.assertNoCallback();
5375
5376 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005377 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005378 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005379 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005380 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005381 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005382 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5383 cellNetworkCallback.assertNoCallback();
5384
5385 mCm.unregisterNetworkCallback(cellNetworkCallback);
5386 }
5387
5388 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005389 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005390 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5391 mCm.registerDefaultNetworkCallback(defaultCallback);
5392
5393 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005394 setUidRulesChanged(RULE_REJECT_ALL);
5395 setUidRulesChanged(RULE_NONE);
5396 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005397 defaultCallback.assertNoCallback();
5398
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005399 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005400 mCellNetworkAgent.connect(true);
5401 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5402 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5403
5404 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005405 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005406 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5407 mWiFiNetworkAgent.connect(true);
5408 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5409
5410 // Switch to METERED network. Restrict the use of the network.
5411 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005412 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005413 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5414
5415 // Network becomes NOT_METERED.
5416 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5417 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5418 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5419
5420 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005421 setRestrictBackgroundChanged(true);
5422 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005423 defaultCallback.assertNoCallback();
5424
5425 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005426 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005427 defaultCallback.assertNoCallback();
5428
5429 mCm.unregisterNetworkCallback(defaultCallback);
5430 }
5431
junyulai4a192e22018-06-13 15:00:37 +08005432 /**
5433 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5434 */
5435 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5436 InterfaceConfiguration cfg = new InterfaceConfiguration();
5437 cfg.setHardwareAddress("11:22:33:44:55:66");
5438 cfg.setLinkAddress(la);
5439 return cfg;
5440 }
5441
5442 /**
5443 * Make expected stack link properties, copied from Nat464Xlat.
5444 */
5445 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5446 LinkAddress clatAddress = la;
5447 LinkProperties stacked = new LinkProperties();
5448 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5449 RouteInfo ipv4Default = new RouteInfo(
5450 new LinkAddress(Inet4Address.ANY, 0),
5451 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5452 stacked.addRoute(ipv4Default);
5453 stacked.addLinkAddress(clatAddress);
5454 return stacked;
5455 }
5456
5457 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005458 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005459 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5460 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005461 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5462 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5463
junyulai4a192e22018-06-13 15:00:37 +08005464 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5465 .addTransportType(TRANSPORT_CELLULAR)
5466 .addCapability(NET_CAPABILITY_INTERNET)
5467 .build();
5468 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5469 mCm.registerNetworkCallback(networkRequest, networkCallback);
5470
Lorenzo Colittid593e292019-02-19 13:21:56 +09005471 // Prepare ipv6 only link properties.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005472 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005473 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005474 final LinkProperties cellLp = new LinkProperties();
5475 cellLp.setInterfaceName(MOBILE_IFNAME);
5476 cellLp.addLinkAddress(myIpv6);
5477 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5478 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5479 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005480 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005481 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08005482 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5483 .thenReturn(getClatInterfaceConfig(myIpv4));
5484
Lorenzo Colittid593e292019-02-19 13:21:56 +09005485 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005486 mCellNetworkAgent.sendLinkProperties(cellLp);
5487 mCellNetworkAgent.connect(true);
Luke Huanga24d5d82019-04-09 18:41:49 +08005488
5489 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5490 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
5491
junyulai4a192e22018-06-13 15:00:37 +08005492 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005493 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005494
Lorenzo Colittid593e292019-02-19 13:21:56 +09005495 // Switching default network updates TCP buffer sizes.
5496 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5497
5498 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5499 // the NAT64 prefix was removed because one was never discovered.
5500 cellLp.addLinkAddress(myIpv4);
5501 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005502 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005503 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005504 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005505
5506 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005507 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005508 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005509 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005510
5511 // Remove IPv4 address. Expect prefix discovery to be started again.
5512 cellLp.removeLinkAddress(myIpv4);
5513 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5514 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005515 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005516 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005517
5518 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005519 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005520 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005521 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5522 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005523 LinkProperties lpBeforeClat = networkCallback.expectCallback(
5524 CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005525 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5526 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5527 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5528
5529 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005530 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005531 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005532 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5533 .getStackedLinks();
5534 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5535
5536 // Change trivial linkproperties and see if stacked link is preserved.
5537 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5538 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005539 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005540
5541 List<LinkProperties> stackedLpsAfterChange =
5542 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5543 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5544 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5545
Luke Huang65914772019-03-16 00:31:46 +08005546 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005547 mResolverParamsParcelCaptor.capture());
5548 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5549 assertEquals(1, resolvrParams.servers.length);
5550 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08005551
Lorenzo Colittid593e292019-02-19 13:21:56 +09005552 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5553 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005554 cellLp.addLinkAddress(myIpv4);
5555 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5556 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005557 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005558 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08005559 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005560
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005561 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean6f4216f2019-06-05 01:40:32 +09005562 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005563 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5564 LinkProperties expected = new LinkProperties(cellLp);
5565 expected.setNat64Prefix(kNat64Prefix);
5566 assertEquals(expected, actualLpAfterIpv4);
5567 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5568
5569 // The interface removed callback happens but has no effect after stop is called.
5570 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5571 networkCallback.assertNoCallback();
5572
Lorenzo Colittid593e292019-02-19 13:21:56 +09005573 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005574 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005575 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005576 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005577
Lorenzo Colittid593e292019-02-19 13:21:56 +09005578 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5579 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5580 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005581 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5582 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005583
5584 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005585 cellLp.removeLinkAddress(myIpv4);
5586 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5587 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5588 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005589 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005590 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005591 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5592 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005593 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005594 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5595
Lorenzo Colittid593e292019-02-19 13:21:56 +09005596
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005597 // Clat iface comes up. Expect stacked link to be added.
5598 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005599 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5600 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005601
5602 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005603 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5604 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005605 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5606 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005607 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005608 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5609 (lp) -> lp.getStackedLinks().size() == 0);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005610
5611 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005612 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005613 networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005614 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005615 mCm.unregisterNetworkCallback(networkCallback);
5616 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005617
5618 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005619 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08005620 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5621 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5622 .addCapability(NET_CAPABILITY_INTERNET)
5623 .build();
5624 mCm.registerNetworkCallback(networkRequest, networkCallback);
5625
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005626 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08005627 final LinkProperties cellLp = new LinkProperties();
5628 cellLp.setInterfaceName(MOBILE_IFNAME);
5629 mCellNetworkAgent.sendLinkProperties(cellLp);
5630 reset(mNetworkManagementService);
5631 mCellNetworkAgent.connect(true);
5632 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5633 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5634 eq(ConnectivityManager.TYPE_MOBILE));
5635
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005636 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005637 final LinkProperties wifiLp = new LinkProperties();
5638 wifiLp.setInterfaceName(WIFI_IFNAME);
5639 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5640
5641 // Network switch
5642 reset(mNetworkManagementService);
5643 mWiFiNetworkAgent.connect(true);
5644 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005645 networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005646 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5647 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5648 eq(ConnectivityManager.TYPE_WIFI));
5649 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5650
5651 // Disconnect wifi and switch back to cell
5652 reset(mNetworkManagementService);
5653 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005654 networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005655 assertNoCallbacks(networkCallback);
5656 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5657 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5658 eq(ConnectivityManager.TYPE_MOBILE));
5659
5660 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005661 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005662 wifiLp.setInterfaceName(WIFI_IFNAME);
5663 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5664 mWiFiNetworkAgent.connect(true);
5665 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005666 networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005667 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5668
5669 // Disconnect cell
5670 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005671 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08005672 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005673 networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005674 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5675 // sent as network being switched. Ensure rule removal for cell will not be triggered
5676 // unexpectedly before network being removed.
5677 waitForIdle();
5678 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08005679 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
5680 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08005681 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08005682
5683 // Disconnect wifi
5684 ConditionVariable cv = waitForConnectivityBroadcasts(1);
5685 reset(mNetworkManagementService);
5686 mWiFiNetworkAgent.disconnect();
5687 waitFor(cv);
5688 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5689
5690 // Clean up
5691 mCm.unregisterNetworkCallback(networkCallback);
5692 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005693
Chalard Jeane7b24752019-06-20 16:01:19 +09005694 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005695 String[] values = tcpBufferSizes.split(",");
5696 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5697 String wmemValues = String.join(" ", values[3], values[4], values[5]);
5698 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09005699 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005700 reset(mMockNetd);
5701 }
5702
5703 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07005704 @FlakyTest(bugId = 140305678)
Chalard Jeane7b24752019-06-20 16:01:19 +09005705 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005706 final String testTcpBufferSizes = "1,2,3,4,5,6";
5707
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005708 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005709 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005710 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005711 mCellNetworkAgent.connect(false);
5712 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5713
5714 // Change link Properties should have updated tcp buffer size.
5715 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005716 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005717 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005718 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005719 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005720
5721 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005722 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005723 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005724 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005725 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5726 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5727 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5728 }
5729
5730 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005731 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005732 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005733 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005734 mWiFiNetworkAgent.connect(true);
5735 waitForIdle();
5736 assertNull(mService.getProxyForNetwork(null));
5737
5738 final LinkProperties testLinkProperties = new LinkProperties();
5739 testLinkProperties.setHttpProxy(testProxyInfo);
5740
5741 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5742 waitForIdle();
5743
5744 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5745 }
5746
5747 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005748 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005749 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5750
5751 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005752 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005753 mWiFiNetworkAgent.connect(true);
5754 waitForIdle();
5755 assertNull(mService.getProxyForNetwork(null));
5756
5757 // Set up a VPN network with a proxy
5758 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005759 final TestNetworkAgentWrapper
5760 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005761 final ArraySet<UidRange> ranges = new ArraySet<>();
5762 ranges.add(new UidRange(uid, uid));
5763 mMockVpn.setUids(ranges);
5764 LinkProperties testLinkProperties = new LinkProperties();
5765 testLinkProperties.setHttpProxy(testProxyInfo);
5766 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5767 waitForIdle();
5768
5769 // Connect to VPN with proxy
5770 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5771 vpnNetworkAgent.connect(true);
5772 mMockVpn.connect();
5773 waitForIdle();
5774
5775 // Test that the VPN network returns a proxy, and the WiFi does not.
5776 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5777 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5778 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5779
5780 // Test that the VPN network returns no proxy when it is set to null.
5781 testLinkProperties.setHttpProxy(null);
5782 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5783 waitForIdle();
5784 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5785 assertNull(mService.getProxyForNetwork(null));
5786
5787 // Set WiFi proxy and check that the vpn proxy is still null.
5788 testLinkProperties.setHttpProxy(testProxyInfo);
5789 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5790 waitForIdle();
5791 assertNull(mService.getProxyForNetwork(null));
5792
5793 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
5794 // correct proxy setting.
5795 vpnNetworkAgent.disconnect();
5796 waitForIdle();
5797 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5798 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5799 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5800 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005801
5802 @Test
5803 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
5804 LinkProperties lp = new LinkProperties();
5805 lp.setInterfaceName("tun0");
5806 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
5807 // The uid range needs to cover the test app so the network is visible to it.
5808 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005809 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005810
5811 // Connected VPN should have interface rules set up. There are two expected invocations,
5812 // one during VPN uid update, one during VPN LinkProperties update
5813 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
5814 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
5815 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
5816 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
5817 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
5818
5819 vpnNetworkAgent.disconnect();
5820 waitForIdle();
5821
5822 // Disconnected VPN should have interface rules removed
5823 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5824 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5825 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
5826 }
5827
5828 @Test
5829 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
5830 LinkProperties lp = new LinkProperties();
5831 lp.setInterfaceName("tun0");
5832 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
5833 // The uid range needs to cover the test app so the network is visible to it.
5834 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005835 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
5836 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005837
5838 // Legacy VPN should not have interface rules set up
5839 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
5840 }
5841
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09005842 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005843 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
5844 throws Exception {
5845 LinkProperties lp = new LinkProperties();
5846 lp.setInterfaceName("tun0");
5847 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
5848 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
5849 // The uid range needs to cover the test app so the network is visible to it.
5850 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005851 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
5852 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005853
5854 // IPv6 unreachable route should not be misinterpreted as a default route
5855 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
5856 }
5857
5858 @Test
5859 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
5860 LinkProperties lp = new LinkProperties();
5861 lp.setInterfaceName("tun0");
5862 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
5863 // The uid range needs to cover the test app so the network is visible to it.
5864 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005865 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005866
5867 // Connected VPN should have interface rules set up. There are two expected invocations,
5868 // one during VPN uid update, one during VPN LinkProperties update
5869 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
5870 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
5871 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
5872 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
5873
5874 reset(mMockNetd);
5875 InOrder inOrder = inOrder(mMockNetd);
5876 lp.setInterfaceName("tun1");
5877 vpnNetworkAgent.sendLinkProperties(lp);
5878 waitForIdle();
5879 // VPN handover (switch to a new interface) should result in rules being updated (old rules
5880 // removed first, then new rules added)
5881 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5882 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5883 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
5884 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5885
5886 reset(mMockNetd);
5887 lp = new LinkProperties();
5888 lp.setInterfaceName("tun1");
5889 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
5890 vpnNetworkAgent.sendLinkProperties(lp);
5891 waitForIdle();
5892 // VPN not routing everything should no longer have interface filtering rules
5893 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5894 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5895
5896 reset(mMockNetd);
5897 lp = new LinkProperties();
5898 lp.setInterfaceName("tun1");
5899 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
5900 vpnNetworkAgent.sendLinkProperties(lp);
5901 waitForIdle();
5902 // Back to routing all IPv6 traffic should have filtering rules
5903 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
5904 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5905 }
5906
5907 @Test
5908 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
5909 LinkProperties lp = new LinkProperties();
5910 lp.setInterfaceName("tun0");
5911 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
5912 // The uid range needs to cover the test app so the network is visible to it.
5913 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005914 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005915 Collections.singleton(vpnRange));
5916
5917 reset(mMockNetd);
5918 InOrder inOrder = inOrder(mMockNetd);
5919
5920 // Update to new range which is old range minus APP1, i.e. only APP2
5921 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
5922 new UidRange(vpnRange.start, APP1_UID - 1),
5923 new UidRange(APP1_UID + 1, vpnRange.stop)));
5924 vpnNetworkAgent.setUids(newRanges);
5925 waitForIdle();
5926
5927 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
5928 // Verify old rules are removed before new rules are added
5929 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5930 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5931 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
5932 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
5933 }
5934
5935
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005936 private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
Chalard Jeane7b24752019-06-20 16:01:19 +09005937 Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005938 final TestNetworkAgentWrapper
5939 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005940 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
5941 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5942 mMockVpn.connect();
5943 mMockVpn.setUids(vpnRange);
5944 vpnNetworkAgent.connect(true);
5945 waitForIdle();
5946 return vpnNetworkAgent;
5947 }
5948
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005949 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
5950 final PackageInfo packageInfo = new PackageInfo();
5951 packageInfo.requestedPermissions = new String[0];
5952 packageInfo.applicationInfo = new ApplicationInfo();
5953 packageInfo.applicationInfo.privateFlags = 0;
5954 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
5955 UserHandle.getAppId(uid));
5956 return packageInfo;
5957 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07005958}