blob: 5bfd647f01528a1b1f69424a5631967cb0f33bf9 [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;
Chalard Jeanb299b842019-09-27 17:13:14 +0900261 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900262 // 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.
Chalard Jeanb299b842019-09-27 17:13:14 +0900267 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
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);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900507 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
508 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900509 }
510
511 @Override
512 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
513 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900514 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900515
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900516 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900517 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900518 return null;
519 };
520
Chalard Jeane7b24752019-06-20 16:01:19 +0900521 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
522 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900523
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900524 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900525 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
526 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
527 doNothing().when(mNetworkStack).makeNetworkMonitor(
528 nmNetworkCaptor.capture(),
529 any() /* name */,
530 nmCbCaptor.capture());
531
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900532 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400533 @Override
534 public void networkStatus(int status, String redirectUrl) {
535 mRedirectUrl = redirectUrl;
536 mNetworkStatusReceived.open();
537 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400538 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900539
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900540 assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900541 mNmCallbacks = nmCbCaptor.getValue();
542
Chalard Jeane7b24752019-06-20 16:01:19 +0900543 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900544
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900545 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900546 }
547
Chalard Jeane7b24752019-06-20 16:01:19 +0900548 private void onValidationRequested() throws Exception {
549 if (mNmProvNotificationRequested
550 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
551 mNmCallbacks.hideProvisioningNotification();
552 mNmProvNotificationRequested = false;
553 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900554
Chalard Jeane7b24752019-06-20 16:01:19 +0900555 mNmCallbacks.notifyNetworkTested(
556 mNmValidationResult, mNmValidationRedirectUrl);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900557
Chalard Jeane7b24752019-06-20 16:01:19 +0900558 if (mNmValidationRedirectUrl != null) {
559 mNmCallbacks.showProvisioningNotification(
560 "test_provisioning_notif_action", "com.android.test.package");
561 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900562 }
Paul Jensen3d911462015-06-12 06:40:24 -0400563 }
564
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900565 /**
566 * Connect without adding any internet capability.
567 */
Paul Jensene0988542015-06-25 15:30:08 -0400568 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900569 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400570 }
571
Paul Jensend7b6ca92015-05-13 14:05:12 -0400572 /**
Paul Jensene0988542015-06-25 15:30:08 -0400573 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400574 * @param validated Indicate if network should pretend to be validated.
575 */
576 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900577 connect(validated, true);
578 }
579
580 /**
581 * Transition this NetworkAgent to CONNECTED state.
582 * @param validated Indicate if network should pretend to be validated.
583 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
584 */
585 public void connect(boolean validated, boolean hasInternet) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900586 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400587
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900588 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400589 final ConditionVariable validatedCv = new ConditionVariable();
590 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900591 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400592 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900593 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900594 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400595 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900596 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400597 public void onCapabilitiesChanged(Network network,
598 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400599 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900600 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400601 validatedCv.open();
602 }
603 }
604 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400605 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400606 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900607 if (hasInternet) {
608 addCapability(NET_CAPABILITY_INTERNET);
609 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400610
Paul Jensene0988542015-06-25 15:30:08 -0400611 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400612
613 if (validated) {
614 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400615 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900616 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400617 }
618
619 if (callback != null) mCm.unregisterNetworkCallback(callback);
620 }
621
Paul Jensen232437312016-04-06 09:51:26 -0400622 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900623 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400624 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400625 }
626
lucasline252a742019-03-12 13:08:03 +0800627 public void connectWithPartialConnectivity() {
628 setNetworkPartial();
629 connect(false);
630 }
631
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900632 public void connectWithPartialValidConnectivity() {
633 setNetworkPartialValid();
634 connect(false);
635 }
636
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900637 void setNetworkValid() {
638 mNmValidationResult = VALIDATION_RESULT_VALID;
639 mNmValidationRedirectUrl = null;
Erik Kline1d3db322017-02-28 16:20:20 +0900640 }
641
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900642 void setNetworkInvalid() {
643 mNmValidationResult = VALIDATION_RESULT_INVALID;
644 mNmValidationRedirectUrl = null;
Chalard Jean804b8fb2018-01-30 22:41:41 +0900645 }
646
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900647 void setNetworkPortal(String redirectUrl) {
648 setNetworkInvalid();
649 mNmValidationRedirectUrl = redirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400650 }
651
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900652 void setNetworkPartial() {
653 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
654 mNmValidationRedirectUrl = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400655 }
Paul Jensene0988542015-06-25 15:30:08 -0400656
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900657 void setNetworkPartialValid() {
658 mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
659 mNmValidationRedirectUrl = null;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900660 }
Paul Jensen232437312016-04-06 09:51:26 -0400661
662 public String waitForRedirectUrl() {
663 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
664 return mRedirectUrl;
665 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900666
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900667 public void expectDisconnected() {
668 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900669 }
670
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900671 public void expectPreventReconnectReceived() {
672 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900673 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400674 }
675
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900676 /**
677 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
678 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900679 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900680 * expectRemoveRequests.
681 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700682 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400683 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
684 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400685 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700686
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900687 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900688 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
689 // once, then cause some other thread to add or remove requests, then call
690 // waitForRequests().
691 // It is not possible to wait for both add and remove requests. When adding, the queue
692 // contains the expected score. When removing, the value is unused, all matters is the
693 // number of objects in the queue.
694 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900695
696 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900697 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900698 private boolean mExpectingAdditions;
699
Etan Cohenddb720a2019-01-08 12:09:18 -0800700 // Used to collect the networks requests managed by this factory. This is a duplicate of
701 // the internal information stored in the NetworkFactory (which is private).
702 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
703
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700704 public MockNetworkFactory(Looper looper, Context context, String logTag,
705 NetworkCapabilities filter) {
706 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900707 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700708 }
709
710 public int getMyRequestCount() {
711 return getRequestCount();
712 }
713
714 protected void startNetwork() {
715 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400716 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700717 }
718
719 protected void stopNetwork() {
720 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400721 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700722 }
723
724 public boolean getMyStartRequested() {
725 return mNetworkStarted.get();
726 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400727
728 public ConditionVariable getNetworkStartedCV() {
729 mNetworkStartedCV.close();
730 return mNetworkStartedCV;
731 }
732
733 public ConditionVariable getNetworkStoppedCV() {
734 mNetworkStoppedCV.close();
735 return mNetworkStoppedCV;
736 }
737
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900738 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900739 protected void handleAddRequest(NetworkRequest request, int score,
740 int factorySerialNumber) {
741 synchronized (mExpectations) {
742 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900743
Chalard Jean05ab6812018-05-02 21:14:54 +0900744 assertNotNull("Added more requests than expected (" + request + " score : "
745 + score + ")", expectedScore);
746 // If we're expecting anything, we must be expecting additions.
747 if (!mExpectingAdditions) {
748 fail("Can't add requests while expecting requests to be removed");
749 }
750 if (expectedScore != score) {
751 fail("Expected score was " + expectedScore + " but actual was " + score
752 + " in added request");
753 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900754
Chalard Jean05ab6812018-05-02 21:14:54 +0900755 // Add the request.
756 mNetworkRequests.put(request.requestId, request);
757 super.handleAddRequest(request, score, factorySerialNumber);
758 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900759 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400760 }
761
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900762 @Override
763 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900764 synchronized (mExpectations) {
765 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900766
Chalard Jean05ab6812018-05-02 21:14:54 +0900767 assertTrue("Removed more requests than expected", expectedScore != null);
768 // If we're expecting anything, we must be expecting removals.
769 if (mExpectingAdditions) {
770 fail("Can't remove requests while expecting requests to be added");
771 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900772
Chalard Jean05ab6812018-05-02 21:14:54 +0900773 // Remove the request.
774 mNetworkRequests.remove(request.requestId);
775 super.handleRemoveRequest(request);
776 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900777 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400778 }
779
Etan Cohenddb720a2019-01-08 12:09:18 -0800780 // Trigger releasing the request as unfulfillable
781 public void triggerUnfulfillable(NetworkRequest r) {
782 super.releaseRequestAsUnfulfillableByAnyFactory(r);
783 }
784
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900785 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900786 if (mExpectations.size() != 0) {
787 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900788 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400789 }
790
Chalard Jean05ab6812018-05-02 21:14:54 +0900791 // Expects that requests with the specified scores will be added.
792 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900793 assertNoExpectations();
794 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900795 for (int score : scores) {
796 mExpectations.add(score);
797 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400798 }
799
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900800 // Expects that count requests will be removed.
801 public void expectRemoveRequests(final int count) {
802 assertNoExpectations();
803 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900804 for (int i = 0; i < count; ++i) {
805 mExpectations.add(0); // For removals the score is ignored so any value will do.
806 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900807 }
808
809 // Waits for the expected request additions or removals to happen within a timeout.
810 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900811 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
812 synchronized (mExpectations) {
813 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
814 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
815 }
816 }
817 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900818 final String msg = count + " requests still not " +
819 (mExpectingAdditions ? "added" : "removed") +
820 " after " + TIMEOUT_MS + " ms";
821 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900822 }
823
Etan Cohenddb720a2019-01-08 12:09:18 -0800824 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
825 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900826 waitForRequests();
827 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800828 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400829 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700830 }
831
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900832 private static Looper startHandlerThreadAndReturnLooper() {
833 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
834 handlerThread.start();
835 return handlerThread.getLooper();
836 }
837
838 private class MockVpn extends Vpn {
839 // TODO : the interactions between this mock and the mock network agent are too
840 // hard to get right at this moment, because it's unclear in which case which
841 // target needs to get a method call or both, and in what order. It's because
842 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
843 // parent class of MockVpn agent wants that responsibility.
844 // That being said inside the test it should be possible to make the interactions
845 // harder to get wrong with precise speccing, judicious comments, helper methods
846 // and a few sprinkled assertions.
847
848 private boolean mConnected = false;
849 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
850 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900851 private TestNetworkAgentWrapper mMockNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900852
853 public MockVpn(int userId) {
854 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
855 userId);
856 }
857
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900858 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
859 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900860 mMockNetworkAgent = agent;
861 mNetworkAgent = agent.getNetworkAgent();
862 mNetworkCapabilities.set(agent.getNetworkCapabilities());
863 }
864
865 public void setUids(Set<UidRange> uids) {
866 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800867 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900868 }
869
870 @Override
871 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800872 if (mMockNetworkAgent == null) {
873 return NETID_UNSET;
874 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900875 return mMockNetworkAgent.getNetwork().netId;
876 }
877
878 @Override
879 public boolean appliesToUid(int uid) {
880 return mConnected; // Trickery to simplify testing.
881 }
882
883 @Override
884 protected boolean isCallerEstablishedOwnerLocked() {
885 return mConnected; // Similar trickery
886 }
887
Varun Anandc51b06d2019-02-25 17:22:02 -0800888 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900889 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
890 mConnected = true;
891 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800892 mConfig.isMetered = isAlwaysMetered;
893 }
894
895 public void connectAsAlwaysMetered() {
896 connect(true /* isAlwaysMetered */);
897 }
898
899 public void connect() {
900 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900901 }
902
903 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800904 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
905 if (!mConnected) return null;
906 super.updateCapabilities(defaultNetwork);
907 // Because super.updateCapabilities will update the capabilities of the agent but
908 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900909 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800910 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900911 }
912
913 private void copyCapabilitiesToNetworkAgent() {
914 if (null != mMockNetworkAgent) {
915 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
916 false /* sendToConnectivityService */);
917 }
918 }
919
920 public void disconnect() {
921 mConnected = false;
922 mConfig = null;
923 }
924 }
925
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900926 private void mockVpn(int uid) {
927 synchronized (mService.mVpns) {
928 int userId = UserHandle.getUserId(uid);
929 mMockVpn = new MockVpn(userId);
930 // This has no effect unless the VPN is actually connected, because things like
931 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
932 // netId, and check if that network is actually connected.
933 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900934 }
935 }
936
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900937 private void setUidRulesChanged(int uidRules) throws RemoteException {
938 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
939 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400940
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900941 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
942 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
943 }
944
945 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
946 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
947 }
948
949 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
950 volatile boolean mConfigRestrictsAvoidBadWifi;
951 volatile int mConfigMeteredMultipathPreference;
952
953 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900954 super(c, h, r);
955 }
956
957 @Override
958 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900959 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +0900960 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900961
962 @Override
963 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900964 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +0800965 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400966 }
967
Paul Jensen3d911462015-06-12 06:40:24 -0400968 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900969 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
970 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400971 */
972 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900973 if (conditionVariable.block(TIMEOUT_MS)) {
974 return;
975 }
976 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -0400977 }
978
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000979 private static final int VPN_USER = 0;
980 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
981 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
982 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
983
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900984 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -0400985 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900986 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400987
Hugo Benichi64901e52017-10-19 14:42:40 +0900988 MockitoAnnotations.initMocks(this);
989 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
990
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000991 when(mUserManager.getUsers(eq(true))).thenReturn(
992 Arrays.asList(new UserInfo[] {
993 new UserInfo(VPN_USER, "", 0),
994 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000995
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900996 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
997 // http://b/25897652 .
998 if (Looper.myLooper() == null) {
999 Looper.prepare();
1000 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001001 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001002
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001003 FakeSettingsProvider.clearSettingsProvider();
1004 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1005 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001006 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1007 LocalServices.addService(
1008 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001009
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001010 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1011 mAlarmManagerThread.start();
1012 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1013
1014 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1015 final ConnectivityService.Dependencies deps = makeDependencies();
1016 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001017 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001018 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001019 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001020 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001021 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001022 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001023 deps);
1024 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1025 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001026
Mike Yuf9729752018-08-17 15:22:05 +08001027 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1028 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1029 verify(mNpm).registerListener(policyListenerCaptor.capture());
1030 mPolicyListener = policyListenerCaptor.getValue();
1031
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001032 // Create local CM before sending system ready so that we can answer
1033 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001034 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001035 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001036 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001037 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001038
1039 // Ensure that the default setting for Captive Portals is used for most tests
1040 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001041 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001042 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001043 }
1044
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001045 private ConnectivityService.Dependencies makeDependencies() {
1046 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1047 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1048 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1049
1050 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1051 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1052 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1053 doReturn(mNetworkStack).when(deps).getNetworkStack();
1054 doReturn(systemProperties).when(deps).getSystemProperties();
1055 doReturn(mock(Tethering.class)).when(deps).makeTethering(any(), any(), any(), any(), any());
1056 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1057 doReturn(mMetricsService).when(deps).getMetricsLogger();
1058 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1059 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
1060 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1061 doAnswer(inv -> {
1062 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1063 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1064 return mPolicyTracker;
1065 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1066
1067 return deps;
1068 }
1069
1070 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1071 doAnswer(inv -> {
1072 final long when = inv.getArgument(1);
1073 final WakeupMessage wakeupMsg = inv.getArgument(3);
1074 final Handler handler = inv.getArgument(4);
1075
1076 long delayMs = when - SystemClock.elapsedRealtime();
1077 if (delayMs < 0) delayMs = 0;
1078 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1079 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1080 + "ms into the future: " + delayMs);
1081 }
1082 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1083 delayMs);
1084
1085 return null;
1086 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1087 any(WakeupMessage.class), any());
1088
1089 doAnswer(inv -> {
1090 final WakeupMessage wakeupMsg = inv.getArgument(0);
1091 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1092 return null;
1093 }).when(am).cancel(any(WakeupMessage.class));
1094 }
1095
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001096 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001097 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001098 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001099 if (mCellNetworkAgent != null) {
1100 mCellNetworkAgent.disconnect();
1101 mCellNetworkAgent = null;
1102 }
1103 if (mWiFiNetworkAgent != null) {
1104 mWiFiNetworkAgent.disconnect();
1105 mWiFiNetworkAgent = null;
1106 }
1107 if (mEthernetNetworkAgent != null) {
1108 mEthernetNetworkAgent.disconnect();
1109 mEthernetNetworkAgent = null;
1110 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001111 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001112
1113 mCsHandlerThread.quitSafely();
1114 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001115 }
1116
Rubin Xu9e64dc02019-04-23 18:04:14 +01001117 private void mockDefaultPackages() throws Exception {
1118 final String testPackageName = mContext.getPackageName();
1119 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1120 testPackageName, PackageManager.GET_PERMISSIONS);
1121 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1122 new String[] {testPackageName});
1123 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1124 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1125
1126 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1127 Arrays.asList(new PackageInfo[] {
1128 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1129 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1130 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1131 }));
1132 }
1133
Paul Jensend7b6ca92015-05-13 14:05:12 -04001134 private void verifyActiveNetwork(int transport) {
1135 // Test getActiveNetworkInfo()
1136 assertNotNull(mCm.getActiveNetworkInfo());
1137 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1138 // Test getActiveNetwork()
1139 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001140 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001141 if (!NetworkCapabilities.isValidTransport(transport)) {
1142 throw new IllegalStateException("Unknown transport " + transport);
1143 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001144 switch (transport) {
1145 case TRANSPORT_WIFI:
1146 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1147 break;
1148 case TRANSPORT_CELLULAR:
1149 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1150 break;
1151 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001152 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001153 }
1154 // Test getNetworkInfo(Network)
1155 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001156 assertEquals(transportToLegacyType(transport),
1157 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001158 // Test getNetworkCapabilities(Network)
1159 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1160 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1161 }
1162
1163 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001164 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001165 // Test getActiveNetworkInfo()
1166 assertNull(mCm.getActiveNetworkInfo());
1167 // Test getActiveNetwork()
1168 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001169 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001170 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001171 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001172 }
1173
1174 /**
1175 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1176 * broadcasts are received.
1177 */
1178 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1179 final ConditionVariable cv = new ConditionVariable();
1180 mServiceContext.registerReceiver(new BroadcastReceiver() {
1181 private int remaining = count;
1182 public void onReceive(Context context, Intent intent) {
1183 if (--remaining == 0) {
1184 cv.open();
1185 mServiceContext.unregisterReceiver(this);
1186 }
1187 }
1188 }, new IntentFilter(CONNECTIVITY_ACTION));
1189 return cv;
1190 }
1191
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001192 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001193 public void testNetworkTypes() {
1194 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1195 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1196 // will fail. Failing here is much easier to debug.
1197 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1198 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001199 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1200 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1201
1202 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1203 // mocks, this assert exercises the ConnectivityService code path that ensures that
1204 // TYPE_ETHERNET is supported if the ethernet service is running.
1205 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001206 }
1207
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001208 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001209 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001210 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001211 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1212 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001213 assertNull(mCm.getActiveNetworkInfo());
1214 assertNull(mCm.getActiveNetwork());
1215 // Test bringing up validated cellular.
1216 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1217 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001218 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001219 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001220 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001221 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1222 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1223 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1224 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1225 // Test bringing up validated WiFi.
1226 cv = waitForConnectivityBroadcasts(2);
1227 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001228 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001229 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001230 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001231 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1232 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1233 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1234 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1235 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001236 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001237 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001238 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001239 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001240 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001241 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1242 // Test WiFi disconnect.
1243 cv = waitForConnectivityBroadcasts(1);
1244 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001245 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001246 verifyNoNetwork();
1247 }
1248
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001249 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001250 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1251 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001252 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001253 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1254 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001255 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001256 verifyActiveNetwork(TRANSPORT_WIFI);
1257 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001258 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001259 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001260 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001261 verifyActiveNetwork(TRANSPORT_WIFI);
1262 // Test cellular disconnect.
1263 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001264 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001265 verifyActiveNetwork(TRANSPORT_WIFI);
1266 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001267 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001268 cv = waitForConnectivityBroadcasts(2);
1269 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001270 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001271 verifyActiveNetwork(TRANSPORT_CELLULAR);
1272 // Test cellular disconnect.
1273 cv = waitForConnectivityBroadcasts(2);
1274 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001275 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001276 verifyActiveNetwork(TRANSPORT_WIFI);
1277 // Test WiFi disconnect.
1278 cv = waitForConnectivityBroadcasts(1);
1279 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001280 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001281 verifyNoNetwork();
1282 }
1283
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001284 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001285 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1286 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001287 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001288 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1289 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001290 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001291 verifyActiveNetwork(TRANSPORT_CELLULAR);
1292 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001293 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001294 cv = waitForConnectivityBroadcasts(2);
1295 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001296 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001297 verifyActiveNetwork(TRANSPORT_WIFI);
1298 // Test WiFi disconnect.
1299 cv = waitForConnectivityBroadcasts(2);
1300 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001301 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001302 verifyActiveNetwork(TRANSPORT_CELLULAR);
1303 // Test cellular disconnect.
1304 cv = waitForConnectivityBroadcasts(1);
1305 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001306 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001307 verifyNoNetwork();
1308 }
1309
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001310 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001311 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001312 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001313 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001314 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1315 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001316 waitFor(cv);
1317 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001318 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001319 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001320 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001321 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001322 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001323 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001324 waitFor(cv);
1325 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001326 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1327 NET_CAPABILITY_VALIDATED));
1328 // Test cellular disconnect.
1329 cv = waitForConnectivityBroadcasts(2);
1330 mCellNetworkAgent.disconnect();
1331 waitFor(cv);
1332 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001333 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001334 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001335 NET_CAPABILITY_VALIDATED));
1336 }
1337
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001338 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001339 public void testCellularOutscoresWeakWifi() throws Exception {
1340 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001341 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001342 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1343 mCellNetworkAgent.connect(true);
1344 waitFor(cv);
1345 verifyActiveNetwork(TRANSPORT_CELLULAR);
1346 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001347 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001348 cv = waitForConnectivityBroadcasts(2);
1349 mWiFiNetworkAgent.connect(true);
1350 waitFor(cv);
1351 verifyActiveNetwork(TRANSPORT_WIFI);
1352 // Test WiFi getting really weak.
1353 cv = waitForConnectivityBroadcasts(2);
1354 mWiFiNetworkAgent.adjustScore(-11);
1355 waitFor(cv);
1356 verifyActiveNetwork(TRANSPORT_CELLULAR);
1357 // Test WiFi restoring signal strength.
1358 cv = waitForConnectivityBroadcasts(2);
1359 mWiFiNetworkAgent.adjustScore(11);
1360 waitFor(cv);
1361 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001362 }
1363
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001364 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001365 public void testReapingNetwork() throws Exception {
1366 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1367 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001368 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001369 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001370 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001371 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1372 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001373 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001374 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001375 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001376 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001377 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1378 final ConditionVariable cv = waitForConnectivityBroadcasts(1);
Paul Jensene0988542015-06-25 15:30:08 -04001379 mWiFiNetworkAgent.connect(true);
1380 waitFor(cv);
1381 verifyActiveNetwork(TRANSPORT_WIFI);
1382 // Test bringing up unvalidated cellular.
1383 // Expect it to be torn down because it could never be the highest scoring network
1384 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001385 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001386 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001387 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001388 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001389 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001390 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001391 }
1392
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001393 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001394 public void testCellularFallback() throws Exception {
1395 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001396 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001397 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1398 mCellNetworkAgent.connect(true);
1399 waitFor(cv);
1400 verifyActiveNetwork(TRANSPORT_CELLULAR);
1401 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001402 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001403 cv = waitForConnectivityBroadcasts(2);
1404 mWiFiNetworkAgent.connect(true);
1405 waitFor(cv);
1406 verifyActiveNetwork(TRANSPORT_WIFI);
1407 // Reevaluate WiFi (it'll instantly fail DNS).
1408 cv = waitForConnectivityBroadcasts(2);
1409 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1410 NET_CAPABILITY_VALIDATED));
1411 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1412 // Should quickly fall back to Cellular.
1413 waitFor(cv);
1414 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1415 NET_CAPABILITY_VALIDATED));
1416 verifyActiveNetwork(TRANSPORT_CELLULAR);
1417 // Reevaluate cellular (it'll instantly fail DNS).
1418 cv = waitForConnectivityBroadcasts(2);
1419 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1420 NET_CAPABILITY_VALIDATED));
1421 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1422 // Should quickly fall back to WiFi.
1423 waitFor(cv);
1424 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1425 NET_CAPABILITY_VALIDATED));
1426 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1427 NET_CAPABILITY_VALIDATED));
1428 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001429 }
1430
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001431 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001432 public void testWiFiFallback() throws Exception {
1433 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001434 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001435 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1436 mWiFiNetworkAgent.connect(false);
1437 waitFor(cv);
1438 verifyActiveNetwork(TRANSPORT_WIFI);
1439 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001440 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001441 cv = waitForConnectivityBroadcasts(2);
1442 mCellNetworkAgent.connect(true);
1443 waitFor(cv);
1444 verifyActiveNetwork(TRANSPORT_CELLULAR);
1445 // Reevaluate cellular (it'll instantly fail DNS).
1446 cv = waitForConnectivityBroadcasts(2);
1447 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1448 NET_CAPABILITY_VALIDATED));
1449 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1450 // Should quickly fall back to WiFi.
1451 waitFor(cv);
1452 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1453 NET_CAPABILITY_VALIDATED));
1454 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001455 }
1456
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001457 @Test
1458 public void testRequiresValidation() {
1459 assertTrue(NetworkMonitorUtils.isValidationRequired(
1460 mCm.getDefaultRequest().networkCapabilities));
1461 }
1462
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001463 /**
1464 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1465 * this class receives, by calling expectCallback() exactly once each time a callback is
1466 * received. assertNoCallback may be called at any time.
1467 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001468 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001469 TestNetworkCallback() {
1470 super(TEST_CALLBACK_TIMEOUT_MS);
1471 }
1472
Chalard Jean6f4216f2019-06-05 01:40:32 +09001473 @Override
1474 public void assertNoCallback() {
1475 // TODO: better support this use case in TestableNetworkCallback
1476 waitForIdle();
1477 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001478 }
Paul Jensen3d911462015-06-12 06:40:24 -04001479
Erik Klineacdd6392016-07-07 16:50:58 +09001480 @Override
Chalard Jean6f4216f2019-06-05 01:40:32 +09001481 public <T extends CallbackRecord> T expectCallback(final KClass<T> type, final HasNetwork n,
1482 final long timeoutMs) {
1483 final T callback = super.expectCallback(type, n, timeoutMs);
1484 if (callback instanceof CallbackRecord.Losing) {
1485 // TODO : move this to the specific test(s) needing this rather than here.
1486 final CallbackRecord.Losing losing = (CallbackRecord.Losing) callback;
1487 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001488 String msg = String.format(
1489 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001490 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001491 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001492 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001493 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001494 }
1495 }
1496
1497 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1498 // only be declared in a static or top level type".
1499 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1500 for (TestNetworkCallback c : callbacks) {
1501 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001502 }
1503 }
1504
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001505 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001506 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001507 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001508 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1509 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001510 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1511 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001512 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1513 .addTransportType(TRANSPORT_WIFI).build();
1514 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1515 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001516 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001517 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1518 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1519
1520 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001521 ConditionVariable cv = waitForConnectivityBroadcasts(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001522 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001523 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001524 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1525 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001526 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1527 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001528 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001529
Paul Jensen3d911462015-06-12 06:40:24 -04001530 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1531 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001532 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001533 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001534 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1535
Paul Jensen3d911462015-06-12 06:40:24 -04001536 cv = waitForConnectivityBroadcasts(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001537 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001538 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001539 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1540 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001541 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1542 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001543 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001544
Paul Jensen3d911462015-06-12 06:40:24 -04001545 cv = waitForConnectivityBroadcasts(2);
1546 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001547 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1548 wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001549 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001550 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001551 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001552
Paul Jensen3d911462015-06-12 06:40:24 -04001553 cv = waitForConnectivityBroadcasts(1);
1554 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001555 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
1556 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001557 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001558 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001559
1560 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001561 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001562 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001563 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1564 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001565 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001566 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001567
Paul Jensen3d911462015-06-12 06:40:24 -04001568 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1569 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001570 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001571 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001572 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1573
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001574 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001575 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001576 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001577 genericNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001578 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001579 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001580 cellNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001581 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001582 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001583
Paul Jensen3d911462015-06-12 06:40:24 -04001584 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001585 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1586 wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001587 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001588
Paul Jensen3d911462015-06-12 06:40:24 -04001589 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001590 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
1591 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001592 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001593 }
1594
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001595 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001596 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001597 // This test would be flaky with the default 120ms timer: that is short enough that
1598 // lingered networks are torn down before assertions can be run. We don't want to mock the
1599 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1600 // in detecting races.
1601 mService.mLingerDelayMs = 300;
1602
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001603 NetworkRequest request = new NetworkRequest.Builder()
1604 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1605 .build();
1606 TestNetworkCallback callback = new TestNetworkCallback();
1607 mCm.registerNetworkCallback(request, callback);
1608
1609 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1610 mCm.registerDefaultNetworkCallback(defaultCallback);
1611
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001612 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1613 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1614 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001615
1616 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1617 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1618 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1619
1620 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001621 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1622 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001623 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001624 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001625
1626 mWiFiNetworkAgent.connect(true);
1627 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1628 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001629 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001630 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001631 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001632 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001633 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001634 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001635 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001636
1637 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001638 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001639 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001640 callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001641 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001642 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001643 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001644 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001645
1646 mEthernetNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001647 callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
1648 defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001649 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001650 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001651
1652 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001653 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001654 if (i % 2 == 0) {
1655 mWiFiNetworkAgent.adjustScore(-15);
1656 oldNetwork = mWiFiNetworkAgent;
1657 newNetwork = mCellNetworkAgent;
1658 } else {
1659 mWiFiNetworkAgent.adjustScore(15);
1660 oldNetwork = mCellNetworkAgent;
1661 newNetwork = mWiFiNetworkAgent;
1662
1663 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001664 callback.expectCallback(CallbackRecord.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001665 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1666 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001667 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001668 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1669 }
1670 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1671
1672 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1673 // if the network is still up.
1674 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001675 // We expect a notification about the capabilities change, and nothing else.
1676 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1677 defaultCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001678 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001679 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001680
1681 // Wifi no longer satisfies our listen, which is for an unmetered network.
1682 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001683 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1684
1685 // Disconnect our test networks.
1686 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001687 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001688 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001689 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001690 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001691 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001692 waitForIdle();
1693 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001694
1695 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001696 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001697
1698 // Check that a network is only lingered or torn down if it would not satisfy a request even
1699 // if it validated.
1700 request = new NetworkRequest.Builder().clearCapabilities().build();
1701 callback = new TestNetworkCallback();
1702
1703 mCm.registerNetworkCallback(request, callback);
1704
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001705 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001706 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001707 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1708 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001709 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001710 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001711
1712 // Bring up wifi with a score of 20.
1713 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001714 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001715 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001716 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1717 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001718 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001719 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001720
1721 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001722 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1723 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001724 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001725 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001726 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001727
1728 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001729 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001730 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001731 mWiFiNetworkAgent.adjustScore(50);
1732 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001733 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001734 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001735 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001736 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001737 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001738
1739 // Tear down wifi.
1740 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001741 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1742 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001743 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001744 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001745 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001746
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001747 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1748 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001749 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001750 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001751 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001752 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001753 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001754 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001755 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001756 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001757 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001758
1759 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001760 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1761 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001762 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001763 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001764 callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
1765 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001766 waitForIdle();
1767 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001768
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001769 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001770 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001771 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001772 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1773 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001774 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001775 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001776 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001777 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1778 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001779 // TODO: Investigate sending validated before losing.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001780 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001781 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001782 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001783
1784 NetworkRequest cellRequest = new NetworkRequest.Builder()
1785 .addTransportType(TRANSPORT_CELLULAR).build();
1786 NetworkCallback noopCallback = new NetworkCallback();
1787 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001788 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1789 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001790 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001791 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001792
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001793 // Similar to the above: lingering can start even after the lingered request is removed.
1794 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001795 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001796 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1797 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001798 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001799 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001800
1801 // Cell is now the default network. Pin it with a cell-specific request.
1802 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1803 mCm.requestNetwork(cellRequest, noopCallback);
1804
1805 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001806 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001807 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001808 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1809 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001810 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001811 // The default request is lingering on cell, but nothing happens to cell, and we send no
1812 // callbacks for it, because it's kept up by cellRequest.
1813 callback.assertNoCallback();
1814 // Now unregister cellRequest and expect cell to start lingering.
1815 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001816 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001817
1818 // Let linger run its course.
1819 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001820 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001821 callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001822
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001823 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
1824 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
1825 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001826 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001827 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001828 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001829 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001830 callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001831 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001832 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
1833 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001834 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001835
1836 // Let linger run its course.
Chalard Jean6f4216f2019-06-05 01:40:32 +09001837 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001838
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001839 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001840 mEthernetNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001841 callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
1842 defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
1843 trackDefaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001844
1845 mCm.unregisterNetworkCallback(callback);
1846 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001847 mCm.unregisterNetworkCallback(trackDefaultCallback);
1848 }
1849
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001850 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001851 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001852 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001853 NetworkRequest request = new NetworkRequest.Builder()
1854 .clearCapabilities()
1855 .build();
1856 TestNetworkCallback callback = new TestNetworkCallback();
1857 mCm.registerNetworkCallback(request, callback);
1858
1859 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1860 mCm.registerDefaultNetworkCallback(defaultCallback);
1861
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001862 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1863 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001864
1865 mCellNetworkAgent.connect(true);
1866 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1867 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1868
1869 // Wifi comes up and cell lingers.
1870 mWiFiNetworkAgent.connect(true);
1871 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1872 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001873 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001874 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1875
1876 // File a request for cellular, then release it.
1877 NetworkRequest cellRequest = new NetworkRequest.Builder()
1878 .addTransportType(TRANSPORT_CELLULAR).build();
1879 NetworkCallback noopCallback = new NetworkCallback();
1880 mCm.requestNetwork(cellRequest, noopCallback);
1881 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001882 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001883
1884 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09001885 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09001886 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
1887 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
1888 lingerTimeoutMs);
1889
1890 // Clean up.
1891 mCm.unregisterNetworkCallback(defaultCallback);
1892 mCm.unregisterNetworkCallback(callback);
1893 }
1894
1895 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001896 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001897 NetworkRequest request = new NetworkRequest.Builder()
1898 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
1899 .build();
1900 TestNetworkCallback callback = new TestNetworkCallback();
1901 mCm.registerNetworkCallback(request, callback);
1902
1903 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001904 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001905 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001906 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001907
1908 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001909 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001910 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001911 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001912 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001913
1914 // Cell Remains the default.
1915 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1916
1917 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
1918 // it's explicitly selected.
1919 mWiFiNetworkAgent.adjustScore(-40);
1920 mWiFiNetworkAgent.adjustScore(40);
1921 callback.assertNoCallback();
1922
1923 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
1924 // wifi even though it's unvalidated.
1925 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001926 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001927 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1928
1929 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
1930 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001931 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001932 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001933 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001934 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001935 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001936
1937 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
1938 // network to disconnect.
1939 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001940 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001941
1942 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001943 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001944 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001945 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001946 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001947 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001948 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1949 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1950
1951 // BUG: the network will no longer linger, even though it's validated and outscored.
1952 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001953 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001954 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001955 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001956 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1957 callback.assertNoCallback();
1958
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001959 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
1960 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
1961 // wifi immediately.
1962 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001963 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001964 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001965 mWiFiNetworkAgent.explicitlySelected(true, true);
1966 mWiFiNetworkAgent.connect(false);
1967 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09001968 callback.expectCallback(CallbackRecord.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001969 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1970 mEthernetNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001971 callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001972
1973 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
1974 // Check that the network is not scored specially and that the device prefers cell data.
1975 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09001976 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001977 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09001978 mWiFiNetworkAgent.explicitlySelected(false, true);
1979 mWiFiNetworkAgent.connect(false);
1980 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1981 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1982
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001983 // Clean up.
1984 mWiFiNetworkAgent.disconnect();
1985 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001986
Chalard Jean6f4216f2019-06-05 01:40:32 +09001987 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
1988 callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001989 }
1990
Chalard Jean05ab6812018-05-02 21:14:54 +09001991 private int[] makeIntArray(final int size, final int value) {
1992 final int[] array = new int[size];
1993 Arrays.fill(array, value);
1994 return array;
1995 }
1996
Paul Jensen85cf78e2015-06-25 13:25:07 -04001997 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001998 // Verify NOT_RESTRICTED is set appropriately
1999 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2000 .build().networkCapabilities;
2001 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2002 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2003 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002004 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002005 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2006 } else {
2007 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2008 }
2009
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002010 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002011 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002012 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2013 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002014 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002015 mServiceContext, "testFactory", filter);
2016 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002017 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002018 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002019 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002020 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002021 int expectedRequestCount = 1;
2022 NetworkCallback networkCallback = null;
2023 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2024 // add one.
2025 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002026 assertFalse(testFactory.getMyStartRequested());
2027 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2028 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002029 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002030 mCm.requestNetwork(request, networkCallback);
2031 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002032 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002033 }
Paul Jensen3d911462015-06-12 06:40:24 -04002034 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002035 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2036 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002037
Paul Jensen85cf78e2015-06-25 13:25:07 -04002038 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002039 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002040 // Rather than create a validated network which complicates things by registering it's
2041 // own NetworkRequest during startup, just bump up the score to cancel out the
2042 // unvalidated penalty.
2043 testAgent.adjustScore(40);
2044 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002045
2046 // When testAgent connects, ConnectivityService will re-send us all current requests with
2047 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2048 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002049 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002050 testAgent.connect(false);
2051 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002052 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002053 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002054 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002055
Paul Jensen85cf78e2015-06-25 13:25:07 -04002056 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002057 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002058 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002059 ConnectivityManager.NetworkCallback[] networkCallbacks =
2060 new ConnectivityManager.NetworkCallback[10];
2061 for (int i = 0; i< networkCallbacks.length; i++) {
2062 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2063 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002064 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002065 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2066 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002067 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2068 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002069
Paul Jensen85cf78e2015-06-25 13:25:07 -04002070 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002071 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002072 for (int i = 0; i < networkCallbacks.length; i++) {
2073 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2074 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002075 testFactory.waitForNetworkRequests(expectedRequestCount);
2076 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002077
Paul Jensen85cf78e2015-06-25 13:25:07 -04002078 // Drop the higher scored network.
2079 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002080 // With the default network disconnecting, the requests are sent with score 0 to factories.
2081 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002082 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002083 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002084 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002085 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2086 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002087
2088 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002089 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002090 handlerThread.quit();
2091 }
2092
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002093 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002094 public void testNetworkFactoryRequests() throws Exception {
2095 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2096 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2097 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2098 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2099 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2100 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2101 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2102 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2103 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2104 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2105 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2106 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2107 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2108 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2109 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2110 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2111 }
2112
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002113 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002114 public void testNoMutableNetworkRequests() throws Exception {
2115 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002116 NetworkRequest request1 = new NetworkRequest.Builder()
2117 .addCapability(NET_CAPABILITY_VALIDATED)
2118 .build();
2119 NetworkRequest request2 = new NetworkRequest.Builder()
2120 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2121 .build();
2122
2123 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002124 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2125 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2126 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2127 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002128 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002129
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002130 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002131 public void testMMSonWiFi() throws Exception {
2132 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002133 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002134 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002135 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002136 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002137 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002138 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002139 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002140
Paul Jensene0988542015-06-25 15:30:08 -04002141 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002142 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2143 final ConditionVariable cv = waitForConnectivityBroadcasts(1);
Paul Jensene0988542015-06-25 15:30:08 -04002144 mWiFiNetworkAgent.connect(true);
2145 waitFor(cv);
2146 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002147
Paul Jensene0988542015-06-25 15:30:08 -04002148 // Register MMS NetworkRequest
2149 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2150 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2151 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2152 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002153
Paul Jensene0988542015-06-25 15:30:08 -04002154 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002155 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002156 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002157 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002158 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002159 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002160
Paul Jensene0988542015-06-25 15:30:08 -04002161 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002162 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002163 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002164 verifyActiveNetwork(TRANSPORT_WIFI);
2165 }
2166
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002167 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002168 public void testMMSonCell() throws Exception {
2169 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002170 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002171 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2172 mCellNetworkAgent.connect(false);
2173 waitFor(cv);
2174 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002175
Paul Jensene0988542015-06-25 15:30:08 -04002176 // Register MMS NetworkRequest
2177 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2178 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2179 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2180 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002181
Paul Jensene0988542015-06-25 15:30:08 -04002182 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002183 TestNetworkAgentWrapper
2184 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002185 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2186 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002187 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002188 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002189
Paul Jensene0988542015-06-25 15:30:08 -04002190 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002191 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002192 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002193 verifyActiveNetwork(TRANSPORT_CELLULAR);
2194 }
2195
lucaslinf3b59b32019-03-26 17:49:49 +08002196 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002197 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002198 // Register network callback.
2199 NetworkRequest request = new NetworkRequest.Builder()
2200 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2201 .build();
2202 TestNetworkCallback callback = new TestNetworkCallback();
2203 mCm.registerNetworkCallback(request, callback);
2204
2205 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002206 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002207 mCellNetworkAgent.connect(true);
2208 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2209
2210 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002211 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002212 mWiFiNetworkAgent.connectWithPartialConnectivity();
2213 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2214 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2215
2216 // Mobile data should be the default network.
2217 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2218 callback.assertNoCallback();
2219
lucaslinf3b59b32019-03-26 17:49:49 +08002220 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2221 // probe.
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002222 mWiFiNetworkAgent.setNetworkPartialValid();
lucasline252a742019-03-12 13:08:03 +08002223 // If the user chooses yes to use this partial connectivity wifi, switch the default
2224 // network to wifi and check if wifi becomes valid or not.
2225 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2226 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002227 // If user accepts partial connectivity network,
2228 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002229 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002230 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002231
lucaslinf3b59b32019-03-26 17:49:49 +08002232 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2233 // validated.
2234 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002235 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002236 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2237 mWiFiNetworkAgent);
2238 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2239 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2240
2241 // Disconnect and reconnect wifi with partial connectivity again.
2242 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002243 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002244 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002245 mWiFiNetworkAgent.connectWithPartialConnectivity();
2246 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2247 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2248
2249 // Mobile data should be the default network.
2250 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2251
2252 // If the user chooses no, disconnect wifi immediately.
2253 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2254 false /* always */);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002255 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002256
2257 // If user accepted partial connectivity before, and device reconnects to that network
2258 // again, but now the network has full connectivity. The network shouldn't contain
2259 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002260 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002261 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002262 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2263 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002264 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002265
lucaslinf3b59b32019-03-26 17:49:49 +08002266 // If user accepted partial connectivity network before,
2267 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2268 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002269 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002270 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002271 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002272 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2273 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002274
lucasline252a742019-03-12 13:08:03 +08002275 // Wifi should be the default network.
2276 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2277 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002278 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002279
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002280 // The user accepted partial connectivity and selected "don't ask again". Now the user
2281 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2282 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002283 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002284 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2285 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002286 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002287 // If user accepted partial connectivity network before,
2288 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2289 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002290 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002291 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002292 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002293 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002294 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2295 mWiFiNetworkAgent.setNetworkValid();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002296
lucaslinf3b59b32019-03-26 17:49:49 +08002297 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2298 // validated.
2299 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2300 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2301 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002302 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002303
2304 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2305 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002306 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002307 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2308 true /* acceptUnvalidated */);
2309
2310 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2311 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2312 // notifyNetworkConnected.
2313 mWiFiNetworkAgent.connectWithPartialValidConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002314 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002315 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002316 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002317 callback.expectCapabilitiesWith(
2318 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2319 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002320 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002321 }
2322
2323 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002324 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002325 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2326 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2327 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2328 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2329
2330 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2331 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2332 .addCapability(NET_CAPABILITY_VALIDATED).build();
2333 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2334
2335 // Bring up a network with a captive portal.
2336 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002337 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002338 String redirectUrl = "http://android.com/path";
2339 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002340 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002341 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002342
2343 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2344 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2345 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2346 .launchCaptivePortalApp();
2347
2348 // Report that the captive portal is dismissed with partial connectivity, and check that
2349 // callbacks are fired.
2350 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002351 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002352 waitForIdle();
2353 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2354 mWiFiNetworkAgent);
2355
2356 // Report partial connectivity is accepted.
2357 mWiFiNetworkAgent.setNetworkPartialValid();
2358 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2359 false /* always */);
2360 waitForIdle();
2361 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002362 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002363 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2364 NetworkCapabilities nc =
2365 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2366 mWiFiNetworkAgent);
2367
2368 mCm.unregisterNetworkCallback(captivePortalCallback);
2369 mCm.unregisterNetworkCallback(validatedCallback);
2370 }
2371
2372 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002373 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002374 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2375 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2376 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2377 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2378
2379 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2380 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2381 .addCapability(NET_CAPABILITY_VALIDATED).build();
2382 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002383
2384 // Bring up a network with a captive portal.
2385 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002386 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002387 String firstRedirectUrl = "http://example.com/firstPath";
2388 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002389 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002390 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002391
2392 // Take down network.
2393 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002394 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002395 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002396
2397 // Bring up a network with a captive portal.
2398 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002399 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002400 String secondRedirectUrl = "http://example.com/secondPath";
2401 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002402 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002403 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002404
2405 // Make captive portal disappear then revalidate.
2406 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002407 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002408 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002409 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002410
2411 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002412 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002413 // Expect no notification to be shown when captive portal disappears by itself
2414 verify(mNotificationManager, never()).notifyAsUser(
2415 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002416
2417 // Break network connectivity.
2418 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002419 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002420 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002421 validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002422 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002423
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002424 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002425 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002426 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2427 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2428 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2429 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2430
2431 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2432 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2433 .addCapability(NET_CAPABILITY_VALIDATED).build();
2434 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2435
2436 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002437 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002438 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002439 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002440 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2441
2442 // Check that calling startCaptivePortalApp does nothing.
2443 final int fastTimeoutMs = 100;
2444 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002445 waitForIdle();
2446 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002447 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2448
2449 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002450 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002451 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002452 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002453 validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002454
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002455 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002456 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002457 waitForIdle();
2458 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2459
2460 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2461 final Bundle testBundle = new Bundle();
2462 final String testKey = "testkey";
2463 final String testValue = "testvalue";
2464 testBundle.putString(testKey, testValue);
2465 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2466 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2467 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2468 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002469
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002470 // Report that the captive portal is dismissed, and check that callbacks are fired
2471 mWiFiNetworkAgent.setNetworkValid();
2472 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002473 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002474 captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002475 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2476 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002477
2478 mCm.unregisterNetworkCallback(validatedCallback);
2479 mCm.unregisterNetworkCallback(captivePortalCallback);
2480 }
2481
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002482 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002483 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002484 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2485 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2486 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2487 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2488
2489 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2490 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2491 .addCapability(NET_CAPABILITY_VALIDATED).build();
2492 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2493
2494 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2495 // Bring up a network with a captive portal.
2496 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002497 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002498 String firstRedirectUrl = "http://example.com/firstPath";
2499
Calvin On1f64f3f2016-10-11 15:10:46 -07002500 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002501 mWiFiNetworkAgent.expectDisconnected();
2502 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002503
2504 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002505 }
2506
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002507 private NetworkRequest.Builder newWifiRequestBuilder() {
2508 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2509 }
2510
Etan Cohen836ad572018-12-30 17:59:59 -08002511 /**
2512 * Verify request matching behavior with network specifiers.
2513 *
2514 * Note: this test is somewhat problematic since it involves removing capabilities from
2515 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2516 * as a WTF bug in
2517 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2518 * does work.
2519 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002520 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002521 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002522 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2523 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2524 Parcelable {
2525 @Override
2526 public boolean satisfiedBy(NetworkSpecifier other) {
2527 return true;
2528 }
2529
2530 @Override
2531 public int describeContents() {
2532 return 0;
2533 }
2534
2535 @Override
2536 public void writeToParcel(Parcel dest, int flags) {}
2537
2538 @Override
2539 public NetworkSpecifier redact() {
2540 return null;
2541 }
2542 }
2543
2544 // A network specifier that matches either another LocalNetworkSpecifier with the same
2545 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2546 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2547 private String mString;
2548
2549 LocalStringNetworkSpecifier(String string) {
2550 mString = string;
2551 }
2552
2553 @Override
2554 public boolean satisfiedBy(NetworkSpecifier other) {
2555 if (other instanceof LocalStringNetworkSpecifier) {
2556 return TextUtils.equals(mString,
2557 ((LocalStringNetworkSpecifier) other).mString);
2558 }
2559 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2560 return false;
2561 }
2562
2563 @Override
2564 public int describeContents() {
2565 return 0;
2566 }
2567 @Override
2568 public void writeToParcel(Parcel dest, int flags) {}
2569 }
2570
2571
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002572 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002573 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002574 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002575 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2576 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002577 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2578 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002579 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002580 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002581
2582 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2583 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2584 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002585 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002586 TestNetworkCallback cFoo = new TestNetworkCallback();
2587 TestNetworkCallback cBar = new TestNetworkCallback();
2588 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002589 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002590
2591 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2592 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2593 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002594 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002595 mCm.registerNetworkCallback(rFoo, cFoo);
2596 mCm.registerNetworkCallback(rBar, cBar);
2597
Etan Cohen836ad572018-12-30 17:59:59 -08002598 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2599 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2600
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002601 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002602 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002603 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2604 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2605 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2606 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002607 assertNoCallbacks(cFoo, cBar);
2608
Etan Cohen836ad572018-12-30 17:59:59 -08002609 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002610 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002611 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002612 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2613 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002614 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002615 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2616 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002617 assertEquals(nsFoo,
2618 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002619 cFoo.assertNoCallback();
2620
Etan Cohen836ad572018-12-30 17:59:59 -08002621 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002622 cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002623 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002624 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002625 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2626 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002627 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002628 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2629 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08002630 assertEquals(nsBar,
2631 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2632 cBar.assertNoCallback();
2633
2634 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2635 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2636 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002637 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2638 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002639 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002640 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2641 (caps) -> caps.getNetworkSpecifier() == null);
2642 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2643 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002644 assertNull(
2645 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2646 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002647 cBar.assertNoCallback();
2648
2649 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002650 cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
2651 cBar.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002652 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002653 c.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002654 }
2655
Etan Cohen836ad572018-12-30 17:59:59 -08002656 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002657 }
2658
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002659 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002660 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09002661 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002662 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002663 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09002664 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002665
Chalard Jean751bb3f2019-06-19 23:29:58 +09002666 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002667 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2668 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002669 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002670 mService.requestNetwork(networkCapabilities, null, 0, null,
2671 ConnectivityManager.TYPE_WIFI);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002672 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002673
Etan Cohena7434272017-04-03 12:17:51 -07002674 class NonParcelableSpecifier extends NetworkSpecifier {
2675 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2676 };
2677 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2678 @Override public int describeContents() { return 0; }
2679 @Override public void writeToParcel(Parcel p, int flags) {}
2680 }
Etan Cohena7434272017-04-03 12:17:51 -07002681
Chalard Jean751bb3f2019-06-19 23:29:58 +09002682 final NetworkRequest.Builder builder =
2683 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2684 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002685 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2686 Parcel parcelW = Parcel.obtain();
2687 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002688 });
Etan Cohena7434272017-04-03 12:17:51 -07002689
Chalard Jean751bb3f2019-06-19 23:29:58 +09002690 final NetworkRequest nr =
2691 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
2692 .setNetworkSpecifier(new ParcelableSpecifier())
2693 .build();
Etan Cohena7434272017-04-03 12:17:51 -07002694 assertNotNull(nr);
2695
Chalard Jean751bb3f2019-06-19 23:29:58 +09002696 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002697 Parcel parcelW = Parcel.obtain();
2698 nr.writeToParcel(parcelW, 0);
2699 byte[] bytes = parcelW.marshall();
2700 parcelW.recycle();
2701
2702 Parcel parcelR = Parcel.obtain();
2703 parcelR.unmarshall(bytes, 0, bytes.length);
2704 parcelR.setDataPosition(0);
2705 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002706 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002707 }
2708
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002709 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002710 public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
Etan Cohen859748f2017-04-03 17:42:34 -07002711 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2712 @Override
2713 public boolean satisfiedBy(NetworkSpecifier other) {
2714 return true;
2715 }
2716
2717 @Override
2718 public void assertValidFromUid(int requestorUid) {
2719 throw new SecurityException("failure");
2720 }
2721
2722 @Override
2723 public int describeContents() { return 0; }
2724 @Override
2725 public void writeToParcel(Parcel dest, int flags) {}
2726 }
2727
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002728 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07002729 mWiFiNetworkAgent.connect(false);
2730
2731 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2732 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2733 networkSpecifier).build();
2734 TestNetworkCallback networkCallback = new TestNetworkCallback();
Chalard Jean751bb3f2019-06-19 23:29:58 +09002735 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07002736 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002737 });
Etan Cohen859748f2017-04-03 17:42:34 -07002738 }
2739
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002740 @Test
paulhu3d67f532019-03-22 16:35:06 +08002741 public void testInvalidSignalStrength() {
2742 NetworkRequest r = new NetworkRequest.Builder()
2743 .addCapability(NET_CAPABILITY_INTERNET)
2744 .addTransportType(TRANSPORT_WIFI)
2745 .setSignalStrength(-75)
2746 .build();
2747 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
2748 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002749 assertThrows(SecurityException.class, () ->
2750 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002751
Chalard Jean751bb3f2019-06-19 23:29:58 +09002752 assertThrows(SecurityException.class, () ->
2753 mCm.registerNetworkCallback(r, PendingIntent.getService(
2754 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002755
2756 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002757 assertThrows(IllegalArgumentException.class, () ->
2758 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002759
Chalard Jean751bb3f2019-06-19 23:29:58 +09002760 assertThrows(IllegalArgumentException.class, () ->
2761 mCm.requestNetwork(r, PendingIntent.getService(
2762 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002763 }
2764
2765 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002766 public void testRegisterDefaultNetworkCallback() throws Exception {
2767 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2768 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2769 defaultNetworkCallback.assertNoCallback();
2770
2771 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2772 // whenever Wi-Fi is up. Without this, the mobile network agent is
2773 // reaped before any other activity can take place.
2774 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2775 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2776 .addTransportType(TRANSPORT_CELLULAR).build();
2777 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2778 cellNetworkCallback.assertNoCallback();
2779
2780 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002781 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002782 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002783 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2784 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002785 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002786
2787 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002788 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09002789 mWiFiNetworkAgent.connect(true);
2790 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002791 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002792 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002793
2794 // Bring down cell. Expect no default network callback, since it wasn't the default.
2795 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002796 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002797 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002798 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002799
2800 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002801 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002802 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002803 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002804 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002805 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002806
2807 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2808 // followed by AVAILABLE cell.
2809 mWiFiNetworkAgent.disconnect();
2810 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002811 defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002812 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002813 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002814 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
2815 defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002816 waitForIdle();
2817 assertEquals(null, mCm.getActiveNetwork());
2818
2819 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002820 final TestNetworkAgentWrapper
2821 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002822 final ArraySet<UidRange> ranges = new ArraySet<>();
2823 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002824 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2825 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002826 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002827 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002828 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2829 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2830
2831 vpnNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002832 defaultNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002833 waitForIdle();
2834 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002835 }
2836
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002837 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002838 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002839 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002840 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002841 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2842 .addTransportType(TRANSPORT_CELLULAR).build();
2843 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2844
2845 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002846 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09002847 mCellNetworkAgent.connect(true);
2848
Erik Kline1d3db322017-02-28 16:20:20 +09002849 // We should get onAvailable(), onCapabilitiesChanged(), and
2850 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2851 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002852 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002853 cellNetworkCallback.assertNoCallback();
2854
2855 // Update LinkProperties.
2856 final LinkProperties lp = new LinkProperties();
2857 lp.setInterfaceName("foonet_data0");
2858 mCellNetworkAgent.sendLinkProperties(lp);
2859 // We should get onLinkPropertiesChanged().
Chalard Jean6f4216f2019-06-05 01:40:32 +09002860 cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
2861 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002862 cellNetworkCallback.assertNoCallback();
2863
Erik Kline1d3db322017-02-28 16:20:20 +09002864 // Suspend the network.
2865 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002866 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
2867 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002868 cellNetworkCallback.expectCallback(CallbackRecord.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002869 cellNetworkCallback.assertNoCallback();
2870
Erik Klineacdd6392016-07-07 16:50:58 +09002871 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09002872 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002873 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002874 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2875 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002876 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09002877 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002878 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2879
2880 mCellNetworkAgent.resume();
2881 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
2882 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002883 cellNetworkCallback.expectCallback(CallbackRecord.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09002884 cellNetworkCallback.assertNoCallback();
2885
2886 dfltNetworkCallback = new TestNetworkCallback();
2887 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2888 // This time onNetworkSuspended should not be called.
2889 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2890 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002891
Erik Klineacdd6392016-07-07 16:50:58 +09002892 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2893 mCm.unregisterNetworkCallback(cellNetworkCallback);
2894 }
2895
Calvin On1f64f3f2016-10-11 15:10:46 -07002896 private void setCaptivePortalMode(int mode) {
2897 ContentResolver cr = mServiceContext.getContentResolver();
2898 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2899 }
2900
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002901 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002902 ContentResolver cr = mServiceContext.getContentResolver();
2903 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002904 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09002905 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002906 }
2907
Erik Kline79c6d052018-03-21 07:18:33 -07002908 private void setPrivateDnsSettings(String mode, String specifier) {
2909 final ContentResolver cr = mServiceContext.getContentResolver();
2910 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
2911 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
2912 mService.updatePrivateDnsSettings();
2913 waitForIdle();
2914 }
2915
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002916 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002917 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2918 assertNotNull(nc);
2919 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2920 }
2921
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002922 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002923 public void testBackgroundNetworks() throws Exception {
2924 // Create a background request. We can't do this ourselves because ConnectivityService
2925 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002926 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002927 final NetworkRequest request = new NetworkRequest.Builder().build();
2928 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2929 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2930 final TestNetworkCallback callback = new TestNetworkCallback();
2931 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2932 mCm.registerNetworkCallback(request, callback);
2933 mCm.registerNetworkCallback(fgRequest, fgCallback);
2934
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002935 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002936 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002937 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2938 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002939 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2940
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002941 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002942 mWiFiNetworkAgent.connect(true);
2943
2944 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002945 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002946 callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002947 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002948 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002949 fgCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002950 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002951 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2952 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2953
2954 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09002955 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002956 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean6f4216f2019-06-05 01:40:32 +09002957 fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09002958 // Expect a network capabilities update sans FOREGROUND.
2959 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002960 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2961 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2962
2963 // File a cell request and check that cell comes into the foreground.
2964 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2965 .addTransportType(TRANSPORT_CELLULAR).build();
2966 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2967 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002968 // NOTE: This request causes the network's capabilities to change. This
2969 // is currently delivered before the onAvailable() callbacks.
2970 // TODO: Fix this.
2971 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002972 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2973 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002974 // Expect a network capabilities update with FOREGROUND, because the most recent
2975 // request causes its state to change.
2976 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002977 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2978 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2979
2980 // Release the request. The network immediately goes into the background, since it was not
2981 // lingering.
2982 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean6f4216f2019-06-05 01:40:32 +09002983 fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002984 // Expect a network capabilities update sans FOREGROUND.
2985 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002986 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2987 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2988
2989 // Disconnect wifi and check that cell is foreground again.
2990 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09002991 callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
2992 fgCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002993 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002994 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2995
2996 mCm.unregisterNetworkCallback(callback);
2997 mCm.unregisterNetworkCallback(fgCallback);
2998 }
2999
Hugo Benichi849b81b2017-05-25 13:42:31 +09003000 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003001 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003002 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003003 // Benchmarks connecting and switching performance in the presence of a large number of
3004 // NetworkRequests.
3005 // 1. File NUM_REQUESTS requests.
3006 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3007 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3008 // and NUM_REQUESTS onAvailable callbacks to fire.
3009 // See how long it took.
3010 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003011 final int REGISTER_TIME_LIMIT_MS = 200;
3012 final int CONNECT_TIME_LIMIT_MS = 60;
3013 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003014 final int UNREGISTER_TIME_LIMIT_MS = 20;
3015
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003016 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3017 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3018 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3019 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3020
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003021 for (int i = 0; i < NUM_REQUESTS; i++) {
3022 callbacks[i] = new NetworkCallback() {
3023 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3024 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3025 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003026 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003027
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003028 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003029 for (NetworkCallback cb : callbacks) {
3030 mCm.registerNetworkCallback(request, cb);
3031 }
3032 });
3033
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003034 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003035 // Don't request that the network validate, because otherwise connect() will block until
3036 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3037 // and we won't actually measure anything.
3038 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003039
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003040 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003041 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003042 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003043 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3044 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3045 onAvailableDispatchingDuration));
3046 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3047 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3048 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003049
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003050 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003051 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003052 mWiFiNetworkAgent.adjustScore(40);
3053 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003054
3055 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003056 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003057 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003058 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3059 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3060 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3061 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3062 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003063
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003064 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003065 for (NetworkCallback cb : callbacks) {
3066 mCm.unregisterNetworkCallback(cb);
3067 }
3068 });
3069 }
3070
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003071 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003072 public void testMobileDataAlwaysOn() throws Exception {
3073 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3074 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3075 .addTransportType(TRANSPORT_CELLULAR).build();
3076 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3077
3078 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3079 handlerThread.start();
3080 NetworkCapabilities filter = new NetworkCapabilities()
3081 .addTransportType(TRANSPORT_CELLULAR)
3082 .addCapability(NET_CAPABILITY_INTERNET);
3083 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3084 mServiceContext, "testFactory", filter);
3085 testFactory.setScoreFilter(40);
3086
3087 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003088 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003089 testFactory.register();
3090 testFactory.waitForNetworkRequests(1);
3091 assertTrue(testFactory.getMyStartRequested());
3092
3093 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003094 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003095 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3096 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003097 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003098 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003099 assertFalse(testFactory.getMyStartRequested());
3100
3101 ContentResolver cr = mServiceContext.getContentResolver();
3102
3103 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003104 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003105 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003106 testFactory.waitForNetworkRequests(2);
3107 assertTrue(testFactory.getMyStartRequested());
3108
3109 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003110 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003111 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003112 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003113 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003114 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003115 testFactory.waitForNetworkRequests(2);
3116 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3117
3118 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003119 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003120 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003121 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003122
3123 // Turn off mobile data always on and expect the request to disappear...
3124 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003125 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003126 testFactory.waitForNetworkRequests(1);
3127
3128 // ... and cell data to be torn down.
Chalard Jean6f4216f2019-06-05 01:40:32 +09003129 cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003130 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003131
3132 testFactory.unregister();
3133 mCm.unregisterNetworkCallback(cellNetworkCallback);
3134 handlerThread.quit();
3135 }
3136
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003137 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003138 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003139 final ContentResolver cr = mServiceContext.getContentResolver();
3140 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3141
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003142 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003143 String[] values = new String[] {null, "0", "1"};
3144 for (int i = 0; i < values.length; i++) {
3145 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003146 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003147 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003148 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003149 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003150 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003151 }
3152
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003153 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003154
3155 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003156 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003157 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003158 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003159 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003160
3161 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003162 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003163 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003164 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003165 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003166
3167 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003168 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003169 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003170 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003171 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003172 }
3173
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003174 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003175 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003176 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003177
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003178 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003179 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003180
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003181 // File a request for cell to ensure it doesn't go down.
3182 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3183 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3184 .addTransportType(TRANSPORT_CELLULAR).build();
3185 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3186
3187 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3188 mCm.registerDefaultNetworkCallback(defaultCallback);
3189
3190 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3191 .addTransportType(TRANSPORT_WIFI)
3192 .addCapability(NET_CAPABILITY_VALIDATED)
3193 .build();
3194 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3195 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3196
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003197 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003198 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003199
3200 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003201 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003202 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003203 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3204 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003205 Network cellNetwork = mCellNetworkAgent.getNetwork();
3206
3207 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003208 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003209 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003210 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3211 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003212 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3213
3214 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003215 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003216 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003217 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09003218 validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003219
3220 // Because avoid bad wifi is off, we don't switch to cellular.
3221 defaultCallback.assertNoCallback();
3222 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3223 NET_CAPABILITY_VALIDATED));
3224 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3225 NET_CAPABILITY_VALIDATED));
3226 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3227
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003228 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3229 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003230 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3231 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003232 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003233 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3234
3235 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003236 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3237 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003238 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003239 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3240
3241 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3242 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003243 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003244 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3245 NET_CAPABILITY_VALIDATED));
3246 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3247 NET_CAPABILITY_VALIDATED));
3248 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3249
3250 // Disconnect and reconnect wifi to clear the one-time switch above.
3251 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003252 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003253 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003254 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3255 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003256 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3257
3258 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003259 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003260 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003261 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09003262 validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003263
3264 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003265 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003266 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003267
3268 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003269 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003270 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3271 NET_CAPABILITY_VALIDATED));
3272 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3273 NET_CAPABILITY_VALIDATED));
3274 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3275
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003276 // Simulate the user turning the cellular fallback setting off and then on.
3277 // We switch to wifi and then to cell.
3278 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003279 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003280 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003281 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3282 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003283 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003284 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003285 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3286
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003287 // If cell goes down, we switch to wifi.
3288 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09003289 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003290 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003291 validatedWifiCallback.assertNoCallback();
3292
3293 mCm.unregisterNetworkCallback(cellNetworkCallback);
3294 mCm.unregisterNetworkCallback(validatedWifiCallback);
3295 mCm.unregisterNetworkCallback(defaultCallback);
3296 }
3297
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003298 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003299 public void testMeteredMultipathPreferenceSetting() throws Exception {
3300 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003301 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3302
3303 for (int config : Arrays.asList(0, 3, 2)) {
3304 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003305 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003306 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003307 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003308 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003309
3310 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3311 String msg = String.format("config=%d, setting=%s", config, setting);
3312 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3313 }
3314 }
3315 }
3316
Erik Kline3841a482015-11-25 12:49:38 +09003317 /**
3318 * Validate that a satisfied network request does not trigger onUnavailable() once the
3319 * time-out period expires.
3320 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003321 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003322 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003323 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3324 NetworkCapabilities.TRANSPORT_WIFI).build();
3325 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003326 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003327
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003328 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003329 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003330 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003331 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003332
3333 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003334 networkCallback.assertNoCallback();
3335 }
3336
3337 /**
3338 * Validate that a satisfied network request followed by a disconnected (lost) network does
3339 * not trigger onUnavailable() once the time-out period expires.
3340 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003341 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003342 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003343 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3344 NetworkCapabilities.TRANSPORT_WIFI).build();
3345 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003346 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003347
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003348 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003349 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003350 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003351 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003352 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09003353 networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003354
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003355 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003356 networkCallback.assertNoCallback();
3357 }
3358
3359 /**
3360 * Validate that when a time-out is specified for a network request the onUnavailable()
3361 * callback is called when time-out expires. Then validate that if network request is
3362 * (somehow) satisfied - the callback isn't called later.
3363 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003364 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003365 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003366 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3367 NetworkCapabilities.TRANSPORT_WIFI).build();
3368 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003369 final int timeoutMs = 10;
3370 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003371
3372 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean6f4216f2019-06-05 01:40:32 +09003373 networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003374
3375 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003376 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003377 mWiFiNetworkAgent.connect(false);
3378 networkCallback.assertNoCallback();
3379 }
3380
3381 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003382 * Validate that when a network request is unregistered (cancelled), no posterior event can
3383 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003384 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003385 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003386 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003387 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3388 NetworkCapabilities.TRANSPORT_WIFI).build();
3389 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003390 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003391
Hugo Benichidfb559a2016-12-20 14:57:49 +09003392 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003393 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003394 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3395 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003396 networkCallback.assertNoCallback();
3397
3398 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003399 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003400 mWiFiNetworkAgent.connect(false);
3401 networkCallback.assertNoCallback();
3402 }
3403
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003404 @Test
3405 public void testUnfulfillableNetworkRequest() throws Exception {
3406 runUnfulfillableNetworkRequest(false);
3407 }
3408
3409 @Test
3410 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3411 runUnfulfillableNetworkRequest(true);
3412 }
3413
Etan Cohenddb720a2019-01-08 12:09:18 -08003414 /**
3415 * Validate the callback flow for a factory releasing a request as unfulfillable.
3416 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003417 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003418 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3419 NetworkCapabilities.TRANSPORT_WIFI).build();
3420 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3421
3422 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3423 handlerThread.start();
3424 NetworkCapabilities filter = new NetworkCapabilities()
3425 .addTransportType(TRANSPORT_WIFI)
3426 .addCapability(NET_CAPABILITY_INTERNET);
3427 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3428 mServiceContext, "testFactory", filter);
3429 testFactory.setScoreFilter(40);
3430
3431 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003432 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003433 testFactory.register();
3434 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3435
3436 assertEquals(1, requests.size()); // have 1 request at this point
3437 int origRequestId = requests.valueAt(0).requestId;
3438
3439 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003440 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003441 mCm.requestNetwork(nr, networkCallback);
3442 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3443
3444 int newRequestId = 0;
3445 for (int i = 0; i < requests.size(); ++i) {
3446 if (requests.valueAt(i).requestId != origRequestId) {
3447 newRequestId = requests.valueAt(i).requestId;
3448 break;
3449 }
3450 }
3451
Etan Cohen22e0fc12019-05-23 08:16:20 -07003452 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003453 if (preUnregister) {
3454 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003455
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003456 // Simulate the factory releasing the request as unfulfillable: no-op since
3457 // the callback has already been unregistered (but a test that no exceptions are
3458 // thrown).
3459 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3460 } else {
3461 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003462 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3463
Chalard Jean6f4216f2019-06-05 01:40:32 +09003464 networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003465 testFactory.waitForRequests();
3466
3467 // unregister network callback - a no-op (since already freed by the
3468 // on-unavailable), but should not fail or throw exceptions.
3469 mCm.unregisterNetworkCallback(networkCallback);
3470 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003471
Etan Cohenddb720a2019-01-08 12:09:18 -08003472 testFactory.unregister();
3473 handlerThread.quit();
3474 }
3475
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003476 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3477
Chalard Jeane7b24752019-06-20 16:01:19 +09003478 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003479
3480 private class CallbackValue {
3481 public CallbackType callbackType;
3482 public int error;
3483
3484 public CallbackValue(CallbackType type) {
3485 this.callbackType = type;
3486 this.error = PacketKeepalive.SUCCESS;
3487 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3488 }
3489
3490 public CallbackValue(CallbackType type, int error) {
3491 this.callbackType = type;
3492 this.error = error;
3493 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3494 }
3495
3496 @Override
3497 public boolean equals(Object o) {
3498 return o instanceof CallbackValue &&
3499 this.callbackType == ((CallbackValue) o).callbackType &&
3500 this.error == ((CallbackValue) o).error;
3501 }
3502
3503 @Override
3504 public String toString() {
3505 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3506 }
3507 }
3508
junyulai7c469172019-01-16 20:23:34 +08003509 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003510
3511 @Override
3512 public void onStarted() {
3513 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3514 }
3515
3516 @Override
3517 public void onStopped() {
3518 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3519 }
3520
3521 @Override
3522 public void onError(int error) {
3523 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3524 }
3525
Chalard Jeane7b24752019-06-20 16:01:19 +09003526 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3527 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003528 }
3529
Chalard Jeane7b24752019-06-20 16:01:19 +09003530 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003531 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3532 }
3533
Chalard Jeane7b24752019-06-20 16:01:19 +09003534 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003535 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3536 }
3537
Chalard Jeane7b24752019-06-20 16:01:19 +09003538 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003539 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3540 }
3541 }
3542
junyulai48eac1d42018-12-27 17:25:29 +08003543 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3544
3545 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3546
3547 private class CallbackValue {
3548 public CallbackType callbackType;
3549 public int error;
3550
3551 CallbackValue(CallbackType type) {
3552 this.callbackType = type;
3553 this.error = SocketKeepalive.SUCCESS;
3554 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3555 }
3556
3557 CallbackValue(CallbackType type, int error) {
3558 this.callbackType = type;
3559 this.error = error;
3560 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3561 }
3562
3563 @Override
3564 public boolean equals(Object o) {
3565 return o instanceof CallbackValue
3566 && this.callbackType == ((CallbackValue) o).callbackType
3567 && this.error == ((CallbackValue) o).error;
3568 }
3569
3570 @Override
3571 public String toString() {
3572 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3573 error);
3574 }
3575 }
3576
3577 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003578 private final Executor mExecutor;
3579
3580 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3581 mExecutor = executor;
3582 }
junyulai48eac1d42018-12-27 17:25:29 +08003583
3584 @Override
3585 public void onStarted() {
3586 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3587 }
3588
3589 @Override
3590 public void onStopped() {
3591 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3592 }
3593
3594 @Override
3595 public void onError(int error) {
3596 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3597 }
3598
Chalard Jeane7b24752019-06-20 16:01:19 +09003599 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3600 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3601
junyulai48eac1d42018-12-27 17:25:29 +08003602 }
3603
Chalard Jeane7b24752019-06-20 16:01:19 +09003604 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003605 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3606 }
3607
Chalard Jeane7b24752019-06-20 16:01:19 +09003608 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003609 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3610 }
3611
Chalard Jeane7b24752019-06-20 16:01:19 +09003612 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003613 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3614 }
junyulai7c469172019-01-16 20:23:34 +08003615
3616 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003617 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003618 CallbackValue cv = mCallbacks.peek();
3619 assertNull("Unexpected callback: " + cv, cv);
3620 }
junyulai48eac1d42018-12-27 17:25:29 +08003621 }
3622
Chalard Jeane7b24752019-06-20 16:01:19 +09003623 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003624 // Ensure the network is disconnected before we do anything.
3625 if (mWiFiNetworkAgent != null) {
3626 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3627 }
3628
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003629 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003630 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3631 mWiFiNetworkAgent.connect(true);
3632 waitFor(cv);
3633 verifyActiveNetwork(TRANSPORT_WIFI);
3634 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003635 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003636 return mWiFiNetworkAgent.getNetwork();
3637 }
3638
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003639 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003640 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003641 public void testPacketKeepalives() throws Exception {
3642 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3643 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3644 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3645 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3646 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3647
Nathan Harold63dd8132018-02-14 13:09:45 -08003648 final int validKaInterval = 15;
3649 final int invalidKaInterval = 9;
3650
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003651 LinkProperties lp = new LinkProperties();
3652 lp.setInterfaceName("wlan12");
3653 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3654 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3655 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3656 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3657
3658 Network notMyNet = new Network(61234);
3659 Network myNet = connectKeepaliveNetwork(lp);
3660
3661 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3662 PacketKeepalive ka;
3663
3664 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003665 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003666 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3667
Nathan Harold63dd8132018-02-14 13:09:45 -08003668 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003669 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3670
Nathan Harold63dd8132018-02-14 13:09:45 -08003671 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003672 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3673
Nathan Harold63dd8132018-02-14 13:09:45 -08003674 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003675 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3676
Nathan Harold63dd8132018-02-14 13:09:45 -08003677 // NAT-T is only supported for IPv4.
3678 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3679 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003680
Nathan Harold63dd8132018-02-14 13:09:45 -08003681 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003682 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3683
Nathan Harold63dd8132018-02-14 13:09:45 -08003684 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003685 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3686
Nathan Harold63dd8132018-02-14 13:09:45 -08003687 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003688 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3689
Nathan Harold63dd8132018-02-14 13:09:45 -08003690 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003691 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3692
3693 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003694 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003695 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003696 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003697 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003698 ka.stop();
3699 callback.expectStopped();
3700
3701 // Check that deleting the IP address stops the keepalive.
3702 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003703 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003704 callback.expectStarted();
3705 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3706 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3707 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3708 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3709 mWiFiNetworkAgent.sendLinkProperties(lp);
3710
3711 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003712 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003713 callback.expectStarted();
3714 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003715 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003716 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3717
3718 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003719 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003720 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003721 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003722 ka.stop();
3723
3724 // Reconnect.
3725 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003726 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003727
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003728 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3729 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003730 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003731 callback.expectStarted();
3732
3733 // The second one gets slot 2.
3734 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3735 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003736 PacketKeepalive ka2 = mCm.startNattKeepalive(
3737 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003738 callback2.expectStarted();
3739
3740 // Now stop the first one and create a third. This also gets slot 1.
3741 ka.stop();
3742 callback.expectStopped();
3743
3744 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3745 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003746 PacketKeepalive ka3 = mCm.startNattKeepalive(
3747 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003748 callback3.expectStarted();
3749
3750 ka2.stop();
3751 callback2.expectStopped();
3752
3753 ka3.stop();
3754 callback3.expectStopped();
3755 }
Udam Sainib7c24872016-01-04 12:16:14 -08003756
Xiao Maa4637112019-02-07 15:03:57 +09003757 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09003758 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
3759 throws Exception {
junyulai06835112019-01-03 18:50:15 +08003760 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09003761 final Executor executorInline = (Runnable r) -> r.run();
3762 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08003763 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09003764 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003765 }
junyulai06835112019-01-03 18:50:15 +08003766
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003767 @Test
junyulaiafe9b492019-03-19 18:50:23 +08003768 public void testNattSocketKeepalives() throws Exception {
3769 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
3770 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08003771 }
3772
3773 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003774 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08003775 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08003776 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08003777 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3778 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3779 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3780 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3781 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3782
3783 final int validKaInterval = 15;
3784 final int invalidKaInterval = 9;
3785
3786 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08003787 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
3788 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08003789
junyulai48eac1d42018-12-27 17:25:29 +08003790 LinkProperties lp = new LinkProperties();
3791 lp.setInterfaceName("wlan12");
3792 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3793 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3794 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3795 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3796
3797 Network notMyNet = new Network(61234);
3798 Network myNet = connectKeepaliveNetwork(lp);
3799
junyulai7c469172019-01-16 20:23:34 +08003800 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08003801
3802 // Attempt to start keepalives with invalid parameters and check for errors.
3803 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08003804 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3805 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3806 ka.start(validKaInterval);
3807 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3808 }
junyulai48eac1d42018-12-27 17:25:29 +08003809
3810 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08003811 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3812 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3813 ka.start(invalidKaInterval);
3814 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3815 }
junyulai48eac1d42018-12-27 17:25:29 +08003816
3817 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08003818 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3819 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
3820 ka.start(validKaInterval);
3821 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3822 }
junyulai48eac1d42018-12-27 17:25:29 +08003823
3824 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08003825 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3826 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
3827 ka.start(validKaInterval);
3828 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3829 }
junyulai48eac1d42018-12-27 17:25:29 +08003830
3831 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08003832 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3833 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
3834 ka.start(validKaInterval);
3835 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3836 }
junyulai48eac1d42018-12-27 17:25:29 +08003837
3838 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08003839 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3840 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3841 ka.start(validKaInterval);
3842 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
3843 }
junyulai48eac1d42018-12-27 17:25:29 +08003844
3845 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003846 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08003847 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3848 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3849 ka.start(validKaInterval);
3850 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003851 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08003852 ka.stop();
3853 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08003854
junyulai0c666972019-03-04 22:45:36 +08003855 // Check that keepalive could be restarted.
3856 ka.start(validKaInterval);
3857 callback.expectStarted();
3858 ka.stop();
3859 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08003860
junyulai0c666972019-03-04 22:45:36 +08003861 // Check that keepalive can be restarted without waiting for callback.
3862 ka.start(validKaInterval);
3863 callback.expectStarted();
3864 ka.stop();
3865 ka.start(validKaInterval);
3866 callback.expectStopped();
3867 callback.expectStarted();
3868 ka.stop();
3869 callback.expectStopped();
3870 }
junyulai7c469172019-01-16 20:23:34 +08003871
junyulai48eac1d42018-12-27 17:25:29 +08003872 // Check that deleting the IP address stops the keepalive.
3873 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08003874 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3875 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3876 ka.start(validKaInterval);
3877 callback.expectStarted();
3878 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3879 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3880 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3881 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3882 mWiFiNetworkAgent.sendLinkProperties(lp);
3883 }
junyulai48eac1d42018-12-27 17:25:29 +08003884
3885 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08003886 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3887 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3888 ka.start(validKaInterval);
3889 callback.expectStarted();
3890 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003891 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08003892 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08003893
junyulai0c666972019-03-04 22:45:36 +08003894 // ... and that stopping it after that has no adverse effects.
3895 waitForIdle();
3896 final Network myNetAlias = myNet;
3897 assertNull(mCm.getNetworkCapabilities(myNetAlias));
3898 ka.stop();
3899 callback.assertNoCallback();
3900 }
junyulai48eac1d42018-12-27 17:25:29 +08003901
3902 // Reconnect.
3903 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003904 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08003905
3906 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3907 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08003908 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08003909 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3910 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3911 ka.start(validKaInterval);
3912 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08003913
junyulai0c666972019-03-04 22:45:36 +08003914 // The second one gets slot 2.
3915 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08003916 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
3917 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08003918 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
3919 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
3920 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
3921 ka2.start(validKaInterval);
3922 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08003923
junyulai0c666972019-03-04 22:45:36 +08003924 ka.stop();
3925 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08003926
junyulai0c666972019-03-04 22:45:36 +08003927 ka2.stop();
3928 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08003929
junyulai0c666972019-03-04 22:45:36 +08003930 testSocket.close();
3931 testSocket2.close();
3932 }
3933 }
junyulai06835112019-01-03 18:50:15 +08003934
junyulai15178152019-03-27 11:00:37 +08003935 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08003936 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
3937 // assertFalse(isUdpPortInUse(srcPort));
3938 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08003939
junyulai06835112019-01-03 18:50:15 +08003940 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003941 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09003942 mWiFiNetworkAgent = null;
3943 }
3944
3945 @Test
junyulaiafe9b492019-03-19 18:50:23 +08003946 public void testTcpSocketKeepalives() throws Exception {
3947 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09003948 }
3949
3950 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
3951 final int srcPortV4 = 12345;
3952 final int srcPortV6 = 23456;
3953 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
3954 final InetAddress myIPv6 = InetAddress.getByName("::1");
3955
3956 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09003957
3958 final LinkProperties lp = new LinkProperties();
3959 lp.setInterfaceName("wlan12");
3960 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3961 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3962 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3963 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
3964
3965 final Network notMyNet = new Network(61234);
3966 final Network myNet = connectKeepaliveNetwork(lp);
3967
3968 final Socket testSocketV4 = new Socket();
3969 final Socket testSocketV6 = new Socket();
3970
junyulai7c469172019-01-16 20:23:34 +08003971 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09003972
3973 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
3974 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08003975 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3976 notMyNet, testSocketV4, executor, callback)) {
3977 ka.start(validKaInterval);
3978 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3979 }
Xiao Maa4637112019-02-07 15:03:57 +09003980
3981 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08003982 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3983 myNet, testSocketV4, executor, callback)) {
3984 ka.start(validKaInterval);
3985 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
3986 }
Xiao Maa4637112019-02-07 15:03:57 +09003987
3988 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08003989 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3990 myNet, testSocketV6, executor, callback)) {
3991 ka.start(validKaInterval);
3992 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
3993 }
Xiao Maa4637112019-02-07 15:03:57 +09003994
3995 // Bind the socket address
3996 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
3997 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
3998
3999 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004000 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4001 myNet, testSocketV4, executor, callback)) {
4002 ka.start(validKaInterval);
4003 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4004 }
Xiao Maa4637112019-02-07 15:03:57 +09004005
4006 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004007 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4008 myNet, testSocketV6, executor, callback)) {
4009 ka.start(validKaInterval);
4010 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4011 }
Xiao Maa4637112019-02-07 15:03:57 +09004012
4013 testSocketV4.close();
4014 testSocketV6.close();
4015
4016 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004017 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004018 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004019 }
4020
junyulai0c666972019-03-04 22:45:36 +08004021 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004022 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4023 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4024 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4025 final int validKaInterval = 15;
4026
4027 // Prepare the target network.
4028 LinkProperties lp = new LinkProperties();
4029 lp.setInterfaceName("wlan12");
4030 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4031 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4032 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004033 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4034 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004035
4036 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4037
4038 // Prepare the target file descriptor, keep only one instance.
4039 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004040 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4041 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004042 final ParcelFileDescriptor testPfd =
4043 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4044 testSocket.close();
4045 assertTrue(isUdpPortInUse(srcPort));
4046
4047 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4048 // block.
4049 try (SocketKeepalive ka = mCm.createNattKeepalive(
4050 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4051 ka.start(validKaInterval);
4052 callback.expectStarted();
4053 ka.stop();
4054 callback.expectStopped();
4055 }
4056
4057 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4058 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4059 // address.
4060 assertTrue(isUdpPortInUse(srcPort));
4061 final InetSocketAddress sa =
4062 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4063 assertEquals(anyIPv4, sa.getAddress());
4064
4065 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004066 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4067 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004068
4069 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004070 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004071 mWiFiNetworkAgent = null;
4072 }
4073
4074 private static boolean isUdpPortInUse(int port) {
4075 try (DatagramSocket ignored = new DatagramSocket(port)) {
4076 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004077 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004078 return true;
4079 }
4080 }
4081
junyulai48eac1d42018-12-27 17:25:29 +08004082 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004083 public void testGetCaptivePortalServerUrl() throws Exception {
4084 String url = mCm.getCaptivePortalServerUrl();
4085 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4086 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004087
4088 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004089 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004090 synchronized(sLock) {
4091 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004092 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004093 }
4094 return sNetwork != null;
4095 }
4096 }
4097
Chalard Jeane7b24752019-06-20 16:01:19 +09004098 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004099 synchronized(sLock) {
4100 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004101 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004102 }
4103 return sNetwork == null;
4104 }
4105 }
4106 }
4107
4108 private void assertPinnedToWifiWithCellDefault() {
4109 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4110 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4111 }
4112
4113 private void assertPinnedToWifiWithWifiDefault() {
4114 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4115 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4116 }
4117
4118 private void assertNotPinnedToWifi() {
4119 assertNull(mCm.getBoundNetworkForProcess());
4120 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4121 }
4122
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004123 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004124 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004125 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4126 .addTransportType(TRANSPORT_WIFI)
4127 .build();
4128 assertNull(mCm.getBoundNetworkForProcess());
4129
4130 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4131 assertNull(mCm.getBoundNetworkForProcess());
4132
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004133 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004134 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004135 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004136 mWiFiNetworkAgent.connect(false);
4137
4138 // When wi-fi connects, expect to be pinned.
4139 assertTrue(TestNetworkPinner.awaitPin(100));
4140 assertPinnedToWifiWithCellDefault();
4141
4142 // Disconnect and expect the pin to drop.
4143 mWiFiNetworkAgent.disconnect();
4144 assertTrue(TestNetworkPinner.awaitUnpin(100));
4145 assertNotPinnedToWifi();
4146
4147 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004148 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004149 mWiFiNetworkAgent.connect(false);
4150 assertFalse(TestNetworkPinner.awaitPin(100));
4151 assertNotPinnedToWifi();
4152
4153 // Pinning while connected causes the pin to take effect immediately.
4154 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4155 assertTrue(TestNetworkPinner.awaitPin(100));
4156 assertPinnedToWifiWithCellDefault();
4157
4158 // Explicitly unpin and expect to use the default network again.
4159 TestNetworkPinner.unpin();
4160 assertNotPinnedToWifi();
4161
4162 // Disconnect cell and wifi.
4163 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4164 mCellNetworkAgent.disconnect();
4165 mWiFiNetworkAgent.disconnect();
4166 waitFor(cv);
4167
4168 // Pinning takes effect even if the pinned network is the default when the pin is set...
4169 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004170 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004171 mWiFiNetworkAgent.connect(false);
4172 assertTrue(TestNetworkPinner.awaitPin(100));
4173 assertPinnedToWifiWithWifiDefault();
4174
4175 // ... and is maintained even when that network is no longer the default.
4176 cv = waitForConnectivityBroadcasts(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004177 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004178 mCellNetworkAgent.connect(true);
4179 waitFor(cv);
4180 assertPinnedToWifiWithCellDefault();
4181 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004182
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004183 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004184 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004185 // We can only have 99 callbacks, because MultipathPolicyTracker is
4186 // already one of them.
4187 final int MAX_REQUESTS = 99;
4188 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004189 final int INTENTS = 10;
4190 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4191
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004192 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004193 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004194
Hugo Benichi893a7622017-09-29 09:34:08 +09004195 int j = 0;
4196 while (j++ < CALLBACKS / 2) {
4197 NetworkCallback cb = new NetworkCallback();
4198 mCm.requestNetwork(networkRequest, cb);
4199 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004200 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004201 while (j++ < CALLBACKS) {
4202 NetworkCallback cb = new NetworkCallback();
4203 mCm.registerNetworkCallback(networkRequest, cb);
4204 registered.add(cb);
4205 }
4206 j = 0;
4207 while (j++ < INTENTS / 2) {
4208 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4209 mCm.requestNetwork(networkRequest, pi);
4210 registered.add(pi);
4211 }
4212 while (j++ < INTENTS) {
4213 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4214 mCm.registerNetworkCallback(networkRequest, pi);
4215 registered.add(pi);
4216 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004217
Hugo Benichi893a7622017-09-29 09:34:08 +09004218 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004219 assertThrows(TooManyRequestsException.class, () ->
4220 mCm.requestNetwork(networkRequest, new NetworkCallback())
4221 );
4222 assertThrows(TooManyRequestsException.class, () ->
4223 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4224 );
4225 assertThrows(TooManyRequestsException.class, () ->
4226 mCm.requestNetwork(networkRequest,
4227 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4228 );
4229 assertThrows(TooManyRequestsException.class, () ->
4230 mCm.registerNetworkCallback(networkRequest,
4231 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4232 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004233
Hugo Benichi893a7622017-09-29 09:34:08 +09004234 for (Object o : registered) {
4235 if (o instanceof NetworkCallback) {
4236 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004237 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004238 if (o instanceof PendingIntent) {
4239 mCm.unregisterNetworkCallback((PendingIntent)o);
4240 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004241 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004242 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004243
4244 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4245 for (int i = 0; i < MAX_REQUESTS; i++) {
4246 NetworkCallback networkCallback = new NetworkCallback();
4247 mCm.requestNetwork(networkRequest, networkCallback);
4248 mCm.unregisterNetworkCallback(networkCallback);
4249 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004250 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004251
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004252 for (int i = 0; i < MAX_REQUESTS; i++) {
4253 NetworkCallback networkCallback = new NetworkCallback();
4254 mCm.registerNetworkCallback(networkRequest, networkCallback);
4255 mCm.unregisterNetworkCallback(networkCallback);
4256 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004257 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004258
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004259 for (int i = 0; i < MAX_REQUESTS; i++) {
4260 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004261 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004262 mCm.requestNetwork(networkRequest, pendingIntent);
4263 mCm.unregisterNetworkCallback(pendingIntent);
4264 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004265 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004266
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004267 for (int i = 0; i < MAX_REQUESTS; i++) {
4268 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004269 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004270 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4271 mCm.unregisterNetworkCallback(pendingIntent);
4272 }
4273 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004274
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004275 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004276 public void testNetworkInfoOfTypeNone() throws Exception {
Hugo Benichi16f0a942017-06-20 14:07:59 +09004277 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4278
4279 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004280 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004281 assertNull(mCm.getActiveNetworkInfo());
4282
4283 Network[] allNetworks = mCm.getAllNetworks();
4284 assertLength(1, allNetworks);
4285 Network network = allNetworks[0];
4286 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4287 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4288
4289 final NetworkRequest request =
4290 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4291 final TestNetworkCallback callback = new TestNetworkCallback();
4292 mCm.registerNetworkCallback(request, callback);
4293
Hugo Benichic1014502017-07-19 10:10:52 +09004294 // Bring up wifi aware network.
4295 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004296 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004297
4298 assertNull(mCm.getActiveNetworkInfo());
4299 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004300 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004301 // of this test. Fix it and uncomment the assert below.
4302 //assertEmpty(mCm.getAllNetworkInfo());
4303
Hugo Benichic1014502017-07-19 10:10:52 +09004304 // Disconnect wifi aware network.
4305 wifiAware.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004306 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackRecord.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004307 mCm.unregisterNetworkCallback(callback);
4308
4309 verifyNoNetwork();
4310 if (broadcastCV.block(10)) {
4311 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4312 }
4313 }
4314
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004315 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004316 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4317 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4318 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4319 assertNull(mCm.getNetworkForType(TYPE_NONE));
4320 assertNull(mCm.getLinkProperties(TYPE_NONE));
4321 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4322
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004323 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004324 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004325
4326 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004327 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4328 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004329 // TODO: let test context have configuration application target sdk version
4330 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004331 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4332 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4333 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004334 }
4335
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004336 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004337 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004338 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4339 .addTransportType(TRANSPORT_WIFI).build();
4340 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4341 mCm.registerNetworkCallback(networkRequest, networkCallback);
4342
4343 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004344 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004345 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4346 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4347 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4348 lp.addLinkAddress(myIpv4Address);
4349 lp.addRoute(myIpv4DefaultRoute);
4350
4351 // Verify direct routes are added when network agent is first registered in
4352 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004353 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004354 networkAgent.connect(true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004355 networkCallback.expectCallback(CallbackRecord.AVAILABLE, networkAgent);
4356 networkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, networkAgent);
4357 CallbackRecord.LinkPropertiesChanged cbi =
4358 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004359 networkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004360 networkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004361 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4362 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004363 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004364 Arrays.asList(myIpv4DefaultRoute));
4365 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4366 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4367
4368 // Verify direct routes are added during subsequent link properties updates.
4369 LinkProperties newLp = new LinkProperties(lp);
4370 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4371 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4372 newLp.addLinkAddress(myIpv6Address1);
4373 newLp.addLinkAddress(myIpv6Address2);
4374 networkAgent.sendLinkProperties(newLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004375 cbi = networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004376 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004377 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004378 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4379 Arrays.asList(myIpv4DefaultRoute));
4380 mCm.unregisterNetworkCallback(networkCallback);
4381 }
4382
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004383 @Test
4384 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004385 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4386 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004387
Varun Anandd33cbc62019-02-07 14:13:13 -08004388 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4389 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4390
4391 LinkProperties cellLp = new LinkProperties();
4392 cellLp.setInterfaceName(MOBILE_IFNAME);
4393 LinkProperties wifiLp = new LinkProperties();
4394 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004395
4396 // Simple connection should have updated ifaces
4397 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004398 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004399 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004400 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004401 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4402 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004403 reset(mStatsService);
4404
4405 // Default network switch should update ifaces.
4406 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004407 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004408 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004409 assertEquals(wifiLp, mService.getActiveLinkProperties());
4410 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004411 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4412 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004413 reset(mStatsService);
4414
4415 // Disconnect should update ifaces.
4416 mWiFiNetworkAgent.disconnect();
4417 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004418 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004419 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4420 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004421 reset(mStatsService);
4422
4423 // Metered change should update ifaces
4424 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4425 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004426 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004427 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4428 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004429 reset(mStatsService);
4430
4431 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4432 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004433 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004434 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4435 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004436 reset(mStatsService);
4437
4438 // Captive portal change shouldn't update ifaces
4439 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4440 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004441 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004442 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4443 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004444 reset(mStatsService);
4445
4446 // Roaming change should update ifaces
4447 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4448 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004449 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004450 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4451 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004452 reset(mStatsService);
4453 }
4454
Erik Klinee89953b2018-01-11 16:11:10 +09004455 @Test
4456 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004457 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004458
4459 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004460 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004461
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004462 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004463 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004464 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004465 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004466
4467 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004468 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004469 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4470 // "is-reachable" testing in order to not program netd with unreachable
4471 // nameservers that it might try repeated to validate.
4472 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004473 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4474 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004475 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004476 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4477 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004478 mCellNetworkAgent.sendLinkProperties(cellLp);
4479 mCellNetworkAgent.connect(false);
4480 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004481
4482 verify(mMockDnsResolver, times(1)).createNetworkCache(
4483 eq(mCellNetworkAgent.getNetwork().netId));
4484 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004485 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004486 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004487
4488 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4489 mCellNetworkAgent.sendLinkProperties(cellLp);
4490 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004491 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004492 mResolverParamsParcelCaptor.capture());
4493 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4494 assertEquals(1, resolvrParams.servers.length);
4495 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004496 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004497 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004498 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004499
4500 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4501 mCellNetworkAgent.sendLinkProperties(cellLp);
4502 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004503 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004504 mResolverParamsParcelCaptor.capture());
4505 resolvrParams = mResolverParamsParcelCaptor.getValue();
4506 assertEquals(2, resolvrParams.servers.length);
4507 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004508 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004509 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004510 assertEquals(2, resolvrParams.tlsServers.length);
4511 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004512 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004513 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004514
4515 final String TLS_SPECIFIER = "tls.example.com";
4516 final String TLS_SERVER6 = "2001:db8:53::53";
4517 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4518 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004519 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4520 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4521
Erik Kline117e7f32018-03-04 21:01:01 +09004522 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004523 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004524 mResolverParamsParcelCaptor.capture());
4525 resolvrParams = mResolverParamsParcelCaptor.getValue();
4526 assertEquals(2, resolvrParams.servers.length);
4527 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004528 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004529 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004530 }
4531
Erik Kline79c6d052018-03-21 07:18:33 -07004532 @Test
4533 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004534 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004535 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004536
4537 // The default on Android is opportunistic mode ("Automatic").
4538 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4539
dalyk1fcb7392018-03-05 12:42:22 -05004540 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4541 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4542 .addTransportType(TRANSPORT_CELLULAR).build();
4543 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4544
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004545 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004546 waitForIdle();
4547 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004548 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004549 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004550
4551 final LinkProperties cellLp = new LinkProperties();
4552 cellLp.setInterfaceName(MOBILE_IFNAME);
4553 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4554 // "is-reachable" testing in order to not program netd with unreachable
4555 // nameservers that it might try repeated to validate.
4556 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4557 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4558 MOBILE_IFNAME));
4559 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4560 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4561 MOBILE_IFNAME));
4562 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4563 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4564
4565 mCellNetworkAgent.sendLinkProperties(cellLp);
4566 mCellNetworkAgent.connect(false);
4567 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004568 verify(mMockDnsResolver, times(1)).createNetworkCache(
4569 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004570 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004571 mResolverParamsParcelCaptor.capture());
4572 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4573 assertEquals(2, resolvrParams.tlsServers.length);
4574 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004575 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004576 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004577 assertEquals(2, resolvrParams.tlsServers.length);
4578 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004579 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004580 reset(mMockDnsResolver);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004581 cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
4582 cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004583 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004584 CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4585 CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4586 cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004587 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004588 assertFalse(cbi.getLp().isPrivateDnsActive());
4589 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004590
4591 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004592 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004593 mResolverParamsParcelCaptor.capture());
4594 resolvrParams = mResolverParamsParcelCaptor.getValue();
4595 assertEquals(2, resolvrParams.servers.length);
4596 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004597 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004598 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004599 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004600
4601 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004602 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004603 mResolverParamsParcelCaptor.capture());
4604 resolvrParams = mResolverParamsParcelCaptor.getValue();
4605 assertEquals(2, resolvrParams.servers.length);
4606 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004607 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08004608 assertEquals(2, resolvrParams.tlsServers.length);
4609 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004610 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004611 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004612 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004613
dalyk1fcb7392018-03-05 12:42:22 -05004614 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4615 // Can't test dns configuration for strict mode without properly mocking
4616 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004617 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004618 mCellNetworkAgent);
4619 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004620 assertTrue(cbi.getLp().isPrivateDnsActive());
4621 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004622 }
4623
4624 @Test
4625 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4626 // The default on Android is opportunistic mode ("Automatic").
4627 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4628
4629 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4630 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4631 .addTransportType(TRANSPORT_CELLULAR).build();
4632 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4633
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004634 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05004635 waitForIdle();
4636 LinkProperties lp = new LinkProperties();
4637 mCellNetworkAgent.sendLinkProperties(lp);
4638 mCellNetworkAgent.connect(false);
4639 waitForIdle();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004640 cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
4641 cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004642 mCellNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004643 CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4644 CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4645 cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004646 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004647 assertFalse(cbi.getLp().isPrivateDnsActive());
4648 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004649 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004650 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004651
4652 // Send a validation event for a server that is not part of the current
4653 // resolver config. The validation event should be ignored.
4654 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4655 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4656 cellNetworkCallback.assertNoCallback();
4657
4658 // Add a dns server to the LinkProperties.
4659 LinkProperties lp2 = new LinkProperties(lp);
4660 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4661 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004662 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004663 mCellNetworkAgent);
4664 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004665 assertFalse(cbi.getLp().isPrivateDnsActive());
4666 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004667 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004668 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004669
4670 // Send a validation event containing a hostname that is not part of
4671 // the current resolver config. The validation event should be ignored.
4672 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4673 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4674 cellNetworkCallback.assertNoCallback();
4675
4676 // Send a validation event where validation failed.
4677 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4678 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4679 cellNetworkCallback.assertNoCallback();
4680
4681 // Send a validation event where validation succeeded for a server in
4682 // the current resolver config. A LinkProperties callback with updated
4683 // private dns fields should be sent.
4684 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4685 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004686 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004687 mCellNetworkAgent);
4688 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004689 assertTrue(cbi.getLp().isPrivateDnsActive());
4690 assertNull(cbi.getLp().getPrivateDnsServerName());
4691 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004692
4693 // The private dns fields in LinkProperties should be preserved when
4694 // the network agent sends unrelated changes.
4695 LinkProperties lp3 = new LinkProperties(lp2);
4696 lp3.setMtu(1300);
4697 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004698 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004699 mCellNetworkAgent);
4700 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004701 assertTrue(cbi.getLp().isPrivateDnsActive());
4702 assertNull(cbi.getLp().getPrivateDnsServerName());
4703 checkDnsServers(cbi.getLp(), dnsServers);
4704 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05004705
4706 // Removing the only validated server should affect the private dns
4707 // fields in LinkProperties.
4708 LinkProperties lp4 = new LinkProperties(lp3);
4709 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4710 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean6f4216f2019-06-05 01:40:32 +09004711 cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004712 mCellNetworkAgent);
4713 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004714 assertFalse(cbi.getLp().isPrivateDnsActive());
4715 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004716 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004717 checkDnsServers(cbi.getLp(), dnsServers);
4718 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004719 }
4720
Rubin Xu1bb5c082017-09-05 18:40:49 +01004721 private void checkDirectlyConnectedRoutes(Object callbackObj,
4722 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4723 assertTrue(callbackObj instanceof LinkProperties);
4724 LinkProperties lp = (LinkProperties) callbackObj;
4725
4726 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4727 expectedRoutes.addAll(otherRoutes);
4728 for (LinkAddress address : linkAddresses) {
4729 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4730 // Duplicates in linkAddresses are considered failures
4731 assertTrue(expectedRoutes.add(localRoute));
4732 }
4733 List<RouteInfo> observedRoutes = lp.getRoutes();
4734 assertEquals(expectedRoutes.size(), observedRoutes.size());
4735 assertTrue(observedRoutes.containsAll(expectedRoutes));
4736 }
4737
dalyk1fcb7392018-03-05 12:42:22 -05004738 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4739 assertTrue(callbackObj instanceof LinkProperties);
4740 LinkProperties lp = (LinkProperties) callbackObj;
4741 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4742 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4743 }
4744
Chalard Jean0b214af2018-01-12 17:22:49 +09004745 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004746 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09004747 final int uid = Process.myUid();
4748
4749 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004750 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004751 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4752 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004753 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004754 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4755 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4756 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004757 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4758 .addTransportType(TRANSPORT_WIFI).build();
4759 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004760 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004761 .addTransportType(TRANSPORT_VPN).build();
4762 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004763 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004764 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4765 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004766 mCm.registerDefaultNetworkCallback(defaultCallback);
4767 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004768
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004769 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09004770 mWiFiNetworkAgent.connect(false);
4771
4772 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004773 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004774 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004775 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004776 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004777 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004778
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004779 final TestNetworkAgentWrapper
4780 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09004781 final ArraySet<UidRange> ranges = new ArraySet<>();
4782 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004783 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4784 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004785 // VPN networks do not satisfy the default request and are automatically validated
4786 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004787 assertFalse(NetworkMonitorUtils.isValidationRequired(
4788 vpnNetworkAgent.getNetworkCapabilities()));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004789 vpnNetworkAgent.setNetworkValid();
4790
Chalard Jean0b214af2018-01-12 17:22:49 +09004791 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004792 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004793 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004794
4795 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004796 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004797 wifiNetworkCallback.assertNoCallback();
4798 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004799 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4800 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004801
Chalard Jean6f4216f2019-06-05 01:40:32 +09004802 genericNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004803 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004804 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
4805 defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004806 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004807
4808 ranges.clear();
4809 vpnNetworkAgent.setUids(ranges);
4810
Chalard Jean6f4216f2019-06-05 01:40:32 +09004811 genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004812 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004813 wifiNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004814 vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004815
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004816 // TODO : The default network callback should actually get a LOST call here (also see the
4817 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4818 // ranges at all when determining whether a network should be rematched. In practice, VPNs
4819 // can't currently update their UIDs without disconnecting, so this does not matter too
4820 // much, but that is the reason the test here has to check for an update to the
4821 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004822 defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004823
Chalard Jean0b214af2018-01-12 17:22:49 +09004824 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004825 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08004826 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004827
4828 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004829 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004830 wifiNetworkCallback.assertNoCallback();
4831 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004832 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4833 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004834 defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004835
4836 mWiFiNetworkAgent.disconnect();
4837
Chalard Jean6f4216f2019-06-05 01:40:32 +09004838 genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
4839 genericNotVpnNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
4840 wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004841 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004842 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004843
4844 vpnNetworkAgent.disconnect();
4845
Chalard Jean6f4216f2019-06-05 01:40:32 +09004846 genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004847 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004848 wifiNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004849 vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
4850 defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004851 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004852
4853 mCm.unregisterNetworkCallback(genericNetworkCallback);
4854 mCm.unregisterNetworkCallback(wifiNetworkCallback);
4855 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004856 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004857 }
Chalard Jean26400492018-04-18 20:18:38 +09004858
4859 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004860 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09004861 final int uid = Process.myUid();
4862
4863 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4864 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09004865
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004866 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09004867 mWiFiNetworkAgent.connect(true);
4868
4869 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4870 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4871
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004872 TestNetworkAgentWrapper
4873 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09004874 final ArraySet<UidRange> ranges = new ArraySet<>();
4875 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004876 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4877 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004878 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004879 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004880
4881 defaultCallback.assertNoCallback();
4882 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4883
4884 vpnNetworkAgent.disconnect();
4885 defaultCallback.assertNoCallback();
4886
Varun Anand4fa80e82019-02-06 10:13:38 -08004887 mCm.unregisterNetworkCallback(defaultCallback);
4888 }
4889
4890 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004891 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08004892 final int uid = Process.myUid();
4893
4894 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4895 mCm.registerDefaultNetworkCallback(defaultCallback);
4896
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004897 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08004898 mWiFiNetworkAgent.connect(true);
4899
4900 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4901 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4902
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004903 TestNetworkAgentWrapper
4904 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08004905 final ArraySet<UidRange> ranges = new ArraySet<>();
4906 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004907 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4908 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004909 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004910 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004911
Chalard Jean26400492018-04-18 20:18:38 +09004912 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4913 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4914
4915 vpnNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004916 defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09004917 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4918
Chalard Jean26400492018-04-18 20:18:38 +09004919 mCm.unregisterNetworkCallback(defaultCallback);
4920 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004921
4922 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004923 public void testVpnUnvalidated() throws Exception {
4924 final TestNetworkCallback callback = new TestNetworkCallback();
4925 mCm.registerDefaultNetworkCallback(callback);
4926
4927 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004928 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004929 mEthernetNetworkAgent.connect(true);
4930 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
4931 callback.assertNoCallback();
4932
4933 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
4934 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004935 final TestNetworkAgentWrapper
4936 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004937 final ArraySet<UidRange> ranges = new ArraySet<>();
4938 ranges.add(new UidRange(uid, uid));
4939 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4940 mMockVpn.setUids(ranges);
4941 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
4942 mMockVpn.connect();
4943
4944 // Even though the VPN is unvalidated, it becomes the default network for our app.
4945 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4946 // TODO: this looks like a spurious callback.
Chalard Jean6f4216f2019-06-05 01:40:32 +09004947 callback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004948 callback.assertNoCallback();
4949
4950 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
4951 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
4952 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4953
4954 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4955 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
4956 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
4957
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004958 assertFalse(NetworkMonitorUtils.isValidationRequired(
4959 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004960 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004961 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004962
4963 // Pretend that the VPN network validates.
4964 vpnNetworkAgent.setNetworkValid();
4965 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4966 // Expect to see the validated capability, but no other changes, because the VPN is already
4967 // the default network for the app.
4968 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
4969 callback.assertNoCallback();
4970
4971 vpnNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004972 callback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09004973 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
4974 }
4975
4976 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004977 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004978 final int uid = Process.myUid();
4979
4980 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4981 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4982 .removeCapability(NET_CAPABILITY_NOT_VPN)
4983 .addTransportType(TRANSPORT_VPN)
4984 .build();
4985 NetworkCapabilities nc;
4986 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4987 vpnNetworkCallback.assertNoCallback();
4988
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004989 final TestNetworkAgentWrapper
4990 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004991 final ArraySet<UidRange> ranges = new ArraySet<>();
4992 ranges.add(new UidRange(uid, uid));
4993 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4994 mMockVpn.connect();
4995 mMockVpn.setUids(ranges);
4996 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4997
4998 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4999 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5000 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5001 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5002 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5003 // For safety reasons a VPN without underlying networks is considered metered.
5004 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5005
5006 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005007 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005008 mCellNetworkAgent.connect(true);
5009
5010 mService.setUnderlyingNetworksForVpn(
5011 new Network[] { mCellNetworkAgent.getNetwork() });
5012
Chalard Jean6f4216f2019-06-05 01:40:32 +09005013 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5014 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005015 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005016 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005017
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005018 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005019 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5020 mWiFiNetworkAgent.connect(true);
5021
5022 mService.setUnderlyingNetworksForVpn(
5023 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5024
Chalard Jean6f4216f2019-06-05 01:40:32 +09005025 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5026 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005027 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005028 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005029
5030 // Don't disconnect, but note the VPN is not using wifi any more.
5031 mService.setUnderlyingNetworksForVpn(
5032 new Network[] { mCellNetworkAgent.getNetwork() });
5033
Chalard Jean6f4216f2019-06-05 01:40:32 +09005034 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5035 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005036 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005037 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005038
5039 // Use Wifi but not cell. Note the VPN is now unmetered.
5040 mService.setUnderlyingNetworksForVpn(
5041 new Network[] { mWiFiNetworkAgent.getNetwork() });
5042
Chalard Jean6f4216f2019-06-05 01:40:32 +09005043 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5044 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005045 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005046 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005047
5048 // Use both again.
5049 mService.setUnderlyingNetworksForVpn(
5050 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5051
Chalard Jean6f4216f2019-06-05 01:40:32 +09005052 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5053 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005054 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005055 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005056
Chalard Jean6b65ec72018-05-18 22:02:56 +09005057 // Disconnect cell. Receive update without even removing the dead network from the
5058 // underlying networks – it's dead anyway. Not metered any more.
5059 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005060 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5061 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005062 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005063 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005064
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005065 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005066 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005067 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5068 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005069 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005070 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005071
5072 mMockVpn.disconnect();
5073 }
junyulai4a192e22018-06-13 15:00:37 +08005074
Mike Yuf9729752018-08-17 15:22:05 +08005075 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005076 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005077 final int uid = Process.myUid();
5078
5079 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5080 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5081 .removeCapability(NET_CAPABILITY_NOT_VPN)
5082 .addTransportType(TRANSPORT_VPN)
5083 .build();
5084 NetworkCapabilities nc;
5085 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5086 vpnNetworkCallback.assertNoCallback();
5087
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005088 final TestNetworkAgentWrapper
5089 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005090 final ArraySet<UidRange> ranges = new ArraySet<>();
5091 ranges.add(new UidRange(uid, uid));
5092 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5093 mMockVpn.connect();
5094 mMockVpn.setUids(ranges);
5095 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5096
5097 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5098 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5099 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5100 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5101 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5102 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5103 // In case of no default network, VPN is considered metered.
5104 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5105
5106 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005107 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005108 mCellNetworkAgent.connect(true);
5109
Chalard Jean6f4216f2019-06-05 01:40:32 +09005110 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5111 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005112 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005113 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005114
5115 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005116 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005117 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5118 mWiFiNetworkAgent.connect(true);
5119
Chalard Jean6f4216f2019-06-05 01:40:32 +09005120 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5121 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005122 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005123 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005124
5125 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5126 // the capabilities.
5127 mCellNetworkAgent.disconnect();
5128
5129 // Disconnect wifi too. Now we have no default network.
5130 mWiFiNetworkAgent.disconnect();
5131
Chalard Jean6f4216f2019-06-05 01:40:32 +09005132 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5133 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005134 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005135 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005136
5137 mMockVpn.disconnect();
5138 }
5139
5140 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005141 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005142 // Returns true by default when no network is available.
5143 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005144 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005145 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5146 mWiFiNetworkAgent.connect(true);
5147 waitForIdle();
5148
5149 assertFalse(mCm.isActiveNetworkMetered());
5150 }
5151
5152 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005153 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005154 // Returns true by default when no network is available.
5155 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005156 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005157 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5158 mCellNetworkAgent.connect(true);
5159 waitForIdle();
5160
5161 assertTrue(mCm.isActiveNetworkMetered());
5162 }
5163
5164 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005165 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005166 // Returns true by default when no network is available.
5167 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005168 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005169 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5170 mCellNetworkAgent.connect(true);
5171 waitForIdle();
5172 assertTrue(mCm.isActiveNetworkMetered());
5173
5174 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005175 TestNetworkAgentWrapper
5176 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005177 final ArraySet<UidRange> ranges = new ArraySet<>();
5178 final int uid = Process.myUid();
5179 ranges.add(new UidRange(uid, uid));
5180 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5181 mMockVpn.setUids(ranges);
5182 vpnNetworkAgent.connect(true);
5183 mMockVpn.connect();
5184 waitForIdle();
5185 // Ensure VPN is now the active network.
5186 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5187
5188 // Expect VPN to be metered.
5189 assertTrue(mCm.isActiveNetworkMetered());
5190
5191 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005192 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005193 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5194 mWiFiNetworkAgent.connect(true);
5195 waitForIdle();
5196 // VPN should still be the active network.
5197 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5198
5199 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5200 assertFalse(mCm.isActiveNetworkMetered());
5201
5202 // Disconnecting Cell should not affect VPN's meteredness.
5203 mCellNetworkAgent.disconnect();
5204 waitForIdle();
5205
5206 assertFalse(mCm.isActiveNetworkMetered());
5207
5208 // Disconnect WiFi; Now there is no platform default network.
5209 mWiFiNetworkAgent.disconnect();
5210 waitForIdle();
5211
5212 // VPN without any underlying networks is treated as metered.
5213 assertTrue(mCm.isActiveNetworkMetered());
5214
5215 vpnNetworkAgent.disconnect();
5216 mMockVpn.disconnect();
5217 }
5218
5219 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005220 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005221 // Returns true by default when no network is available.
5222 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005223 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005224 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5225 mCellNetworkAgent.connect(true);
5226 waitForIdle();
5227 assertTrue(mCm.isActiveNetworkMetered());
5228
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005229 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005230 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5231 mWiFiNetworkAgent.connect(true);
5232 waitForIdle();
5233 assertFalse(mCm.isActiveNetworkMetered());
5234
5235 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005236 TestNetworkAgentWrapper
5237 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005238 final ArraySet<UidRange> ranges = new ArraySet<>();
5239 final int uid = Process.myUid();
5240 ranges.add(new UidRange(uid, uid));
5241 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5242 mMockVpn.setUids(ranges);
5243 vpnNetworkAgent.connect(true);
5244 mMockVpn.connect();
5245 waitForIdle();
5246 // Ensure VPN is now the active network.
5247 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5248 // VPN is using Cell
5249 mService.setUnderlyingNetworksForVpn(
5250 new Network[] { mCellNetworkAgent.getNetwork() });
5251 waitForIdle();
5252
5253 // Expect VPN to be metered.
5254 assertTrue(mCm.isActiveNetworkMetered());
5255
5256 // VPN is now using WiFi
5257 mService.setUnderlyingNetworksForVpn(
5258 new Network[] { mWiFiNetworkAgent.getNetwork() });
5259 waitForIdle();
5260
5261 // Expect VPN to be unmetered
5262 assertFalse(mCm.isActiveNetworkMetered());
5263
5264 // VPN is using Cell | WiFi.
5265 mService.setUnderlyingNetworksForVpn(
5266 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5267 waitForIdle();
5268
5269 // Expect VPN to be metered.
5270 assertTrue(mCm.isActiveNetworkMetered());
5271
5272 // VPN is using WiFi | Cell.
5273 mService.setUnderlyingNetworksForVpn(
5274 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5275 waitForIdle();
5276
5277 // Order should not matter and VPN should still be metered.
5278 assertTrue(mCm.isActiveNetworkMetered());
5279
5280 // VPN is not using any underlying networks.
5281 mService.setUnderlyingNetworksForVpn(new Network[0]);
5282 waitForIdle();
5283
5284 // VPN without underlying networks is treated as metered.
5285 assertTrue(mCm.isActiveNetworkMetered());
5286
5287 vpnNetworkAgent.disconnect();
5288 mMockVpn.disconnect();
5289 }
5290
5291 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005292 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005293 // Returns true by default when no network is available.
5294 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005295 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005296 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5297 mWiFiNetworkAgent.connect(true);
5298 waitForIdle();
5299 assertFalse(mCm.isActiveNetworkMetered());
5300
5301 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005302 TestNetworkAgentWrapper
5303 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005304 final ArraySet<UidRange> ranges = new ArraySet<>();
5305 final int uid = Process.myUid();
5306 ranges.add(new UidRange(uid, uid));
5307 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5308 mMockVpn.setUids(ranges);
5309 vpnNetworkAgent.connect(true);
5310 mMockVpn.connectAsAlwaysMetered();
5311 waitForIdle();
5312 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5313
5314 // VPN is tracking current platform default (WiFi).
5315 mService.setUnderlyingNetworksForVpn(null);
5316 waitForIdle();
5317
5318 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5319 assertTrue(mCm.isActiveNetworkMetered());
5320
5321 // VPN explicitly declares WiFi as its underlying network.
5322 mService.setUnderlyingNetworksForVpn(
5323 new Network[] { mWiFiNetworkAgent.getNetwork() });
5324 waitForIdle();
5325
5326 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5327 assertTrue(mCm.isActiveNetworkMetered());
5328
5329 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5330 // anyways suppose to be metered.
5331 mWiFiNetworkAgent.disconnect();
5332 waitForIdle();
5333
5334 assertTrue(mCm.isActiveNetworkMetered());
5335
5336 vpnNetworkAgent.disconnect();
5337 }
5338
5339 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005340 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005341 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5342 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5343 .addTransportType(TRANSPORT_CELLULAR)
5344 .build();
5345 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5346
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005347 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005348 mCellNetworkAgent.connect(true);
5349 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5350
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005351 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005352 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5353
5354 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005355 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005356 cellNetworkCallback.assertNoCallback();
5357
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005358 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005359 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5360
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005361 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005362 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5363
5364 // Restrict the network based on UID rule and NOT_METERED capability change.
5365 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5366 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5367 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5368 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5369 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5370 mCellNetworkAgent);
5371 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005372 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005373 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5374
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005375 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005376 cellNetworkCallback.assertNoCallback();
5377
5378 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005379 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005380 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005381 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005382 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005383 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005384 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5385 cellNetworkCallback.assertNoCallback();
5386
5387 mCm.unregisterNetworkCallback(cellNetworkCallback);
5388 }
5389
5390 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005391 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005392 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5393 mCm.registerDefaultNetworkCallback(defaultCallback);
5394
5395 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005396 setUidRulesChanged(RULE_REJECT_ALL);
5397 setUidRulesChanged(RULE_NONE);
5398 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005399 defaultCallback.assertNoCallback();
5400
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005401 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005402 mCellNetworkAgent.connect(true);
5403 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5404 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5405
5406 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005407 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005408 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5409 mWiFiNetworkAgent.connect(true);
5410 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5411
5412 // Switch to METERED network. Restrict the use of the network.
5413 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005414 defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005415 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5416
5417 // Network becomes NOT_METERED.
5418 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5419 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5420 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5421
5422 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005423 setRestrictBackgroundChanged(true);
5424 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005425 defaultCallback.assertNoCallback();
5426
5427 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005428 defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005429 defaultCallback.assertNoCallback();
5430
5431 mCm.unregisterNetworkCallback(defaultCallback);
5432 }
5433
junyulai4a192e22018-06-13 15:00:37 +08005434 /**
5435 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5436 */
5437 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5438 InterfaceConfiguration cfg = new InterfaceConfiguration();
5439 cfg.setHardwareAddress("11:22:33:44:55:66");
5440 cfg.setLinkAddress(la);
5441 return cfg;
5442 }
5443
5444 /**
5445 * Make expected stack link properties, copied from Nat464Xlat.
5446 */
5447 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5448 LinkAddress clatAddress = la;
5449 LinkProperties stacked = new LinkProperties();
5450 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5451 RouteInfo ipv4Default = new RouteInfo(
5452 new LinkAddress(Inet4Address.ANY, 0),
5453 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5454 stacked.addRoute(ipv4Default);
5455 stacked.addLinkAddress(clatAddress);
5456 return stacked;
5457 }
5458
5459 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005460 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005461 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5462 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005463 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5464 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5465
junyulai4a192e22018-06-13 15:00:37 +08005466 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5467 .addTransportType(TRANSPORT_CELLULAR)
5468 .addCapability(NET_CAPABILITY_INTERNET)
5469 .build();
5470 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5471 mCm.registerNetworkCallback(networkRequest, networkCallback);
5472
Lorenzo Colittid593e292019-02-19 13:21:56 +09005473 // Prepare ipv6 only link properties.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005474 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005475 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005476 final LinkProperties cellLp = new LinkProperties();
5477 cellLp.setInterfaceName(MOBILE_IFNAME);
5478 cellLp.addLinkAddress(myIpv6);
5479 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5480 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5481 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005482 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005483 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08005484 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5485 .thenReturn(getClatInterfaceConfig(myIpv4));
5486
Lorenzo Colittid593e292019-02-19 13:21:56 +09005487 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005488 mCellNetworkAgent.sendLinkProperties(cellLp);
5489 mCellNetworkAgent.connect(true);
Luke Huanga24d5d82019-04-09 18:41:49 +08005490
5491 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5492 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
5493
junyulai4a192e22018-06-13 15:00:37 +08005494 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005495 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005496
Lorenzo Colittid593e292019-02-19 13:21:56 +09005497 // Switching default network updates TCP buffer sizes.
5498 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5499
5500 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5501 // the NAT64 prefix was removed because one was never discovered.
5502 cellLp.addLinkAddress(myIpv4);
5503 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005504 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005505 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005506 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005507
5508 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005509 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005510 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005511 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005512
5513 // Remove IPv4 address. Expect prefix discovery to be started again.
5514 cellLp.removeLinkAddress(myIpv4);
5515 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5516 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005517 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005518 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005519
5520 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005521 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005522 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005523 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5524 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005525 LinkProperties lpBeforeClat = networkCallback.expectCallback(
5526 CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005527 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5528 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5529 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5530
5531 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005532 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005533 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005534 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5535 .getStackedLinks();
5536 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5537
5538 // Change trivial linkproperties and see if stacked link is preserved.
5539 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5540 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005541 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005542
5543 List<LinkProperties> stackedLpsAfterChange =
5544 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5545 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5546 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5547
Luke Huang65914772019-03-16 00:31:46 +08005548 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005549 mResolverParamsParcelCaptor.capture());
5550 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5551 assertEquals(1, resolvrParams.servers.length);
5552 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08005553
Lorenzo Colittid593e292019-02-19 13:21:56 +09005554 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5555 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005556 cellLp.addLinkAddress(myIpv4);
5557 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5558 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005559 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005560 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08005561 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005562
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005563 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean6f4216f2019-06-05 01:40:32 +09005564 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005565 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5566 LinkProperties expected = new LinkProperties(cellLp);
5567 expected.setNat64Prefix(kNat64Prefix);
5568 assertEquals(expected, actualLpAfterIpv4);
5569 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5570
5571 // The interface removed callback happens but has no effect after stop is called.
5572 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5573 networkCallback.assertNoCallback();
5574
Lorenzo Colittid593e292019-02-19 13:21:56 +09005575 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005576 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005577 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005578 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005579
Lorenzo Colittid593e292019-02-19 13:21:56 +09005580 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5581 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5582 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005583 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5584 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005585
5586 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005587 cellLp.removeLinkAddress(myIpv4);
5588 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5589 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5590 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005591 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005592 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005593 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5594 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005595 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005596 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5597
Lorenzo Colittid593e292019-02-19 13:21:56 +09005598
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005599 // Clat iface comes up. Expect stacked link to be added.
5600 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005601 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5602 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005603
5604 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005605 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5606 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005607 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5608 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005609 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005610 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5611 (lp) -> lp.getStackedLinks().size() == 0);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005612
5613 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005614 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005615 networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005616 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005617 mCm.unregisterNetworkCallback(networkCallback);
5618 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005619
5620 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005621 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08005622 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5623 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5624 .addCapability(NET_CAPABILITY_INTERNET)
5625 .build();
5626 mCm.registerNetworkCallback(networkRequest, networkCallback);
5627
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005628 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08005629 final LinkProperties cellLp = new LinkProperties();
5630 cellLp.setInterfaceName(MOBILE_IFNAME);
5631 mCellNetworkAgent.sendLinkProperties(cellLp);
5632 reset(mNetworkManagementService);
5633 mCellNetworkAgent.connect(true);
5634 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5635 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5636 eq(ConnectivityManager.TYPE_MOBILE));
5637
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005638 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005639 final LinkProperties wifiLp = new LinkProperties();
5640 wifiLp.setInterfaceName(WIFI_IFNAME);
5641 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5642
5643 // Network switch
5644 reset(mNetworkManagementService);
5645 mWiFiNetworkAgent.connect(true);
5646 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005647 networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005648 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5649 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5650 eq(ConnectivityManager.TYPE_WIFI));
5651 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5652
5653 // Disconnect wifi and switch back to cell
5654 reset(mNetworkManagementService);
5655 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005656 networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005657 assertNoCallbacks(networkCallback);
5658 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5659 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5660 eq(ConnectivityManager.TYPE_MOBILE));
5661
5662 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005663 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005664 wifiLp.setInterfaceName(WIFI_IFNAME);
5665 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5666 mWiFiNetworkAgent.connect(true);
5667 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005668 networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005669 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5670
5671 // Disconnect cell
5672 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005673 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08005674 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005675 networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005676 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5677 // sent as network being switched. Ensure rule removal for cell will not be triggered
5678 // unexpectedly before network being removed.
5679 waitForIdle();
5680 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08005681 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
5682 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08005683 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08005684
5685 // Disconnect wifi
5686 ConditionVariable cv = waitForConnectivityBroadcasts(1);
5687 reset(mNetworkManagementService);
5688 mWiFiNetworkAgent.disconnect();
5689 waitFor(cv);
5690 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5691
5692 // Clean up
5693 mCm.unregisterNetworkCallback(networkCallback);
5694 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005695
Chalard Jeane7b24752019-06-20 16:01:19 +09005696 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005697 String[] values = tcpBufferSizes.split(",");
5698 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5699 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09005700 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005701 reset(mMockNetd);
5702 }
5703
5704 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07005705 @FlakyTest(bugId = 140305678)
Chalard Jeane7b24752019-06-20 16:01:19 +09005706 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005707 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08005708 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5709 .addTransportType(TRANSPORT_CELLULAR)
5710 .addCapability(NET_CAPABILITY_INTERNET)
5711 .build();
5712 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5713 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005714
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005715 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005716 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005717 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005718 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08005719 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005720 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5721
5722 // Change link Properties should have updated tcp buffer size.
5723 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005724 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005725 mCellNetworkAgent.sendLinkProperties(lp);
paulhu66269b32019-08-30 19:24:36 +08005726 networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005727 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08005728
5729 // Clean up.
5730 mCellNetworkAgent.disconnect();
5731 networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
5732 networkCallback.assertNoCallback();
5733 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005734 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005735
5736 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005737 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005738 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005739 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005740 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5741 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5742 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5743 }
5744
5745 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005746 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005747 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005748 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005749 mWiFiNetworkAgent.connect(true);
5750 waitForIdle();
5751 assertNull(mService.getProxyForNetwork(null));
5752
5753 final LinkProperties testLinkProperties = new LinkProperties();
5754 testLinkProperties.setHttpProxy(testProxyInfo);
5755
5756 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5757 waitForIdle();
5758
5759 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5760 }
5761
5762 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005763 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005764 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5765
5766 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005767 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005768 mWiFiNetworkAgent.connect(true);
5769 waitForIdle();
5770 assertNull(mService.getProxyForNetwork(null));
5771
5772 // Set up a VPN network with a proxy
5773 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005774 final TestNetworkAgentWrapper
5775 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005776 final ArraySet<UidRange> ranges = new ArraySet<>();
5777 ranges.add(new UidRange(uid, uid));
5778 mMockVpn.setUids(ranges);
5779 LinkProperties testLinkProperties = new LinkProperties();
5780 testLinkProperties.setHttpProxy(testProxyInfo);
5781 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5782 waitForIdle();
5783
5784 // Connect to VPN with proxy
5785 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5786 vpnNetworkAgent.connect(true);
5787 mMockVpn.connect();
5788 waitForIdle();
5789
5790 // Test that the VPN network returns a proxy, and the WiFi does not.
5791 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5792 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5793 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5794
5795 // Test that the VPN network returns no proxy when it is set to null.
5796 testLinkProperties.setHttpProxy(null);
5797 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5798 waitForIdle();
5799 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5800 assertNull(mService.getProxyForNetwork(null));
5801
5802 // Set WiFi proxy and check that the vpn proxy is still null.
5803 testLinkProperties.setHttpProxy(testProxyInfo);
5804 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5805 waitForIdle();
5806 assertNull(mService.getProxyForNetwork(null));
5807
5808 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
5809 // correct proxy setting.
5810 vpnNetworkAgent.disconnect();
5811 waitForIdle();
5812 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5813 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5814 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5815 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005816
5817 @Test
5818 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
5819 LinkProperties lp = new LinkProperties();
5820 lp.setInterfaceName("tun0");
5821 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
5822 // The uid range needs to cover the test app so the network is visible to it.
5823 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005824 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005825
5826 // Connected VPN should have interface rules set up. There are two expected invocations,
5827 // one during VPN uid update, one during VPN LinkProperties update
5828 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
5829 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
5830 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
5831 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
5832 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
5833
5834 vpnNetworkAgent.disconnect();
5835 waitForIdle();
5836
5837 // Disconnected VPN should have interface rules removed
5838 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5839 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5840 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
5841 }
5842
5843 @Test
5844 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
5845 LinkProperties lp = new LinkProperties();
5846 lp.setInterfaceName("tun0");
5847 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
5848 // The uid range needs to cover the test app so the network is visible to it.
5849 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005850 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
5851 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005852
5853 // Legacy VPN should not have interface rules set up
5854 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
5855 }
5856
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09005857 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005858 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
5859 throws Exception {
5860 LinkProperties lp = new LinkProperties();
5861 lp.setInterfaceName("tun0");
5862 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
5863 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
5864 // The uid range needs to cover the test app so the network is visible to it.
5865 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005866 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
5867 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005868
5869 // IPv6 unreachable route should not be misinterpreted as a default route
5870 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
5871 }
5872
5873 @Test
5874 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
5875 LinkProperties lp = new LinkProperties();
5876 lp.setInterfaceName("tun0");
5877 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
5878 // The uid range needs to cover the test app so the network is visible to it.
5879 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005880 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005881
5882 // Connected VPN should have interface rules set up. There are two expected invocations,
5883 // one during VPN uid update, one during VPN LinkProperties update
5884 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
5885 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
5886 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
5887 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
5888
5889 reset(mMockNetd);
5890 InOrder inOrder = inOrder(mMockNetd);
5891 lp.setInterfaceName("tun1");
5892 vpnNetworkAgent.sendLinkProperties(lp);
5893 waitForIdle();
5894 // VPN handover (switch to a new interface) should result in rules being updated (old rules
5895 // removed first, then new rules added)
5896 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5897 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5898 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
5899 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5900
5901 reset(mMockNetd);
5902 lp = new LinkProperties();
5903 lp.setInterfaceName("tun1");
5904 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
5905 vpnNetworkAgent.sendLinkProperties(lp);
5906 waitForIdle();
5907 // VPN not routing everything should no longer have interface filtering rules
5908 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5909 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5910
5911 reset(mMockNetd);
5912 lp = new LinkProperties();
5913 lp.setInterfaceName("tun1");
5914 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
5915 vpnNetworkAgent.sendLinkProperties(lp);
5916 waitForIdle();
5917 // Back to routing all IPv6 traffic should have filtering rules
5918 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
5919 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5920 }
5921
5922 @Test
5923 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
5924 LinkProperties lp = new LinkProperties();
5925 lp.setInterfaceName("tun0");
5926 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
5927 // The uid range needs to cover the test app so the network is visible to it.
5928 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005929 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005930 Collections.singleton(vpnRange));
5931
5932 reset(mMockNetd);
5933 InOrder inOrder = inOrder(mMockNetd);
5934
5935 // Update to new range which is old range minus APP1, i.e. only APP2
5936 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
5937 new UidRange(vpnRange.start, APP1_UID - 1),
5938 new UidRange(APP1_UID + 1, vpnRange.stop)));
5939 vpnNetworkAgent.setUids(newRanges);
5940 waitForIdle();
5941
5942 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
5943 // Verify old rules are removed before new rules are added
5944 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
5945 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
5946 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
5947 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
5948 }
5949
5950
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005951 private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
Chalard Jeane7b24752019-06-20 16:01:19 +09005952 Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005953 final TestNetworkAgentWrapper
5954 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005955 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
5956 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5957 mMockVpn.connect();
5958 mMockVpn.setUids(vpnRange);
5959 vpnNetworkAgent.connect(true);
5960 waitForIdle();
5961 return vpnNetworkAgent;
5962 }
5963
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00005964 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
5965 final PackageInfo packageInfo = new PackageInfo();
5966 packageInfo.requestedPermissions = new String[0];
5967 packageInfo.applicationInfo = new ApplicationInfo();
5968 packageInfo.applicationInfo.privateFlags = 0;
5969 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
5970 UserHandle.getAppId(uid));
5971 return packageInfo;
5972 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07005973}