Home | History | Annotate | Download | only in server
      1 /*
      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 
     17 package com.android.server;
     18 
     19 import static android.content.pm.PackageManager.GET_PERMISSIONS;
     20 import static android.content.pm.PackageManager.MATCH_ANY_USER;
     21 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
     22 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
     23 import static android.net.ConnectivityManager.NETID_UNSET;
     24 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
     25 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
     26 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
     27 import static android.net.ConnectivityManager.TYPE_ETHERNET;
     28 import static android.net.ConnectivityManager.TYPE_MOBILE;
     29 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
     30 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
     31 import static android.net.ConnectivityManager.TYPE_NONE;
     32 import static android.net.ConnectivityManager.TYPE_VPN;
     33 import static android.net.ConnectivityManager.TYPE_WIFI;
     34 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
     35 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
     36 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
     37 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
     38 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
     39 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
     40 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
     41 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
     42 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
     43 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
     44 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
     45 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
     46 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
     47 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
     48 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
     49 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
     50 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
     51 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
     52 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
     53 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
     54 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
     55 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
     56 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
     57 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
     58 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
     59 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
     60 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
     61 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
     62 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
     63 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
     64 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
     65 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
     66 import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
     67 import static android.net.NetworkPolicyManager.RULE_NONE;
     68 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
     69 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
     70 import static android.net.RouteInfo.RTN_UNREACHABLE;
     71 
     72 import static com.android.internal.util.TestUtils.waitForIdleHandler;
     73 import static com.android.internal.util.TestUtils.waitForIdleLooper;
     74 import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
     75 
     76 import static org.junit.Assert.assertArrayEquals;
     77 import static org.junit.Assert.assertEquals;
     78 import static org.junit.Assert.assertFalse;
     79 import static org.junit.Assert.assertNotEquals;
     80 import static org.junit.Assert.assertNotNull;
     81 import static org.junit.Assert.assertNull;
     82 import static org.junit.Assert.assertTrue;
     83 import static org.junit.Assert.fail;
     84 import static org.mockito.ArgumentMatchers.anyString;
     85 import static org.mockito.ArgumentMatchers.eq;
     86 import static org.mockito.Matchers.anyInt;
     87 import static org.mockito.Mockito.any;
     88 import static org.mockito.Mockito.atLeastOnce;
     89 import static org.mockito.Mockito.doAnswer;
     90 import static org.mockito.Mockito.doNothing;
     91 import static org.mockito.Mockito.inOrder;
     92 import static org.mockito.Mockito.mock;
     93 import static org.mockito.Mockito.never;
     94 import static org.mockito.Mockito.reset;
     95 import static org.mockito.Mockito.spy;
     96 import static org.mockito.Mockito.timeout;
     97 import static org.mockito.Mockito.times;
     98 import static org.mockito.Mockito.verify;
     99 import static org.mockito.Mockito.verifyNoMoreInteractions;
    100 import static org.mockito.Mockito.when;
    101 
    102 import android.annotation.NonNull;
    103 import android.app.NotificationManager;
    104 import android.app.PendingIntent;
    105 import android.content.BroadcastReceiver;
    106 import android.content.ContentProvider;
    107 import android.content.ContentResolver;
    108 import android.content.Context;
    109 import android.content.Intent;
    110 import android.content.IntentFilter;
    111 import android.content.pm.ApplicationInfo;
    112 import android.content.pm.PackageInfo;
    113 import android.content.pm.PackageManager;
    114 import android.content.pm.UserInfo;
    115 import android.content.res.Resources;
    116 import android.net.ConnectivityManager;
    117 import android.net.ConnectivityManager.NetworkCallback;
    118 import android.net.ConnectivityManager.PacketKeepalive;
    119 import android.net.ConnectivityManager.PacketKeepaliveCallback;
    120 import android.net.ConnectivityManager.TooManyRequestsException;
    121 import android.net.ConnectivityThread;
    122 import android.net.IDnsResolver;
    123 import android.net.INetd;
    124 import android.net.INetworkMonitor;
    125 import android.net.INetworkMonitorCallbacks;
    126 import android.net.INetworkPolicyListener;
    127 import android.net.INetworkPolicyManager;
    128 import android.net.INetworkStatsService;
    129 import android.net.InterfaceConfiguration;
    130 import android.net.IpPrefix;
    131 import android.net.IpSecManager;
    132 import android.net.IpSecManager.UdpEncapsulationSocket;
    133 import android.net.LinkAddress;
    134 import android.net.LinkProperties;
    135 import android.net.MatchAllNetworkSpecifier;
    136 import android.net.Network;
    137 import android.net.NetworkAgent;
    138 import android.net.NetworkCapabilities;
    139 import android.net.NetworkFactory;
    140 import android.net.NetworkInfo;
    141 import android.net.NetworkInfo.DetailedState;
    142 import android.net.NetworkMisc;
    143 import android.net.NetworkRequest;
    144 import android.net.NetworkSpecifier;
    145 import android.net.NetworkStack;
    146 import android.net.NetworkStackClient;
    147 import android.net.NetworkState;
    148 import android.net.NetworkUtils;
    149 import android.net.ProxyInfo;
    150 import android.net.ResolverParamsParcel;
    151 import android.net.RouteInfo;
    152 import android.net.SocketKeepalive;
    153 import android.net.UidRange;
    154 import android.net.metrics.IpConnectivityLog;
    155 import android.net.shared.NetworkMonitorUtils;
    156 import android.net.shared.PrivateDnsConfig;
    157 import android.net.util.MultinetworkPolicyTracker;
    158 import android.os.Binder;
    159 import android.os.Bundle;
    160 import android.os.ConditionVariable;
    161 import android.os.Handler;
    162 import android.os.HandlerThread;
    163 import android.os.INetworkManagementService;
    164 import android.os.Looper;
    165 import android.os.Message;
    166 import android.os.Parcel;
    167 import android.os.ParcelFileDescriptor;
    168 import android.os.Parcelable;
    169 import android.os.Process;
    170 import android.os.RemoteException;
    171 import android.os.SystemClock;
    172 import android.os.UserHandle;
    173 import android.os.UserManager;
    174 import android.provider.Settings;
    175 import android.system.Os;
    176 import android.test.mock.MockContentResolver;
    177 import android.text.TextUtils;
    178 import android.util.ArraySet;
    179 import android.util.Log;
    180 import android.util.SparseArray;
    181 
    182 import androidx.test.InstrumentationRegistry;
    183 import androidx.test.filters.SmallTest;
    184 import androidx.test.runner.AndroidJUnit4;
    185 
    186 import com.android.internal.net.VpnConfig;
    187 import com.android.internal.net.VpnInfo;
    188 import com.android.internal.util.ArrayUtils;
    189 import com.android.internal.util.WakeupMessage;
    190 import com.android.internal.util.test.BroadcastInterceptingContext;
    191 import com.android.internal.util.test.FakeSettingsProvider;
    192 import com.android.server.connectivity.ConnectivityConstants;
    193 import com.android.server.connectivity.DefaultNetworkMetrics;
    194 import com.android.server.connectivity.IpConnectivityMetrics;
    195 import com.android.server.connectivity.MockableSystemProperties;
    196 import com.android.server.connectivity.Nat464Xlat;
    197 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
    198 import com.android.server.connectivity.ProxyTracker;
    199 import com.android.server.connectivity.Tethering;
    200 import com.android.server.connectivity.Vpn;
    201 import com.android.server.net.NetworkPinner;
    202 import com.android.server.net.NetworkPolicyManagerInternal;
    203 
    204 import org.junit.After;
    205 import org.junit.Before;
    206 import org.junit.Ignore;
    207 import org.junit.Test;
    208 import org.junit.runner.RunWith;
    209 import org.mockito.ArgumentCaptor;
    210 import org.mockito.InOrder;
    211 import org.mockito.Mock;
    212 import org.mockito.MockitoAnnotations;
    213 import org.mockito.Spy;
    214 import org.mockito.stubbing.Answer;
    215 
    216 import java.io.IOException;
    217 import java.net.DatagramSocket;
    218 import java.net.Inet4Address;
    219 import java.net.Inet6Address;
    220 import java.net.InetAddress;
    221 import java.net.InetSocketAddress;
    222 import java.net.Socket;
    223 import java.net.UnknownHostException;
    224 import java.util.ArrayList;
    225 import java.util.Arrays;
    226 import java.util.Collection;
    227 import java.util.Collections;
    228 import java.util.HashSet;
    229 import java.util.List;
    230 import java.util.Objects;
    231 import java.util.Set;
    232 import java.util.concurrent.CountDownLatch;
    233 import java.util.concurrent.Executor;
    234 import java.util.concurrent.ExecutorService;
    235 import java.util.concurrent.Executors;
    236 import java.util.concurrent.LinkedBlockingQueue;
    237 import java.util.concurrent.TimeUnit;
    238 import java.util.concurrent.atomic.AtomicBoolean;
    239 import java.util.function.Predicate;
    240 
    241 /**
    242  * Tests for {@link ConnectivityService}.
    243  *
    244  * Build, install and run with:
    245  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
    246  */
    247 @RunWith(AndroidJUnit4.class)
    248 @SmallTest
    249 public class ConnectivityServiceTest {
    250     private static final String TAG = "ConnectivityServiceTest";
    251 
    252     private static final int TIMEOUT_MS = 500;
    253     private static final int TEST_LINGER_DELAY_MS = 250;
    254     // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
    255     // LOST callback that arrives immediately and a LOST callback that arrives after the linger
    256     // timeout. For this, our assertions should run fast enough to leave less than
    257     // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
    258     // supposedly fired, and the time we call expectCallback.
    259     private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
    260     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
    261     // complete before callbacks are verified.
    262     private final static int TEST_REQUEST_TIMEOUT_MS = 150;
    263 
    264     private static final String CLAT_PREFIX = "v4-";
    265     private static final String MOBILE_IFNAME = "test_rmnet_data0";
    266     private static final String WIFI_IFNAME = "test_wlan0";
    267     private static final String[] EMPTY_STRING_ARRAY = new String[0];
    268 
    269     private MockContext mServiceContext;
    270     private WrappedConnectivityService mService;
    271     private WrappedConnectivityManager mCm;
    272     private MockNetworkAgent mWiFiNetworkAgent;
    273     private MockNetworkAgent mCellNetworkAgent;
    274     private MockNetworkAgent mEthernetNetworkAgent;
    275     private MockVpn mMockVpn;
    276     private Context mContext;
    277     private INetworkPolicyListener mPolicyListener;
    278 
    279     @Mock IpConnectivityMetrics.Logger mMetricsService;
    280     @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
    281     @Mock INetworkManagementService mNetworkManagementService;
    282     @Mock INetworkStatsService mStatsService;
    283     @Mock INetworkPolicyManager mNpm;
    284     @Mock IDnsResolver mMockDnsResolver;
    285     @Mock INetd mMockNetd;
    286     @Mock NetworkStackClient mNetworkStack;
    287     @Mock PackageManager mPackageManager;
    288     @Mock UserManager mUserManager;
    289     @Mock NotificationManager mNotificationManager;
    290 
    291     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
    292             ArgumentCaptor.forClass(ResolverParamsParcel.class);
    293 
    294     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
    295     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
    296     // reflect the state of our test ConnectivityService.
    297     private class WrappedConnectivityManager extends ConnectivityManager {
    298         private Network mFakeBoundNetwork;
    299 
    300         public synchronized boolean bindProcessToNetwork(Network network) {
    301             mFakeBoundNetwork = network;
    302             return true;
    303         }
    304 
    305         public synchronized Network getBoundNetworkForProcess() {
    306             return mFakeBoundNetwork;
    307         }
    308 
    309         public WrappedConnectivityManager(Context context, ConnectivityService service) {
    310             super(context, service);
    311         }
    312     }
    313 
    314     private class MockContext extends BroadcastInterceptingContext {
    315         private final MockContentResolver mContentResolver;
    316 
    317         @Spy private Resources mResources;
    318         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
    319 
    320         MockContext(Context base, ContentProvider settingsProvider) {
    321             super(base);
    322 
    323             mResources = spy(base.getResources());
    324             when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
    325                     thenReturn(new String[] {
    326                             "wifi,1,1,1,-1,true",
    327                             "mobile,0,0,0,-1,true",
    328                             "mobile_mms,2,0,2,60000,true",
    329                     });
    330 
    331             mContentResolver = new MockContentResolver();
    332             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
    333         }
    334 
    335         @Override
    336         public void startActivityAsUser(Intent intent, UserHandle handle) {
    337             mStartedActivities.offer(intent);
    338         }
    339 
    340         public Intent expectStartActivityIntent(int timeoutMs) {
    341             Intent intent = null;
    342             try {
    343                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
    344             } catch (InterruptedException e) {}
    345             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
    346             return intent;
    347         }
    348 
    349         public void expectNoStartActivityIntent(int timeoutMs) {
    350             try {
    351                 assertNull("Received unexpected Intent to start activity",
    352                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
    353             } catch (InterruptedException e) {}
    354         }
    355 
    356         @Override
    357         public Object getSystemService(String name) {
    358             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
    359             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
    360             if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
    361             if (Context.USER_SERVICE.equals(name)) return mUserManager;
    362             return super.getSystemService(name);
    363         }
    364 
    365         @Override
    366         public ContentResolver getContentResolver() {
    367             return mContentResolver;
    368         }
    369 
    370         @Override
    371         public Resources getResources() {
    372             return mResources;
    373         }
    374 
    375         @Override
    376         public PackageManager getPackageManager() {
    377             return mPackageManager;
    378         }
    379 
    380         @Override
    381         public void enforceCallingOrSelfPermission(String permission, String message) {
    382             // The mainline permission can only be held if signed with the network stack certificate
    383             // Skip testing for this permission.
    384             if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
    385             // All other permissions should be held by the test or unnecessary: check as normal to
    386             // make sure the code does not rely on unexpected permissions.
    387             super.enforceCallingOrSelfPermission(permission, message);
    388         }
    389     }
    390 
    391     public void waitForIdle(int timeoutMsAsInt) {
    392         long timeoutMs = timeoutMsAsInt;
    393         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
    394         waitForIdle(mCellNetworkAgent, timeoutMs);
    395         waitForIdle(mWiFiNetworkAgent, timeoutMs);
    396         waitForIdle(mEthernetNetworkAgent, timeoutMs);
    397         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
    398         waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
    399     }
    400 
    401     public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
    402         if (agent == null) {
    403             return;
    404         }
    405         waitForIdleHandler(agent.mHandlerThread, timeoutMs);
    406     }
    407 
    408     private void waitForIdle() {
    409         waitForIdle(TIMEOUT_MS);
    410     }
    411 
    412     @Test
    413     public void testWaitForIdle() {
    414         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
    415 
    416         // Tests that waitForIdle returns immediately if the service is already idle.
    417         for (int i = 0; i < attempts; i++) {
    418             waitForIdle();
    419         }
    420 
    421         // Bring up a network that we can use to send messages to ConnectivityService.
    422         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    423         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    424         mWiFiNetworkAgent.connect(false);
    425         waitFor(cv);
    426         Network n = mWiFiNetworkAgent.getNetwork();
    427         assertNotNull(n);
    428 
    429         // Tests that calling waitForIdle waits for messages to be processed.
    430         for (int i = 0; i < attempts; i++) {
    431             mWiFiNetworkAgent.setSignalStrength(i);
    432             waitForIdle();
    433             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
    434         }
    435     }
    436 
    437     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
    438     // or presubmit tests. It is kept for manual runs and documentation purposes.
    439     @Ignore
    440     public void verifyThatNotWaitingForIdleCausesRaceConditions() {
    441         // Bring up a network that we can use to send messages to ConnectivityService.
    442         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    443         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    444         mWiFiNetworkAgent.connect(false);
    445         waitFor(cv);
    446         Network n = mWiFiNetworkAgent.getNetwork();
    447         assertNotNull(n);
    448 
    449         // Ensure that not calling waitForIdle causes a race condition.
    450         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
    451         for (int i = 0; i < attempts; i++) {
    452             mWiFiNetworkAgent.setSignalStrength(i);
    453             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
    454                 // We hit a race condition, as expected. Pass the test.
    455                 return;
    456             }
    457         }
    458 
    459         // No race? There is a bug in this test.
    460         fail("expected race condition at least once in " + attempts + " attempts");
    461     }
    462 
    463     private class MockNetworkAgent {
    464         private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
    465                 | NETWORK_VALIDATION_PROBE_HTTP
    466                 | NETWORK_VALIDATION_PROBE_HTTPS;
    467         private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
    468                 | NETWORK_VALIDATION_RESULT_VALID;
    469         private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
    470                 | NETWORK_VALIDATION_PROBE_FALLBACK
    471                 | NETWORK_VALIDATION_RESULT_PARTIAL;
    472         private static final int VALIDATION_RESULT_INVALID = 0;
    473 
    474         private final INetworkMonitor mNetworkMonitor;
    475         private final NetworkInfo mNetworkInfo;
    476         private final NetworkCapabilities mNetworkCapabilities;
    477         private final HandlerThread mHandlerThread;
    478         private final ConditionVariable mDisconnected = new ConditionVariable();
    479         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
    480         private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
    481         private int mScore;
    482         private NetworkAgent mNetworkAgent;
    483         private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
    484         private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
    485         private Integer mExpectedKeepaliveSlot = null;
    486         // Contains the redirectUrl from networkStatus(). Before reading, wait for
    487         // mNetworkStatusReceived.
    488         private String mRedirectUrl;
    489 
    490         private INetworkMonitorCallbacks mNmCallbacks;
    491         private int mNmValidationResult = VALIDATION_RESULT_BASE;
    492         private String mNmValidationRedirectUrl = null;
    493         private boolean mNmProvNotificationRequested = false;
    494 
    495         void setNetworkValid() {
    496             mNmValidationResult = VALIDATION_RESULT_VALID;
    497             mNmValidationRedirectUrl = null;
    498         }
    499 
    500         void setNetworkInvalid() {
    501             mNmValidationResult = VALIDATION_RESULT_INVALID;
    502             mNmValidationRedirectUrl = null;
    503         }
    504 
    505         void setNetworkPortal(String redirectUrl) {
    506             setNetworkInvalid();
    507             mNmValidationRedirectUrl = redirectUrl;
    508         }
    509 
    510         void setNetworkPartial() {
    511             mNmValidationResult = VALIDATION_RESULT_PARTIAL;
    512             mNmValidationRedirectUrl = null;
    513         }
    514 
    515         void setNetworkPartialValid() {
    516             mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
    517             mNmValidationRedirectUrl = null;
    518         }
    519 
    520         MockNetworkAgent(int transport) {
    521             this(transport, new LinkProperties());
    522         }
    523 
    524         MockNetworkAgent(int transport, LinkProperties linkProperties) {
    525             final int type = transportToLegacyType(transport);
    526             final String typeName = ConnectivityManager.getNetworkTypeName(type);
    527             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
    528             mNetworkCapabilities = new NetworkCapabilities();
    529             mNetworkCapabilities.addTransportType(transport);
    530             switch (transport) {
    531                 case TRANSPORT_ETHERNET:
    532                     mScore = 70;
    533                     break;
    534                 case TRANSPORT_WIFI:
    535                     mScore = 60;
    536                     break;
    537                 case TRANSPORT_CELLULAR:
    538                     mScore = 50;
    539                     break;
    540                 case TRANSPORT_WIFI_AWARE:
    541                     mScore = 20;
    542                     break;
    543                 case TRANSPORT_VPN:
    544                     mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
    545                     mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
    546                     break;
    547                 default:
    548                     throw new UnsupportedOperationException("unimplemented network type");
    549             }
    550             mHandlerThread = new HandlerThread("Mock-" + typeName);
    551             mHandlerThread.start();
    552 
    553             mNetworkMonitor = mock(INetworkMonitor.class);
    554             final Answer validateAnswer = inv -> {
    555                 new Thread(this::onValidationRequested).start();
    556                 return null;
    557             };
    558 
    559             try {
    560                 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
    561                 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
    562             } catch (RemoteException e) {
    563                 fail(e.getMessage());
    564             }
    565 
    566             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
    567             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
    568                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
    569             doNothing().when(mNetworkStack).makeNetworkMonitor(
    570                     nmNetworkCaptor.capture(),
    571                     any() /* name */,
    572                     nmCbCaptor.capture());
    573 
    574             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
    575                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
    576                     linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
    577                 @Override
    578                 public void unwanted() { mDisconnected.open(); }
    579 
    580                 @Override
    581                 public void startSocketKeepalive(Message msg) {
    582                     int slot = msg.arg1;
    583                     if (mExpectedKeepaliveSlot != null) {
    584                         assertEquals((int) mExpectedKeepaliveSlot, slot);
    585                     }
    586                     onSocketKeepaliveEvent(slot, mStartKeepaliveError);
    587                 }
    588 
    589                 @Override
    590                 public void stopSocketKeepalive(Message msg) {
    591                     onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
    592                 }
    593 
    594                 @Override
    595                 public void networkStatus(int status, String redirectUrl) {
    596                     mRedirectUrl = redirectUrl;
    597                     mNetworkStatusReceived.open();
    598                 }
    599 
    600                 @Override
    601                 protected void preventAutomaticReconnect() {
    602                     mPreventReconnectReceived.open();
    603                 }
    604 
    605                 @Override
    606                 protected void addKeepalivePacketFilter(Message msg) {
    607                     Log.i(TAG, "Add keepalive packet filter.");
    608                 }
    609 
    610                 @Override
    611                 protected void removeKeepalivePacketFilter(Message msg) {
    612                     Log.i(TAG, "Remove keepalive packet filter.");
    613                 }
    614             };
    615 
    616             assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
    617             mNmCallbacks = nmCbCaptor.getValue();
    618 
    619             try {
    620                 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
    621             } catch (RemoteException e) {
    622                 fail(e.getMessage());
    623             }
    624 
    625             // Waits for the NetworkAgent to be registered, which includes the creation of the
    626             // NetworkMonitor.
    627             waitForIdle();
    628         }
    629 
    630         private void onValidationRequested() {
    631             try {
    632                 if (mNmProvNotificationRequested
    633                         && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
    634                     mNmCallbacks.hideProvisioningNotification();
    635                     mNmProvNotificationRequested = false;
    636                 }
    637 
    638                 mNmCallbacks.notifyNetworkTested(
    639                         mNmValidationResult, mNmValidationRedirectUrl);
    640 
    641                 if (mNmValidationRedirectUrl != null) {
    642                     mNmCallbacks.showProvisioningNotification(
    643                             "test_provisioning_notif_action", "com.android.test.package");
    644                     mNmProvNotificationRequested = true;
    645                 }
    646             } catch (RemoteException e) {
    647                 fail(e.getMessage());
    648             }
    649         }
    650 
    651         public void adjustScore(int change) {
    652             mScore += change;
    653             mNetworkAgent.sendNetworkScore(mScore);
    654         }
    655 
    656         public int getScore() {
    657             return mScore;
    658         }
    659 
    660         public void explicitlySelected(boolean acceptUnvalidated) {
    661             mNetworkAgent.explicitlySelected(acceptUnvalidated);
    662         }
    663 
    664         public void addCapability(int capability) {
    665             mNetworkCapabilities.addCapability(capability);
    666             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    667         }
    668 
    669         public void removeCapability(int capability) {
    670             mNetworkCapabilities.removeCapability(capability);
    671             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    672         }
    673 
    674         public void setUids(Set<UidRange> uids) {
    675             mNetworkCapabilities.setUids(uids);
    676             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    677         }
    678 
    679         public void setSignalStrength(int signalStrength) {
    680             mNetworkCapabilities.setSignalStrength(signalStrength);
    681             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    682         }
    683 
    684         public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
    685             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
    686             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    687         }
    688 
    689         public void setNetworkCapabilities(NetworkCapabilities nc,
    690                 boolean sendToConnectivityService) {
    691             mNetworkCapabilities.set(nc);
    692             if (sendToConnectivityService) {
    693                 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    694             }
    695         }
    696 
    697         public void connectWithoutInternet() {
    698             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
    699             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    700         }
    701 
    702         /**
    703          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
    704          * @param validated Indicate if network should pretend to be validated.
    705          */
    706         public void connect(boolean validated) {
    707             connect(validated, true);
    708         }
    709 
    710         /**
    711          * Transition this NetworkAgent to CONNECTED state.
    712          * @param validated Indicate if network should pretend to be validated.
    713          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
    714          */
    715         public void connect(boolean validated, boolean hasInternet) {
    716             assertEquals("MockNetworkAgents can only be connected once",
    717                     mNetworkInfo.getDetailedState(), DetailedState.IDLE);
    718             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
    719 
    720             NetworkCallback callback = null;
    721             final ConditionVariable validatedCv = new ConditionVariable();
    722             if (validated) {
    723                 setNetworkValid();
    724                 NetworkRequest request = new NetworkRequest.Builder()
    725                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
    726                         .clearCapabilities()
    727                         .build();
    728                 callback = new NetworkCallback() {
    729                     public void onCapabilitiesChanged(Network network,
    730                             NetworkCapabilities networkCapabilities) {
    731                         if (network.equals(getNetwork()) &&
    732                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
    733                             validatedCv.open();
    734                         }
    735                     }
    736                 };
    737                 mCm.registerNetworkCallback(request, callback);
    738             }
    739             if (hasInternet) {
    740                 addCapability(NET_CAPABILITY_INTERNET);
    741             }
    742 
    743             connectWithoutInternet();
    744 
    745             if (validated) {
    746                 // Wait for network to validate.
    747                 waitFor(validatedCv);
    748                 setNetworkInvalid();
    749             }
    750 
    751             if (callback != null) mCm.unregisterNetworkCallback(callback);
    752         }
    753 
    754         public void connectWithCaptivePortal(String redirectUrl) {
    755             setNetworkPortal(redirectUrl);
    756             connect(false);
    757         }
    758 
    759         public void connectWithPartialConnectivity() {
    760             setNetworkPartial();
    761             connect(false);
    762         }
    763 
    764         public void suspend() {
    765             mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
    766             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    767         }
    768 
    769         public void resume() {
    770             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
    771             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    772         }
    773 
    774         public void disconnect() {
    775             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
    776             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    777         }
    778 
    779         public Network getNetwork() {
    780             return new Network(mNetworkAgent.netId);
    781         }
    782 
    783         public ConditionVariable getPreventReconnectReceived() {
    784             return mPreventReconnectReceived;
    785         }
    786 
    787         public ConditionVariable getDisconnectedCV() {
    788             return mDisconnected;
    789         }
    790 
    791         public void sendLinkProperties(LinkProperties lp) {
    792             mNetworkAgent.sendLinkProperties(lp);
    793         }
    794 
    795         public void setStartKeepaliveError(int error) {
    796             mStartKeepaliveError = error;
    797         }
    798 
    799         public void setStopKeepaliveError(int error) {
    800             mStopKeepaliveError = error;
    801         }
    802 
    803         public void setExpectedKeepaliveSlot(Integer slot) {
    804             mExpectedKeepaliveSlot = slot;
    805         }
    806 
    807         public String waitForRedirectUrl() {
    808             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
    809             return mRedirectUrl;
    810         }
    811 
    812         public NetworkAgent getNetworkAgent() {
    813             return mNetworkAgent;
    814         }
    815 
    816         public NetworkCapabilities getNetworkCapabilities() {
    817             return mNetworkCapabilities;
    818         }
    819     }
    820 
    821     /**
    822      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
    823      * operations have been processed. Before ConnectivityService can add or remove any requests,
    824      * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
    825      * expectRemoveRequests.
    826      */
    827     private static class MockNetworkFactory extends NetworkFactory {
    828         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
    829         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
    830         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
    831 
    832         // Used to expect that requests be removed or added on a separate thread, without sleeping.
    833         // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
    834         // once, then cause some other thread to add or remove requests, then call
    835         // waitForRequests().
    836         // It is not possible to wait for both add and remove requests. When adding, the queue
    837         // contains the expected score. When removing, the value is unused, all matters is the
    838         // number of objects in the queue.
    839         private final LinkedBlockingQueue<Integer> mExpectations;
    840 
    841         // Whether we are currently expecting requests to be added or removed. Valid only if
    842         // mExpectations is non-empty.
    843         private boolean mExpectingAdditions;
    844 
    845         // Used to collect the networks requests managed by this factory. This is a duplicate of
    846         // the internal information stored in the NetworkFactory (which is private).
    847         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
    848 
    849         public MockNetworkFactory(Looper looper, Context context, String logTag,
    850                 NetworkCapabilities filter) {
    851             super(looper, context, logTag, filter);
    852             mExpectations = new LinkedBlockingQueue<>();
    853         }
    854 
    855         public int getMyRequestCount() {
    856             return getRequestCount();
    857         }
    858 
    859         protected void startNetwork() {
    860             mNetworkStarted.set(true);
    861             mNetworkStartedCV.open();
    862         }
    863 
    864         protected void stopNetwork() {
    865             mNetworkStarted.set(false);
    866             mNetworkStoppedCV.open();
    867         }
    868 
    869         public boolean getMyStartRequested() {
    870             return mNetworkStarted.get();
    871         }
    872 
    873         public ConditionVariable getNetworkStartedCV() {
    874             mNetworkStartedCV.close();
    875             return mNetworkStartedCV;
    876         }
    877 
    878         public ConditionVariable getNetworkStoppedCV() {
    879             mNetworkStoppedCV.close();
    880             return mNetworkStoppedCV;
    881         }
    882 
    883         @Override
    884         protected void handleAddRequest(NetworkRequest request, int score,
    885                 int factorySerialNumber) {
    886             synchronized (mExpectations) {
    887                 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
    888 
    889                 assertNotNull("Added more requests than expected (" + request + " score : "
    890                         + score + ")", expectedScore);
    891                 // If we're expecting anything, we must be expecting additions.
    892                 if (!mExpectingAdditions) {
    893                     fail("Can't add requests while expecting requests to be removed");
    894                 }
    895                 if (expectedScore != score) {
    896                     fail("Expected score was " + expectedScore + " but actual was " + score
    897                             + " in added request");
    898                 }
    899 
    900                 // Add the request.
    901                 mNetworkRequests.put(request.requestId, request);
    902                 super.handleAddRequest(request, score, factorySerialNumber);
    903                 mExpectations.notify();
    904             }
    905         }
    906 
    907         @Override
    908         protected void handleRemoveRequest(NetworkRequest request) {
    909             synchronized (mExpectations) {
    910                 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
    911 
    912                 assertTrue("Removed more requests than expected", expectedScore != null);
    913                 // If we're expecting anything, we must be expecting removals.
    914                 if (mExpectingAdditions) {
    915                     fail("Can't remove requests while expecting requests to be added");
    916                 }
    917 
    918                 // Remove the request.
    919                 mNetworkRequests.remove(request.requestId);
    920                 super.handleRemoveRequest(request);
    921                 mExpectations.notify();
    922             }
    923         }
    924 
    925         // Trigger releasing the request as unfulfillable
    926         public void triggerUnfulfillable(NetworkRequest r) {
    927             super.releaseRequestAsUnfulfillableByAnyFactory(r);
    928         }
    929 
    930         private void assertNoExpectations() {
    931             if (mExpectations.size() != 0) {
    932                 fail("Can't add expectation, " + mExpectations.size() + " already pending");
    933             }
    934         }
    935 
    936         // Expects that requests with the specified scores will be added.
    937         public void expectAddRequestsWithScores(final int... scores) {
    938             assertNoExpectations();
    939             mExpectingAdditions = true;
    940             for (int score : scores) {
    941                 mExpectations.add(score);
    942             }
    943         }
    944 
    945         // Expects that count requests will be removed.
    946         public void expectRemoveRequests(final int count) {
    947             assertNoExpectations();
    948             mExpectingAdditions = false;
    949             for (int i = 0; i < count; ++i) {
    950                 mExpectations.add(0); // For removals the score is ignored so any value will do.
    951             }
    952         }
    953 
    954         // Waits for the expected request additions or removals to happen within a timeout.
    955         public void waitForRequests() throws InterruptedException {
    956             final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
    957             synchronized (mExpectations) {
    958                 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
    959                     mExpectations.wait(deadline - SystemClock.elapsedRealtime());
    960                 }
    961             }
    962             final long count = mExpectations.size();
    963             final String msg = count + " requests still not " +
    964                     (mExpectingAdditions ? "added" : "removed") +
    965                     " after " + TIMEOUT_MS + " ms";
    966             assertEquals(msg, 0, count);
    967         }
    968 
    969         public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
    970                 throws InterruptedException {
    971             waitForRequests();
    972             assertEquals(count, getMyRequestCount());
    973             return mNetworkRequests;
    974         }
    975     }
    976 
    977     private static Looper startHandlerThreadAndReturnLooper() {
    978         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
    979         handlerThread.start();
    980         return handlerThread.getLooper();
    981     }
    982 
    983     private class MockVpn extends Vpn {
    984         // TODO : the interactions between this mock and the mock network agent are too
    985         // hard to get right at this moment, because it's unclear in which case which
    986         // target needs to get a method call or both, and in what order. It's because
    987         // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
    988         // parent class of MockVpn agent wants that responsibility.
    989         // That being said inside the test it should be possible to make the interactions
    990         // harder to get wrong with precise speccing, judicious comments, helper methods
    991         // and a few sprinkled assertions.
    992 
    993         private boolean mConnected = false;
    994         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
    995         // not inherit from NetworkAgent.
    996         private MockNetworkAgent mMockNetworkAgent;
    997 
    998         public MockVpn(int userId) {
    999             super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
   1000                     userId);
   1001         }
   1002 
   1003         public void setNetworkAgent(MockNetworkAgent agent) {
   1004             waitForIdle(agent, TIMEOUT_MS);
   1005             mMockNetworkAgent = agent;
   1006             mNetworkAgent = agent.getNetworkAgent();
   1007             mNetworkCapabilities.set(agent.getNetworkCapabilities());
   1008         }
   1009 
   1010         public void setUids(Set<UidRange> uids) {
   1011             mNetworkCapabilities.setUids(uids);
   1012             updateCapabilities(null /* defaultNetwork */);
   1013         }
   1014 
   1015         @Override
   1016         public int getNetId() {
   1017             if (mMockNetworkAgent == null) {
   1018                 return NETID_UNSET;
   1019             }
   1020             return mMockNetworkAgent.getNetwork().netId;
   1021         }
   1022 
   1023         @Override
   1024         public boolean appliesToUid(int uid) {
   1025             return mConnected;  // Trickery to simplify testing.
   1026         }
   1027 
   1028         @Override
   1029         protected boolean isCallerEstablishedOwnerLocked() {
   1030             return mConnected;  // Similar trickery
   1031         }
   1032 
   1033         private void connect(boolean isAlwaysMetered) {
   1034             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
   1035             mConnected = true;
   1036             mConfig = new VpnConfig();
   1037             mConfig.isMetered = isAlwaysMetered;
   1038         }
   1039 
   1040         public void connectAsAlwaysMetered() {
   1041             connect(true /* isAlwaysMetered */);
   1042         }
   1043 
   1044         public void connect() {
   1045             connect(false /* isAlwaysMetered */);
   1046         }
   1047 
   1048         @Override
   1049         public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
   1050             if (!mConnected) return null;
   1051             super.updateCapabilities(defaultNetwork);
   1052             // Because super.updateCapabilities will update the capabilities of the agent but
   1053             // not the mock agent, the mock agent needs to know about them.
   1054             copyCapabilitiesToNetworkAgent();
   1055             return new NetworkCapabilities(mNetworkCapabilities);
   1056         }
   1057 
   1058         private void copyCapabilitiesToNetworkAgent() {
   1059             if (null != mMockNetworkAgent) {
   1060                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
   1061                         false /* sendToConnectivityService */);
   1062             }
   1063         }
   1064 
   1065         public void disconnect() {
   1066             mConnected = false;
   1067             mConfig = null;
   1068         }
   1069     }
   1070 
   1071     private class FakeWakeupMessage extends WakeupMessage {
   1072         private static final int UNREASONABLY_LONG_WAIT = 1000;
   1073 
   1074         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
   1075             super(context, handler, cmdName, cmd);
   1076         }
   1077 
   1078         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
   1079                 int arg1, int arg2, Object obj) {
   1080             super(context, handler, cmdName, cmd, arg1, arg2, obj);
   1081         }
   1082 
   1083         @Override
   1084         public void schedule(long when) {
   1085             long delayMs = when - SystemClock.elapsedRealtime();
   1086             if (delayMs < 0) delayMs = 0;
   1087             if (delayMs > UNREASONABLY_LONG_WAIT) {
   1088                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
   1089                         "ms into the future: " + delayMs);
   1090             }
   1091             Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
   1092             mHandler.sendMessageDelayed(msg, delayMs);
   1093         }
   1094 
   1095         @Override
   1096         public void cancel() {
   1097             mHandler.removeMessages(mCmd, mObj);
   1098         }
   1099 
   1100         @Override
   1101         public void onAlarm() {
   1102             throw new AssertionError("Should never happen. Update this fake.");
   1103         }
   1104     }
   1105 
   1106     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
   1107         public volatile boolean configRestrictsAvoidBadWifi;
   1108         public volatile int configMeteredMultipathPreference;
   1109 
   1110         public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
   1111             super(c, h, r);
   1112         }
   1113 
   1114         @Override
   1115         public boolean configRestrictsAvoidBadWifi() {
   1116             return configRestrictsAvoidBadWifi;
   1117         }
   1118 
   1119         @Override
   1120         public int configMeteredMultipathPreference() {
   1121             return configMeteredMultipathPreference;
   1122         }
   1123     }
   1124 
   1125     private class WrappedConnectivityService extends ConnectivityService {
   1126         public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
   1127         private MockableSystemProperties mSystemProperties;
   1128 
   1129         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
   1130                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
   1131                 IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
   1132             super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
   1133             mNetd = netd;
   1134             mLingerDelayMs = TEST_LINGER_DELAY_MS;
   1135         }
   1136 
   1137         @Override
   1138         protected MockableSystemProperties getSystemProperties() {
   1139             // Minimal approach to overriding system properties: let most calls fall through to real
   1140             // device values, and only override ones values that are important to this test.
   1141             mSystemProperties = spy(new MockableSystemProperties());
   1142             when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
   1143             when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
   1144             return mSystemProperties;
   1145         }
   1146 
   1147         @Override
   1148         protected Tethering makeTethering() {
   1149             return mock(Tethering.class);
   1150         }
   1151 
   1152         @Override
   1153         protected ProxyTracker makeProxyTracker() {
   1154             return mock(ProxyTracker.class);
   1155         }
   1156 
   1157         @Override
   1158         protected int reserveNetId() {
   1159             while (true) {
   1160                 final int netId = super.reserveNetId();
   1161 
   1162                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
   1163                 // can have odd side-effects, like network validations succeeding.
   1164                 Context context = InstrumentationRegistry.getContext();
   1165                 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
   1166                 boolean overlaps = false;
   1167                 for (Network network : networks) {
   1168                     if (netId == network.netId) {
   1169                         overlaps = true;
   1170                         break;
   1171                     }
   1172                 }
   1173                 if (overlaps) continue;
   1174 
   1175                 return netId;
   1176             }
   1177         }
   1178 
   1179         @Override
   1180         protected boolean queryUserAccess(int uid, int netId) {
   1181             return true;
   1182         }
   1183 
   1184         public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
   1185             return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
   1186         }
   1187 
   1188         @Override
   1189         public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
   1190                 Context c, Handler h, Runnable r) {
   1191             final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
   1192             return tracker;
   1193         }
   1194 
   1195         public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
   1196             return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
   1197         }
   1198 
   1199         @Override
   1200         protected NetworkStackClient getNetworkStack() {
   1201             return mNetworkStack;
   1202         }
   1203 
   1204         @Override
   1205         public WakeupMessage makeWakeupMessage(
   1206                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
   1207             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
   1208         }
   1209 
   1210         @Override
   1211         public boolean hasService(String name) {
   1212             // Currenty, the only relevant service that ConnectivityService checks for is
   1213             // ETHERNET_SERVICE.
   1214             return Context.ETHERNET_SERVICE.equals(name);
   1215         }
   1216 
   1217         @Override
   1218         protected IpConnectivityMetrics.Logger metricsLogger() {
   1219             return mMetricsService;
   1220         }
   1221 
   1222         @Override
   1223         protected void registerNetdEventCallback() {
   1224         }
   1225 
   1226         public void mockVpn(int uid) {
   1227             synchronized (mVpns) {
   1228                 int userId = UserHandle.getUserId(uid);
   1229                 mMockVpn = new MockVpn(userId);
   1230                 // This has no effect unless the VPN is actually connected, because things like
   1231                 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
   1232                 // netId, and check if that network is actually connected.
   1233                 mVpns.put(userId, mMockVpn);
   1234             }
   1235         }
   1236 
   1237         public void waitForIdle(int timeoutMs) {
   1238             waitForIdleHandler(mHandlerThread, timeoutMs);
   1239         }
   1240 
   1241         public void waitForIdle() {
   1242             waitForIdle(TIMEOUT_MS);
   1243         }
   1244 
   1245         public void setUidRulesChanged(int uidRules) {
   1246             try {
   1247                 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
   1248             } catch (RemoteException ignored) {
   1249             }
   1250         }
   1251 
   1252         public void setRestrictBackgroundChanged(boolean restrictBackground) {
   1253             try {
   1254                 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
   1255             } catch (RemoteException ignored) {
   1256             }
   1257         }
   1258     }
   1259 
   1260     /**
   1261      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
   1262      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
   1263      */
   1264     static private void waitFor(ConditionVariable conditionVariable) {
   1265         if (conditionVariable.block(TIMEOUT_MS)) {
   1266             return;
   1267         }
   1268         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
   1269     }
   1270 
   1271     private static final int VPN_USER = 0;
   1272     private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
   1273     private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
   1274     private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
   1275 
   1276     @Before
   1277     public void setUp() throws Exception {
   1278         mContext = InstrumentationRegistry.getContext();
   1279 
   1280         MockitoAnnotations.initMocks(this);
   1281         when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
   1282 
   1283         when(mUserManager.getUsers(eq(true))).thenReturn(
   1284                 Arrays.asList(new UserInfo[] {
   1285                         new UserInfo(VPN_USER, "", 0),
   1286                 }));
   1287 
   1288         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
   1289         // http://b/25897652 .
   1290         if (Looper.myLooper() == null) {
   1291             Looper.prepare();
   1292         }
   1293         mockDefaultPackages();
   1294 
   1295         FakeSettingsProvider.clearSettingsProvider();
   1296         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
   1297                 new FakeSettingsProvider());
   1298         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
   1299         LocalServices.addService(
   1300                 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
   1301 
   1302         mService = new WrappedConnectivityService(mServiceContext,
   1303                 mNetworkManagementService,
   1304                 mStatsService,
   1305                 mNpm,
   1306                 mock(IpConnectivityLog.class),
   1307                 mMockNetd,
   1308                 mMockDnsResolver);
   1309 
   1310         final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
   1311                 ArgumentCaptor.forClass(INetworkPolicyListener.class);
   1312         verify(mNpm).registerListener(policyListenerCaptor.capture());
   1313         mPolicyListener = policyListenerCaptor.getValue();
   1314 
   1315         // Create local CM before sending system ready so that we can answer
   1316         // getSystemService() correctly.
   1317         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
   1318         mService.systemReady();
   1319         mService.mockVpn(Process.myUid());
   1320         mCm.bindProcessToNetwork(null);
   1321 
   1322         // Ensure that the default setting for Captive Portals is used for most tests
   1323         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
   1324         setAlwaysOnNetworks(false);
   1325         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
   1326     }
   1327 
   1328     @After
   1329     public void tearDown() throws Exception {
   1330         setAlwaysOnNetworks(false);
   1331         if (mCellNetworkAgent != null) {
   1332             mCellNetworkAgent.disconnect();
   1333             mCellNetworkAgent = null;
   1334         }
   1335         if (mWiFiNetworkAgent != null) {
   1336             mWiFiNetworkAgent.disconnect();
   1337             mWiFiNetworkAgent = null;
   1338         }
   1339         if (mEthernetNetworkAgent != null) {
   1340             mEthernetNetworkAgent.disconnect();
   1341             mEthernetNetworkAgent = null;
   1342         }
   1343         FakeSettingsProvider.clearSettingsProvider();
   1344     }
   1345 
   1346     private void mockDefaultPackages() throws Exception {
   1347         final String testPackageName = mContext.getPackageName();
   1348         final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
   1349                 testPackageName, PackageManager.GET_PERMISSIONS);
   1350         when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
   1351                 new String[] {testPackageName});
   1352         when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
   1353                 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
   1354 
   1355         when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
   1356                 Arrays.asList(new PackageInfo[] {
   1357                         buildPackageInfo(/* SYSTEM */ false, APP1_UID),
   1358                         buildPackageInfo(/* SYSTEM */ false, APP2_UID),
   1359                         buildPackageInfo(/* SYSTEM */ false, VPN_UID)
   1360                 }));
   1361     }
   1362 
   1363    private static int transportToLegacyType(int transport) {
   1364         switch (transport) {
   1365             case TRANSPORT_ETHERNET:
   1366                 return TYPE_ETHERNET;
   1367             case TRANSPORT_WIFI:
   1368                 return TYPE_WIFI;
   1369             case TRANSPORT_CELLULAR:
   1370                 return TYPE_MOBILE;
   1371             case TRANSPORT_VPN:
   1372                 return TYPE_VPN;
   1373             default:
   1374                 return TYPE_NONE;
   1375         }
   1376     }
   1377 
   1378     private void verifyActiveNetwork(int transport) {
   1379         // Test getActiveNetworkInfo()
   1380         assertNotNull(mCm.getActiveNetworkInfo());
   1381         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
   1382         // Test getActiveNetwork()
   1383         assertNotNull(mCm.getActiveNetwork());
   1384         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
   1385         if (!NetworkCapabilities.isValidTransport(transport)) {
   1386             throw new IllegalStateException("Unknown transport " + transport);
   1387         }
   1388         switch (transport) {
   1389             case TRANSPORT_WIFI:
   1390                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
   1391                 break;
   1392             case TRANSPORT_CELLULAR:
   1393                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
   1394                 break;
   1395             default:
   1396                 break;
   1397         }
   1398         // Test getNetworkInfo(Network)
   1399         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
   1400         assertEquals(transportToLegacyType(transport),
   1401                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
   1402         // Test getNetworkCapabilities(Network)
   1403         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
   1404         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
   1405     }
   1406 
   1407     private void verifyNoNetwork() {
   1408         waitForIdle();
   1409         // Test getActiveNetworkInfo()
   1410         assertNull(mCm.getActiveNetworkInfo());
   1411         // Test getActiveNetwork()
   1412         assertNull(mCm.getActiveNetwork());
   1413         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
   1414         // Test getAllNetworks()
   1415         assertEmpty(mCm.getAllNetworks());
   1416     }
   1417 
   1418     /**
   1419      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
   1420      * broadcasts are received.
   1421      */
   1422     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
   1423         final ConditionVariable cv = new ConditionVariable();
   1424         mServiceContext.registerReceiver(new BroadcastReceiver() {
   1425                     private int remaining = count;
   1426                     public void onReceive(Context context, Intent intent) {
   1427                         if (--remaining == 0) {
   1428                             cv.open();
   1429                             mServiceContext.unregisterReceiver(this);
   1430                         }
   1431                     }
   1432                 }, new IntentFilter(CONNECTIVITY_ACTION));
   1433         return cv;
   1434     }
   1435 
   1436     @Test
   1437     public void testNetworkTypes() {
   1438         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
   1439         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
   1440         // will fail. Failing here is much easier to debug.
   1441         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
   1442         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
   1443         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
   1444         assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
   1445 
   1446         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
   1447         // mocks, this assert exercises the ConnectivityService code path that ensures that
   1448         // TYPE_ETHERNET is supported if the ethernet service is running.
   1449         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
   1450     }
   1451 
   1452     @Test
   1453     public void testLingering() throws Exception {
   1454         verifyNoNetwork();
   1455         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1456         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1457         assertNull(mCm.getActiveNetworkInfo());
   1458         assertNull(mCm.getActiveNetwork());
   1459         // Test bringing up validated cellular.
   1460         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1461         mCellNetworkAgent.connect(true);
   1462         waitFor(cv);
   1463         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1464         assertLength(2, mCm.getAllNetworks());
   1465         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
   1466                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
   1467         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
   1468                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
   1469         // Test bringing up validated WiFi.
   1470         cv = waitForConnectivityBroadcasts(2);
   1471         mWiFiNetworkAgent.connect(true);
   1472         waitFor(cv);
   1473         verifyActiveNetwork(TRANSPORT_WIFI);
   1474         assertLength(2, mCm.getAllNetworks());
   1475         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
   1476                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
   1477         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
   1478                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
   1479         // Test cellular linger timeout.
   1480         waitFor(mCellNetworkAgent.getDisconnectedCV());
   1481         waitForIdle();
   1482         assertLength(1, mCm.getAllNetworks());
   1483         verifyActiveNetwork(TRANSPORT_WIFI);
   1484         assertLength(1, mCm.getAllNetworks());
   1485         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
   1486         // Test WiFi disconnect.
   1487         cv = waitForConnectivityBroadcasts(1);
   1488         mWiFiNetworkAgent.disconnect();
   1489         waitFor(cv);
   1490         verifyNoNetwork();
   1491     }
   1492 
   1493     @Test
   1494     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
   1495         // Test bringing up unvalidated WiFi
   1496         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1497         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1498         mWiFiNetworkAgent.connect(false);
   1499         waitFor(cv);
   1500         verifyActiveNetwork(TRANSPORT_WIFI);
   1501         // Test bringing up unvalidated cellular
   1502         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1503         mCellNetworkAgent.connect(false);
   1504         waitForIdle();
   1505         verifyActiveNetwork(TRANSPORT_WIFI);
   1506         // Test cellular disconnect.
   1507         mCellNetworkAgent.disconnect();
   1508         waitForIdle();
   1509         verifyActiveNetwork(TRANSPORT_WIFI);
   1510         // Test bringing up validated cellular
   1511         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1512         cv = waitForConnectivityBroadcasts(2);
   1513         mCellNetworkAgent.connect(true);
   1514         waitFor(cv);
   1515         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1516         // Test cellular disconnect.
   1517         cv = waitForConnectivityBroadcasts(2);
   1518         mCellNetworkAgent.disconnect();
   1519         waitFor(cv);
   1520         verifyActiveNetwork(TRANSPORT_WIFI);
   1521         // Test WiFi disconnect.
   1522         cv = waitForConnectivityBroadcasts(1);
   1523         mWiFiNetworkAgent.disconnect();
   1524         waitFor(cv);
   1525         verifyNoNetwork();
   1526     }
   1527 
   1528     @Test
   1529     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
   1530         // Test bringing up unvalidated cellular.
   1531         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1532         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1533         mCellNetworkAgent.connect(false);
   1534         waitFor(cv);
   1535         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1536         // Test bringing up unvalidated WiFi.
   1537         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1538         cv = waitForConnectivityBroadcasts(2);
   1539         mWiFiNetworkAgent.connect(false);
   1540         waitFor(cv);
   1541         verifyActiveNetwork(TRANSPORT_WIFI);
   1542         // Test WiFi disconnect.
   1543         cv = waitForConnectivityBroadcasts(2);
   1544         mWiFiNetworkAgent.disconnect();
   1545         waitFor(cv);
   1546         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1547         // Test cellular disconnect.
   1548         cv = waitForConnectivityBroadcasts(1);
   1549         mCellNetworkAgent.disconnect();
   1550         waitFor(cv);
   1551         verifyNoNetwork();
   1552     }
   1553 
   1554     @Test
   1555     public void testUnlingeringDoesNotValidate() throws Exception {
   1556         // Test bringing up unvalidated WiFi.
   1557         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1558         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1559         mWiFiNetworkAgent.connect(false);
   1560         waitFor(cv);
   1561         verifyActiveNetwork(TRANSPORT_WIFI);
   1562         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1563                 NET_CAPABILITY_VALIDATED));
   1564         // Test bringing up validated cellular.
   1565         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1566         cv = waitForConnectivityBroadcasts(2);
   1567         mCellNetworkAgent.connect(true);
   1568         waitFor(cv);
   1569         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1570         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1571                 NET_CAPABILITY_VALIDATED));
   1572         // Test cellular disconnect.
   1573         cv = waitForConnectivityBroadcasts(2);
   1574         mCellNetworkAgent.disconnect();
   1575         waitFor(cv);
   1576         verifyActiveNetwork(TRANSPORT_WIFI);
   1577         // Unlingering a network should not cause it to be marked as validated.
   1578         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1579                 NET_CAPABILITY_VALIDATED));
   1580     }
   1581 
   1582     @Test
   1583     public void testCellularOutscoresWeakWifi() throws Exception {
   1584         // Test bringing up validated cellular.
   1585         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1586         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1587         mCellNetworkAgent.connect(true);
   1588         waitFor(cv);
   1589         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1590         // Test bringing up validated WiFi.
   1591         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1592         cv = waitForConnectivityBroadcasts(2);
   1593         mWiFiNetworkAgent.connect(true);
   1594         waitFor(cv);
   1595         verifyActiveNetwork(TRANSPORT_WIFI);
   1596         // Test WiFi getting really weak.
   1597         cv = waitForConnectivityBroadcasts(2);
   1598         mWiFiNetworkAgent.adjustScore(-11);
   1599         waitFor(cv);
   1600         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1601         // Test WiFi restoring signal strength.
   1602         cv = waitForConnectivityBroadcasts(2);
   1603         mWiFiNetworkAgent.adjustScore(11);
   1604         waitFor(cv);
   1605         verifyActiveNetwork(TRANSPORT_WIFI);
   1606     }
   1607 
   1608     @Test
   1609     public void testReapingNetwork() throws Exception {
   1610         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
   1611         // Expect it to be torn down immediately because it satisfies no requests.
   1612         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1613         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
   1614         mWiFiNetworkAgent.connectWithoutInternet();
   1615         waitFor(cv);
   1616         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
   1617         // Expect it to be torn down immediately because it satisfies no requests.
   1618         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1619         cv = mCellNetworkAgent.getDisconnectedCV();
   1620         mCellNetworkAgent.connectWithoutInternet();
   1621         waitFor(cv);
   1622         // Test bringing up validated WiFi.
   1623         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1624         cv = waitForConnectivityBroadcasts(1);
   1625         mWiFiNetworkAgent.connect(true);
   1626         waitFor(cv);
   1627         verifyActiveNetwork(TRANSPORT_WIFI);
   1628         // Test bringing up unvalidated cellular.
   1629         // Expect it to be torn down because it could never be the highest scoring network
   1630         // satisfying the default request even if it validated.
   1631         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1632         cv = mCellNetworkAgent.getDisconnectedCV();
   1633         mCellNetworkAgent.connect(false);
   1634         waitFor(cv);
   1635         verifyActiveNetwork(TRANSPORT_WIFI);
   1636         cv = mWiFiNetworkAgent.getDisconnectedCV();
   1637         mWiFiNetworkAgent.disconnect();
   1638         waitFor(cv);
   1639     }
   1640 
   1641     @Test
   1642     public void testCellularFallback() throws Exception {
   1643         // Test bringing up validated cellular.
   1644         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1645         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1646         mCellNetworkAgent.connect(true);
   1647         waitFor(cv);
   1648         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1649         // Test bringing up validated WiFi.
   1650         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1651         cv = waitForConnectivityBroadcasts(2);
   1652         mWiFiNetworkAgent.connect(true);
   1653         waitFor(cv);
   1654         verifyActiveNetwork(TRANSPORT_WIFI);
   1655         // Reevaluate WiFi (it'll instantly fail DNS).
   1656         cv = waitForConnectivityBroadcasts(2);
   1657         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1658                 NET_CAPABILITY_VALIDATED));
   1659         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
   1660         // Should quickly fall back to Cellular.
   1661         waitFor(cv);
   1662         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1663                 NET_CAPABILITY_VALIDATED));
   1664         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1665         // Reevaluate cellular (it'll instantly fail DNS).
   1666         cv = waitForConnectivityBroadcasts(2);
   1667         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1668                 NET_CAPABILITY_VALIDATED));
   1669         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
   1670         // Should quickly fall back to WiFi.
   1671         waitFor(cv);
   1672         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1673                 NET_CAPABILITY_VALIDATED));
   1674         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1675                 NET_CAPABILITY_VALIDATED));
   1676         verifyActiveNetwork(TRANSPORT_WIFI);
   1677     }
   1678 
   1679     @Test
   1680     public void testWiFiFallback() throws Exception {
   1681         // Test bringing up unvalidated WiFi.
   1682         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1683         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1684         mWiFiNetworkAgent.connect(false);
   1685         waitFor(cv);
   1686         verifyActiveNetwork(TRANSPORT_WIFI);
   1687         // Test bringing up validated cellular.
   1688         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1689         cv = waitForConnectivityBroadcasts(2);
   1690         mCellNetworkAgent.connect(true);
   1691         waitFor(cv);
   1692         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1693         // Reevaluate cellular (it'll instantly fail DNS).
   1694         cv = waitForConnectivityBroadcasts(2);
   1695         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1696                 NET_CAPABILITY_VALIDATED));
   1697         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
   1698         // Should quickly fall back to WiFi.
   1699         waitFor(cv);
   1700         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1701                 NET_CAPABILITY_VALIDATED));
   1702         verifyActiveNetwork(TRANSPORT_WIFI);
   1703     }
   1704 
   1705     @Test
   1706     public void testRequiresValidation() {
   1707         assertTrue(NetworkMonitorUtils.isValidationRequired(
   1708                 mCm.getDefaultRequest().networkCapabilities));
   1709     }
   1710 
   1711     enum CallbackState {
   1712         NONE,
   1713         AVAILABLE,
   1714         NETWORK_CAPABILITIES,
   1715         LINK_PROPERTIES,
   1716         SUSPENDED,
   1717         RESUMED,
   1718         LOSING,
   1719         LOST,
   1720         UNAVAILABLE,
   1721         BLOCKED_STATUS
   1722     }
   1723 
   1724     private static class CallbackInfo {
   1725         public final CallbackState state;
   1726         public final Network network;
   1727         public final Object arg;
   1728         public CallbackInfo(CallbackState s, Network n, Object o) {
   1729             state = s; network = n; arg = o;
   1730         }
   1731         public String toString() {
   1732             return String.format("%s (%s) (%s)", state, network, arg);
   1733         }
   1734         @Override
   1735         public boolean equals(Object o) {
   1736             if (!(o instanceof CallbackInfo)) return false;
   1737             // Ignore timeMs, since it's unpredictable.
   1738             CallbackInfo other = (CallbackInfo) o;
   1739             return (state == other.state) && Objects.equals(network, other.network);
   1740         }
   1741         @Override
   1742         public int hashCode() {
   1743             return Objects.hash(state, network);
   1744         }
   1745     }
   1746 
   1747     /**
   1748      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
   1749      * this class receives, by calling expectCallback() exactly once each time a callback is
   1750      * received. assertNoCallback may be called at any time.
   1751      */
   1752     private class TestNetworkCallback extends NetworkCallback {
   1753         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
   1754         private Network mLastAvailableNetwork;
   1755 
   1756         protected void setLastCallback(CallbackState state, Network network, Object o) {
   1757             mCallbacks.offer(new CallbackInfo(state, network, o));
   1758         }
   1759 
   1760         @Override
   1761         public void onAvailable(Network network) {
   1762             mLastAvailableNetwork = network;
   1763             setLastCallback(CallbackState.AVAILABLE, network, null);
   1764         }
   1765 
   1766         @Override
   1767         public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
   1768             setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
   1769         }
   1770 
   1771         @Override
   1772         public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
   1773             setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
   1774         }
   1775 
   1776         @Override
   1777         public void onUnavailable() {
   1778             setLastCallback(CallbackState.UNAVAILABLE, null, null);
   1779         }
   1780 
   1781         @Override
   1782         public void onNetworkSuspended(Network network) {
   1783             setLastCallback(CallbackState.SUSPENDED, network, null);
   1784         }
   1785 
   1786         @Override
   1787         public void onNetworkResumed(Network network) {
   1788             setLastCallback(CallbackState.RESUMED, network, null);
   1789         }
   1790 
   1791         @Override
   1792         public void onLosing(Network network, int maxMsToLive) {
   1793             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
   1794         }
   1795 
   1796         @Override
   1797         public void onLost(Network network) {
   1798             mLastAvailableNetwork = null;
   1799             setLastCallback(CallbackState.LOST, network, null);
   1800         }
   1801 
   1802         @Override
   1803         public void onBlockedStatusChanged(Network network, boolean blocked) {
   1804             setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
   1805         }
   1806 
   1807         public Network getLastAvailableNetwork() {
   1808             return mLastAvailableNetwork;
   1809         }
   1810 
   1811         CallbackInfo nextCallback(int timeoutMs) {
   1812             CallbackInfo cb = null;
   1813             try {
   1814                 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
   1815             } catch (InterruptedException e) {
   1816             }
   1817             if (cb == null) {
   1818                 // LinkedBlockingQueue.poll() returns null if it timeouts.
   1819                 fail("Did not receive callback after " + timeoutMs + "ms");
   1820             }
   1821             return cb;
   1822         }
   1823 
   1824         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
   1825             final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
   1826             CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
   1827             CallbackInfo actual = nextCallback(timeoutMs);
   1828             assertEquals("Unexpected callback:", expected, actual);
   1829 
   1830             if (state == CallbackState.LOSING) {
   1831                 String msg = String.format(
   1832                         "Invalid linger time value %d, must be between %d and %d",
   1833                         actual.arg, 0, mService.mLingerDelayMs);
   1834                 int maxMsToLive = (Integer) actual.arg;
   1835                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
   1836             }
   1837 
   1838             return actual;
   1839         }
   1840 
   1841         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
   1842             return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
   1843         }
   1844 
   1845         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
   1846             return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
   1847         }
   1848 
   1849         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
   1850             int timeLeft = timeoutMs;
   1851             while (timeLeft > 0) {
   1852                 long start = SystemClock.elapsedRealtime();
   1853                 CallbackInfo info = nextCallback(timeLeft);
   1854                 if (fn.test(info)) {
   1855                     return info;
   1856                 }
   1857                 timeLeft -= (SystemClock.elapsedRealtime() - start);
   1858             }
   1859             fail("Did not receive expected callback after " + timeoutMs + "ms");
   1860             return null;
   1861         }
   1862 
   1863         // Expects onAvailable and the callbacks that follow it. These are:
   1864         // - onSuspended, iff the network was suspended when the callbacks fire.
   1865         // - onCapabilitiesChanged.
   1866         // - onLinkPropertiesChanged.
   1867         // - onBlockedStatusChanged.
   1868         //
   1869         // @param agent the network to expect the callbacks on.
   1870         // @param expectSuspended whether to expect a SUSPENDED callback.
   1871         // @param expectValidated the expected value of the VALIDATED capability in the
   1872         //        onCapabilitiesChanged callback.
   1873         // @param timeoutMs how long to wait for the callbacks.
   1874         void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
   1875                 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
   1876             expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
   1877             if (expectSuspended) {
   1878                 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
   1879             }
   1880             if (expectValidated) {
   1881                 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
   1882             } else {
   1883                 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
   1884             }
   1885             expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
   1886             expectBlockedStatusCallback(expectBlocked, agent);
   1887         }
   1888 
   1889         // Expects the available callbacks (validated), plus onSuspended.
   1890         void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
   1891             expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
   1892         }
   1893 
   1894         void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
   1895             expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
   1896         }
   1897 
   1898         void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
   1899             expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
   1900         }
   1901 
   1902         void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
   1903             expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
   1904         }
   1905 
   1906         void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
   1907             expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
   1908         }
   1909 
   1910         // Expects the available callbacks (where the onCapabilitiesChanged must contain the
   1911         // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
   1912         // one we just sent.
   1913         // TODO: this is likely a bug. Fix it and remove this method.
   1914         void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
   1915             expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
   1916             NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
   1917             expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
   1918             // Implicitly check the network is allowed to use.
   1919             // TODO: should we need to consider if network is in blocked status in this case?
   1920             expectBlockedStatusCallback(false, agent);
   1921             NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
   1922             assertEquals(nc1, nc2);
   1923         }
   1924 
   1925         // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
   1926         // then expects another onCapabilitiesChanged that has the validated bit set. This is used
   1927         // when a network connects and satisfies a callback, and then immediately validates.
   1928         void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
   1929             expectAvailableCallbacksUnvalidated(agent);
   1930             expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
   1931         }
   1932 
   1933         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
   1934             return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
   1935         }
   1936 
   1937         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
   1938                 int timeoutMs) {
   1939             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
   1940             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
   1941             assertTrue(nc.hasCapability(capability));
   1942             return nc;
   1943         }
   1944 
   1945         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
   1946             return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
   1947         }
   1948 
   1949         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
   1950                 int timeoutMs) {
   1951             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
   1952             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
   1953             assertFalse(nc.hasCapability(capability));
   1954             return nc;
   1955         }
   1956 
   1957         void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
   1958             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
   1959             assertTrue("Received capabilities don't match expectations : " + cbi.arg,
   1960                     fn.test((NetworkCapabilities) cbi.arg));
   1961         }
   1962 
   1963         void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
   1964             CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
   1965             assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
   1966                     fn.test((LinkProperties) cbi.arg));
   1967         }
   1968 
   1969         void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
   1970             CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
   1971             boolean actualBlocked = (boolean) cbi.arg;
   1972             assertEquals(expectBlocked, actualBlocked);
   1973         }
   1974 
   1975         void assertNoCallback() {
   1976             waitForIdle();
   1977             CallbackInfo c = mCallbacks.peek();
   1978             assertNull("Unexpected callback: " + c, c);
   1979         }
   1980     }
   1981 
   1982     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
   1983     // only be declared in a static or top level type".
   1984     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
   1985         for (TestNetworkCallback c : callbacks) {
   1986             c.assertNoCallback();
   1987         }
   1988     }
   1989 
   1990     @Test
   1991     public void testStateChangeNetworkCallbacks() throws Exception {
   1992         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
   1993         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
   1994         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   1995         final NetworkRequest genericRequest = new NetworkRequest.Builder()
   1996                 .clearCapabilities().build();
   1997         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
   1998                 .addTransportType(TRANSPORT_WIFI).build();
   1999         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2000                 .addTransportType(TRANSPORT_CELLULAR).build();
   2001         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
   2002         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
   2003         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   2004 
   2005         // Test unvalidated networks
   2006         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   2007         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2008         mCellNetworkAgent.connect(false);
   2009         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2010         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2011         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2012         waitFor(cv);
   2013         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2014 
   2015         // This should not trigger spurious onAvailable() callbacks, b/21762680.
   2016         mCellNetworkAgent.adjustScore(-1);
   2017         waitForIdle();
   2018         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2019         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2020 
   2021         cv = waitForConnectivityBroadcasts(2);
   2022         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2023         mWiFiNetworkAgent.connect(false);
   2024         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2025         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2026         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2027         waitFor(cv);
   2028         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2029 
   2030         cv = waitForConnectivityBroadcasts(2);
   2031         mWiFiNetworkAgent.disconnect();
   2032         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2033         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2034         cellNetworkCallback.assertNoCallback();
   2035         waitFor(cv);
   2036         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2037 
   2038         cv = waitForConnectivityBroadcasts(1);
   2039         mCellNetworkAgent.disconnect();
   2040         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2041         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2042         waitFor(cv);
   2043         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2044 
   2045         // Test validated networks
   2046         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2047         mCellNetworkAgent.connect(true);
   2048         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2049         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2050         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2051         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2052 
   2053         // This should not trigger spurious onAvailable() callbacks, b/21762680.
   2054         mCellNetworkAgent.adjustScore(-1);
   2055         waitForIdle();
   2056         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2057         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2058 
   2059         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2060         mWiFiNetworkAgent.connect(true);
   2061         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2062         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2063         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2064         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   2065         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2066         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2067         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2068 
   2069         mWiFiNetworkAgent.disconnect();
   2070         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2071         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2072         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2073 
   2074         mCellNetworkAgent.disconnect();
   2075         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2076         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2077         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   2078     }
   2079 
   2080     @Test
   2081     public void testMultipleLingering() {
   2082         // This test would be flaky with the default 120ms timer: that is short enough that
   2083         // lingered networks are torn down before assertions can be run. We don't want to mock the
   2084         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
   2085         // in detecting races.
   2086         mService.mLingerDelayMs = 300;
   2087 
   2088         NetworkRequest request = new NetworkRequest.Builder()
   2089                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
   2090                 .build();
   2091         TestNetworkCallback callback = new TestNetworkCallback();
   2092         mCm.registerNetworkCallback(request, callback);
   2093 
   2094         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   2095         mCm.registerDefaultNetworkCallback(defaultCallback);
   2096 
   2097         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2098         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2099         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   2100 
   2101         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   2102         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   2103         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   2104 
   2105         mCellNetworkAgent.connect(true);
   2106         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2107         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2108         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2109         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2110 
   2111         mWiFiNetworkAgent.connect(true);
   2112         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
   2113         // We then get LOSING when wifi validates and cell is outscored.
   2114         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2115         // TODO: Investigate sending validated before losing.
   2116         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2117         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2118         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2119         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2120         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2121 
   2122         mEthernetNetworkAgent.connect(true);
   2123         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
   2124         // TODO: Investigate sending validated before losing.
   2125         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
   2126         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
   2127         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
   2128         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2129         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2130 
   2131         mEthernetNetworkAgent.disconnect();
   2132         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2133         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2134         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   2135         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2136 
   2137         for (int i = 0; i < 4; i++) {
   2138             MockNetworkAgent oldNetwork, newNetwork;
   2139             if (i % 2 == 0) {
   2140                 mWiFiNetworkAgent.adjustScore(-15);
   2141                 oldNetwork = mWiFiNetworkAgent;
   2142                 newNetwork = mCellNetworkAgent;
   2143             } else {
   2144                 mWiFiNetworkAgent.adjustScore(15);
   2145                 oldNetwork = mCellNetworkAgent;
   2146                 newNetwork = mWiFiNetworkAgent;
   2147 
   2148             }
   2149             callback.expectCallback(CallbackState.LOSING, oldNetwork);
   2150             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
   2151             // longer lingering?
   2152             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
   2153             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
   2154         }
   2155         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2156 
   2157         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
   2158         // if the network is still up.
   2159         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   2160         // We expect a notification about the capabilities change, and nothing else.
   2161         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
   2162         defaultCallback.assertNoCallback();
   2163         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2164         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2165 
   2166         // Wifi no longer satisfies our listen, which is for an unmetered network.
   2167         // But because its score is 55, it's still up (and the default network).
   2168         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2169 
   2170         // Disconnect our test networks.
   2171         mWiFiNetworkAgent.disconnect();
   2172         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2173         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2174         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2175         mCellNetworkAgent.disconnect();
   2176         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2177         waitForIdle();
   2178         assertEquals(null, mCm.getActiveNetwork());
   2179 
   2180         mCm.unregisterNetworkCallback(callback);
   2181         waitForIdle();
   2182 
   2183         // Check that a network is only lingered or torn down if it would not satisfy a request even
   2184         // if it validated.
   2185         request = new NetworkRequest.Builder().clearCapabilities().build();
   2186         callback = new TestNetworkCallback();
   2187 
   2188         mCm.registerNetworkCallback(request, callback);
   2189 
   2190         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2191         mCellNetworkAgent.connect(false);   // Score: 10
   2192         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2193         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2194         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2195         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2196 
   2197         // Bring up wifi with a score of 20.
   2198         // Cell stays up because it would satisfy the default request if it validated.
   2199         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2200         mWiFiNetworkAgent.connect(false);   // Score: 20
   2201         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2202         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2203         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2204         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2205 
   2206         mWiFiNetworkAgent.disconnect();
   2207         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2208         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2209         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2210         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2211         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2212 
   2213         // Bring up wifi with a score of 70.
   2214         // Cell is lingered because it would not satisfy any request, even if it validated.
   2215         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2216         mWiFiNetworkAgent.adjustScore(50);
   2217         mWiFiNetworkAgent.connect(false);   // Score: 70
   2218         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2219         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2220         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2221         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2222         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2223 
   2224         // Tear down wifi.
   2225         mWiFiNetworkAgent.disconnect();
   2226         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2227         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2228         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2229         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2230         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2231 
   2232         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
   2233         // it's arguably correct to linger it, since it was the default network before it validated.
   2234         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2235         mWiFiNetworkAgent.connect(true);
   2236         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2237         // TODO: Investigate sending validated before losing.
   2238         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2239         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2240         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   2241         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2242         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2243 
   2244         mWiFiNetworkAgent.disconnect();
   2245         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2246         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2247         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2248         mCellNetworkAgent.disconnect();
   2249         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2250         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2251         waitForIdle();
   2252         assertEquals(null, mCm.getActiveNetwork());
   2253 
   2254         // If a network is lingering, and we add and remove a request from it, resume lingering.
   2255         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2256         mCellNetworkAgent.connect(true);
   2257         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2258         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2259         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2260         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2261         mWiFiNetworkAgent.connect(true);
   2262         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2263         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2264         // TODO: Investigate sending validated before losing.
   2265         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2266         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2267         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2268 
   2269         NetworkRequest cellRequest = new NetworkRequest.Builder()
   2270                 .addTransportType(TRANSPORT_CELLULAR).build();
   2271         NetworkCallback noopCallback = new NetworkCallback();
   2272         mCm.requestNetwork(cellRequest, noopCallback);
   2273         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
   2274         // lingering?
   2275         mCm.unregisterNetworkCallback(noopCallback);
   2276         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2277 
   2278         // Similar to the above: lingering can start even after the lingered request is removed.
   2279         // Disconnect wifi and switch to cell.
   2280         mWiFiNetworkAgent.disconnect();
   2281         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2282         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2283         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2284         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2285 
   2286         // Cell is now the default network. Pin it with a cell-specific request.
   2287         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
   2288         mCm.requestNetwork(cellRequest, noopCallback);
   2289 
   2290         // Now connect wifi, and expect it to become the default network.
   2291         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2292         mWiFiNetworkAgent.connect(true);
   2293         callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   2294         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2295         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2296         // The default request is lingering on cell, but nothing happens to cell, and we send no
   2297         // callbacks for it, because it's kept up by cellRequest.
   2298         callback.assertNoCallback();
   2299         // Now unregister cellRequest and expect cell to start lingering.
   2300         mCm.unregisterNetworkCallback(noopCallback);
   2301         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2302 
   2303         // Let linger run its course.
   2304         callback.assertNoCallback();
   2305         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
   2306         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
   2307 
   2308         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
   2309         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
   2310         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
   2311         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   2312         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   2313         mEthernetNetworkAgent.connect(true);
   2314         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
   2315         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
   2316         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
   2317         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
   2318         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
   2319         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2320 
   2321         // Let linger run its course.
   2322         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
   2323 
   2324         // Clean up.
   2325         mEthernetNetworkAgent.disconnect();
   2326         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2327         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2328         trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2329 
   2330         mCm.unregisterNetworkCallback(callback);
   2331         mCm.unregisterNetworkCallback(defaultCallback);
   2332         mCm.unregisterNetworkCallback(trackDefaultCallback);
   2333     }
   2334 
   2335     @Test
   2336     public void testNetworkGoesIntoBackgroundAfterLinger() {
   2337         setAlwaysOnNetworks(true);
   2338         NetworkRequest request = new NetworkRequest.Builder()
   2339                 .clearCapabilities()
   2340                 .build();
   2341         TestNetworkCallback callback = new TestNetworkCallback();
   2342         mCm.registerNetworkCallback(request, callback);
   2343 
   2344         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   2345         mCm.registerDefaultNetworkCallback(defaultCallback);
   2346 
   2347         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2348         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2349 
   2350         mCellNetworkAgent.connect(true);
   2351         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2352         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2353 
   2354         // Wifi comes up and cell lingers.
   2355         mWiFiNetworkAgent.connect(true);
   2356         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2357         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2358         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2359         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2360 
   2361         // File a request for cellular, then release it.
   2362         NetworkRequest cellRequest = new NetworkRequest.Builder()
   2363                 .addTransportType(TRANSPORT_CELLULAR).build();
   2364         NetworkCallback noopCallback = new NetworkCallback();
   2365         mCm.requestNetwork(cellRequest, noopCallback);
   2366         mCm.unregisterNetworkCallback(noopCallback);
   2367         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2368 
   2369         // Let linger run its course.
   2370         callback.assertNoCallback();
   2371         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
   2372         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
   2373                 lingerTimeoutMs);
   2374 
   2375         // Clean up.
   2376         mCm.unregisterNetworkCallback(defaultCallback);
   2377         mCm.unregisterNetworkCallback(callback);
   2378     }
   2379 
   2380     @Test
   2381     public void testExplicitlySelected() {
   2382         NetworkRequest request = new NetworkRequest.Builder()
   2383                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
   2384                 .build();
   2385         TestNetworkCallback callback = new TestNetworkCallback();
   2386         mCm.registerNetworkCallback(request, callback);
   2387 
   2388         // Bring up validated cell.
   2389         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2390         mCellNetworkAgent.connect(true);
   2391         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2392 
   2393         // Bring up unvalidated wifi with explicitlySelected=true.
   2394         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2395         mWiFiNetworkAgent.explicitlySelected(false);
   2396         mWiFiNetworkAgent.connect(false);
   2397         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2398 
   2399         // Cell Remains the default.
   2400         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2401 
   2402         // Lower wifi's score to below than cell, and check that it doesn't disconnect because
   2403         // it's explicitly selected.
   2404         mWiFiNetworkAgent.adjustScore(-40);
   2405         mWiFiNetworkAgent.adjustScore(40);
   2406         callback.assertNoCallback();
   2407 
   2408         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
   2409         // wifi even though it's unvalidated.
   2410         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
   2411         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2412         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2413 
   2414         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
   2415         mWiFiNetworkAgent.disconnect();
   2416         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2417         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2418         mWiFiNetworkAgent.explicitlySelected(false);
   2419         mWiFiNetworkAgent.connect(false);
   2420         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2421 
   2422         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
   2423         // network to disconnect.
   2424         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
   2425         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2426 
   2427         // Reconnect, again with explicitlySelected=true, but this time validate.
   2428         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2429         mWiFiNetworkAgent.explicitlySelected(false);
   2430         mWiFiNetworkAgent.connect(true);
   2431         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2432         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2433         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2434         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2435 
   2436         // BUG: the network will no longer linger, even though it's validated and outscored.
   2437         // TODO: fix this.
   2438         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   2439         mEthernetNetworkAgent.connect(true);
   2440         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
   2441         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2442         callback.assertNoCallback();
   2443 
   2444         // Clean up.
   2445         mWiFiNetworkAgent.disconnect();
   2446         mCellNetworkAgent.disconnect();
   2447         mEthernetNetworkAgent.disconnect();
   2448 
   2449         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2450         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2451         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2452     }
   2453 
   2454     private int[] makeIntArray(final int size, final int value) {
   2455         final int[] array = new int[size];
   2456         Arrays.fill(array, value);
   2457         return array;
   2458     }
   2459 
   2460     private void tryNetworkFactoryRequests(int capability) throws Exception {
   2461         // Verify NOT_RESTRICTED is set appropriately
   2462         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
   2463                 .build().networkCapabilities;
   2464         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
   2465                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
   2466                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
   2467                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
   2468             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
   2469         } else {
   2470             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
   2471         }
   2472 
   2473         NetworkCapabilities filter = new NetworkCapabilities();
   2474         filter.addCapability(capability);
   2475         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
   2476         handlerThread.start();
   2477         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   2478                 mServiceContext, "testFactory", filter);
   2479         testFactory.setScoreFilter(40);
   2480         ConditionVariable cv = testFactory.getNetworkStartedCV();
   2481         testFactory.expectAddRequestsWithScores(0);
   2482         testFactory.register();
   2483         testFactory.waitForNetworkRequests(1);
   2484         int expectedRequestCount = 1;
   2485         NetworkCallback networkCallback = null;
   2486         // For non-INTERNET capabilities we cannot rely on the default request being present, so
   2487         // add one.
   2488         if (capability != NET_CAPABILITY_INTERNET) {
   2489             assertFalse(testFactory.getMyStartRequested());
   2490             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
   2491             networkCallback = new NetworkCallback();
   2492             testFactory.expectAddRequestsWithScores(0);  // New request
   2493             mCm.requestNetwork(request, networkCallback);
   2494             expectedRequestCount++;
   2495             testFactory.waitForNetworkRequests(expectedRequestCount);
   2496         }
   2497         waitFor(cv);
   2498         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   2499         assertTrue(testFactory.getMyStartRequested());
   2500 
   2501         // Now bring in a higher scored network.
   2502         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2503         // Rather than create a validated network which complicates things by registering it's
   2504         // own NetworkRequest during startup, just bump up the score to cancel out the
   2505         // unvalidated penalty.
   2506         testAgent.adjustScore(40);
   2507         cv = testFactory.getNetworkStoppedCV();
   2508 
   2509         // When testAgent connects, ConnectivityService will re-send us all current requests with
   2510         // the new score. There are expectedRequestCount such requests, and we must wait for all of
   2511         // them.
   2512         testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
   2513         testAgent.connect(false);
   2514         testAgent.addCapability(capability);
   2515         waitFor(cv);
   2516         testFactory.waitForNetworkRequests(expectedRequestCount);
   2517         assertFalse(testFactory.getMyStartRequested());
   2518 
   2519         // Bring in a bunch of requests.
   2520         testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
   2521         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   2522         ConnectivityManager.NetworkCallback[] networkCallbacks =
   2523                 new ConnectivityManager.NetworkCallback[10];
   2524         for (int i = 0; i< networkCallbacks.length; i++) {
   2525             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
   2526             NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2527             builder.addCapability(capability);
   2528             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
   2529         }
   2530         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
   2531         assertFalse(testFactory.getMyStartRequested());
   2532 
   2533         // Remove the requests.
   2534         testFactory.expectRemoveRequests(10);
   2535         for (int i = 0; i < networkCallbacks.length; i++) {
   2536             mCm.unregisterNetworkCallback(networkCallbacks[i]);
   2537         }
   2538         testFactory.waitForNetworkRequests(expectedRequestCount);
   2539         assertFalse(testFactory.getMyStartRequested());
   2540 
   2541         // Drop the higher scored network.
   2542         cv = testFactory.getNetworkStartedCV();
   2543         // With the default network disconnecting, the requests are sent with score 0 to factories.
   2544         testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
   2545         testAgent.disconnect();
   2546         waitFor(cv);
   2547         testFactory.waitForNetworkRequests(expectedRequestCount);
   2548         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   2549         assertTrue(testFactory.getMyStartRequested());
   2550 
   2551         testFactory.unregister();
   2552         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
   2553         handlerThread.quit();
   2554     }
   2555 
   2556     @Test
   2557     public void testNetworkFactoryRequests() throws Exception {
   2558         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
   2559         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
   2560         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
   2561         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
   2562         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
   2563         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
   2564         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
   2565         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
   2566         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
   2567         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
   2568         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
   2569         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
   2570         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
   2571         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
   2572         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
   2573         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
   2574     }
   2575 
   2576     @Test
   2577     public void testNoMutableNetworkRequests() throws Exception {
   2578         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
   2579         NetworkRequest request1 = new NetworkRequest.Builder()
   2580                 .addCapability(NET_CAPABILITY_VALIDATED)
   2581                 .build();
   2582         NetworkRequest request2 = new NetworkRequest.Builder()
   2583                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
   2584                 .build();
   2585 
   2586         Class<IllegalArgumentException> expected = IllegalArgumentException.class;
   2587         assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
   2588         assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
   2589         assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
   2590         assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
   2591     }
   2592 
   2593     @Test
   2594     public void testMMSonWiFi() throws Exception {
   2595         // Test bringing up cellular without MMS NetworkRequest gets reaped
   2596         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2597         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   2598         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
   2599         mCellNetworkAgent.connectWithoutInternet();
   2600         waitFor(cv);
   2601         waitForIdle();
   2602         assertEmpty(mCm.getAllNetworks());
   2603         verifyNoNetwork();
   2604 
   2605         // Test bringing up validated WiFi.
   2606         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2607         cv = waitForConnectivityBroadcasts(1);
   2608         mWiFiNetworkAgent.connect(true);
   2609         waitFor(cv);
   2610         verifyActiveNetwork(TRANSPORT_WIFI);
   2611 
   2612         // Register MMS NetworkRequest
   2613         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2614         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
   2615         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   2616         mCm.requestNetwork(builder.build(), networkCallback);
   2617 
   2618         // Test bringing up unvalidated cellular with MMS
   2619         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2620         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   2621         mCellNetworkAgent.connectWithoutInternet();
   2622         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2623         verifyActiveNetwork(TRANSPORT_WIFI);
   2624 
   2625         // Test releasing NetworkRequest disconnects cellular with MMS
   2626         cv = mCellNetworkAgent.getDisconnectedCV();
   2627         mCm.unregisterNetworkCallback(networkCallback);
   2628         waitFor(cv);
   2629         verifyActiveNetwork(TRANSPORT_WIFI);
   2630     }
   2631 
   2632     @Test
   2633     public void testMMSonCell() throws Exception {
   2634         // Test bringing up cellular without MMS
   2635         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2636         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   2637         mCellNetworkAgent.connect(false);
   2638         waitFor(cv);
   2639         verifyActiveNetwork(TRANSPORT_CELLULAR);
   2640 
   2641         // Register MMS NetworkRequest
   2642         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2643         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
   2644         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   2645         mCm.requestNetwork(builder.build(), networkCallback);
   2646 
   2647         // Test bringing up MMS cellular network
   2648         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2649         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   2650         mmsNetworkAgent.connectWithoutInternet();
   2651         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
   2652         verifyActiveNetwork(TRANSPORT_CELLULAR);
   2653 
   2654         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
   2655         cv = mmsNetworkAgent.getDisconnectedCV();
   2656         mCm.unregisterNetworkCallback(networkCallback);
   2657         waitFor(cv);
   2658         verifyActiveNetwork(TRANSPORT_CELLULAR);
   2659     }
   2660 
   2661     @Test
   2662     public void testPartialConnectivity() {
   2663         // Register network callback.
   2664         NetworkRequest request = new NetworkRequest.Builder()
   2665                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
   2666                 .build();
   2667         TestNetworkCallback callback = new TestNetworkCallback();
   2668         mCm.registerNetworkCallback(request, callback);
   2669 
   2670         // Bring up validated mobile data.
   2671         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2672         mCellNetworkAgent.connect(true);
   2673         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2674 
   2675         // Bring up wifi with partial connectivity.
   2676         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2677         mWiFiNetworkAgent.connectWithPartialConnectivity();
   2678         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2679         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
   2680 
   2681         // Mobile data should be the default network.
   2682         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2683         callback.assertNoCallback();
   2684 
   2685         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
   2686         // probe.
   2687         mWiFiNetworkAgent.setNetworkPartialValid();
   2688         // If the user chooses yes to use this partial connectivity wifi, switch the default
   2689         // network to wifi and check if wifi becomes valid or not.
   2690         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
   2691                 false /* always */);
   2692         // If user accepts partial connectivity network,
   2693         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
   2694         waitForIdle();
   2695         try {
   2696             verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
   2697         } catch (RemoteException e) {
   2698             fail(e.getMessage());
   2699         }
   2700         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
   2701         // validated.
   2702         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   2703         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2704         NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
   2705                 mWiFiNetworkAgent);
   2706         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
   2707         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2708 
   2709         // Disconnect and reconnect wifi with partial connectivity again.
   2710         mWiFiNetworkAgent.disconnect();
   2711         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2712         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2713         mWiFiNetworkAgent.connectWithPartialConnectivity();
   2714         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2715         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
   2716 
   2717         // Mobile data should be the default network.
   2718         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2719 
   2720         // If the user chooses no, disconnect wifi immediately.
   2721         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
   2722                 false /* always */);
   2723         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2724 
   2725         // If user accepted partial connectivity before, and device reconnects to that network
   2726         // again, but now the network has full connectivity. The network shouldn't contain
   2727         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
   2728         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2729         // acceptUnvalidated is also used as setting for accepting partial networks.
   2730         mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
   2731         mWiFiNetworkAgent.connect(true);
   2732         // If user accepted partial connectivity network before,
   2733         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
   2734         // ConnectivityService#updateNetworkInfo().
   2735         waitForIdle();
   2736         try {
   2737             verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
   2738         } catch (RemoteException e) {
   2739             fail(e.getMessage());
   2740         }
   2741         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2742         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2743         nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2744         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
   2745         // Wifi should be the default network.
   2746         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2747         mWiFiNetworkAgent.disconnect();
   2748         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2749 
   2750         // If user accepted partial connectivity before, and now the device reconnects to the
   2751         // partial connectivity network. The network should be valid and contain
   2752         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
   2753         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2754         mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
   2755         // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
   2756         // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
   2757         // to ConnectivityService first then send VALID. Once NetworkMonitor support
   2758         // multi-testResult, this test case also need to be changed to meet the new design.
   2759         mWiFiNetworkAgent.connectWithPartialConnectivity();
   2760         // If user accepted partial connectivity network before,
   2761         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
   2762         // ConnectivityService#updateNetworkInfo().
   2763         waitForIdle();
   2764         try {
   2765             verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
   2766         } catch (RemoteException e) {
   2767             fail(e.getMessage());
   2768         }
   2769         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2770         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2771         // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
   2772         // NetworkMonitor detects partial connectivity
   2773         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2774         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
   2775         mWiFiNetworkAgent.setNetworkValid();
   2776         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
   2777         // validated.
   2778         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   2779         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2780         mWiFiNetworkAgent.disconnect();
   2781         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2782     }
   2783 
   2784     @Test
   2785     public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
   2786         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2787         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2788                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2789         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2790 
   2791         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2792         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2793                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2794         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2795 
   2796         // Bring up a network with a captive portal.
   2797         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   2798         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2799         String redirectUrl = "http://android.com/path";
   2800         mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
   2801         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2802         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
   2803 
   2804         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
   2805         mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
   2806         verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
   2807                 .launchCaptivePortalApp();
   2808 
   2809         // Report that the captive portal is dismissed with partial connectivity, and check that
   2810         // callbacks are fired.
   2811         mWiFiNetworkAgent.setNetworkPartial();
   2812         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   2813         waitForIdle();
   2814         captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
   2815                 mWiFiNetworkAgent);
   2816 
   2817         // Report partial connectivity is accepted.
   2818         mWiFiNetworkAgent.setNetworkPartialValid();
   2819         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
   2820                 false /* always */);
   2821         waitForIdle();
   2822         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   2823         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2824         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   2825         NetworkCapabilities nc =
   2826                 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
   2827                 mWiFiNetworkAgent);
   2828 
   2829         mCm.unregisterNetworkCallback(captivePortalCallback);
   2830         mCm.unregisterNetworkCallback(validatedCallback);
   2831     }
   2832 
   2833     @Test
   2834     public void testCaptivePortal() {
   2835         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2836         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2837                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2838         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2839 
   2840         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2841         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2842                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2843         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2844 
   2845         // Bring up a network with a captive portal.
   2846         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   2847         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2848         String firstRedirectUrl = "http://example.com/firstPath";
   2849         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
   2850         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2851         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
   2852 
   2853         // Take down network.
   2854         // Expect onLost callback.
   2855         mWiFiNetworkAgent.disconnect();
   2856         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2857 
   2858         // Bring up a network with a captive portal.
   2859         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   2860         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2861         String secondRedirectUrl = "http://example.com/secondPath";
   2862         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
   2863         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2864         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
   2865 
   2866         // Make captive portal disappear then revalidate.
   2867         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
   2868         mWiFiNetworkAgent.setNetworkValid();
   2869         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   2870         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2871 
   2872         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
   2873         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2874         // Expect no notification to be shown when captive portal disappears by itself
   2875         verify(mNotificationManager, never()).notifyAsUser(
   2876                 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
   2877 
   2878         // Break network connectivity.
   2879         // Expect NET_CAPABILITY_VALIDATED onLost callback.
   2880         mWiFiNetworkAgent.setNetworkInvalid();
   2881         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
   2882         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2883     }
   2884 
   2885     @Test
   2886     public void testCaptivePortalApp() throws RemoteException {
   2887         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2888         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2889                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2890         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2891 
   2892         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2893         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2894                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2895         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2896 
   2897         // Bring up wifi.
   2898         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2899         mWiFiNetworkAgent.connect(true);
   2900         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2901         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
   2902 
   2903         // Check that calling startCaptivePortalApp does nothing.
   2904         final int fastTimeoutMs = 100;
   2905         mCm.startCaptivePortalApp(wifiNetwork);
   2906         waitForIdle();
   2907         verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
   2908         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
   2909 
   2910         // Turn into a captive portal.
   2911         mWiFiNetworkAgent.setNetworkPortal("http://example.com");
   2912         mCm.reportNetworkConnectivity(wifiNetwork, false);
   2913         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2914         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2915 
   2916         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
   2917         mCm.startCaptivePortalApp(wifiNetwork);
   2918         waitForIdle();
   2919         verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
   2920 
   2921         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
   2922         final Bundle testBundle = new Bundle();
   2923         final String testKey = "testkey";
   2924         final String testValue = "testvalue";
   2925         testBundle.putString(testKey, testValue);
   2926         mCm.startCaptivePortalApp(wifiNetwork, testBundle);
   2927         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
   2928         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
   2929         assertEquals(testValue, signInIntent.getStringExtra(testKey));
   2930 
   2931         // Report that the captive portal is dismissed, and check that callbacks are fired
   2932         mWiFiNetworkAgent.setNetworkValid();
   2933         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
   2934         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   2935         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2936         verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
   2937                 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
   2938 
   2939         mCm.unregisterNetworkCallback(validatedCallback);
   2940         mCm.unregisterNetworkCallback(captivePortalCallback);
   2941     }
   2942 
   2943     @Test
   2944     public void testAvoidOrIgnoreCaptivePortals() {
   2945         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2946         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2947                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2948         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2949 
   2950         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2951         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2952                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2953         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2954 
   2955         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
   2956         // Bring up a network with a captive portal.
   2957         // Expect it to fail to connect and not result in any callbacks.
   2958         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2959         String firstRedirectUrl = "http://example.com/firstPath";
   2960 
   2961         ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
   2962         ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
   2963         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
   2964         waitFor(disconnectCv);
   2965         waitFor(avoidCv);
   2966 
   2967         assertNoCallbacks(captivePortalCallback, validatedCallback);
   2968     }
   2969 
   2970     private NetworkRequest.Builder newWifiRequestBuilder() {
   2971         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
   2972     }
   2973 
   2974     /**
   2975      * Verify request matching behavior with network specifiers.
   2976      *
   2977      * Note: this test is somewhat problematic since it involves removing capabilities from
   2978      * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
   2979      * as a WTF bug in
   2980      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
   2981      * does work.
   2982      */
   2983     @Test
   2984     public void testNetworkSpecifier() {
   2985         // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
   2986         class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
   2987                 Parcelable {
   2988             @Override
   2989             public boolean satisfiedBy(NetworkSpecifier other) {
   2990                 return true;
   2991             }
   2992 
   2993             @Override
   2994             public int describeContents() {
   2995                 return 0;
   2996             }
   2997 
   2998             @Override
   2999             public void writeToParcel(Parcel dest, int flags) {}
   3000 
   3001             @Override
   3002             public NetworkSpecifier redact() {
   3003                 return null;
   3004             }
   3005         }
   3006 
   3007         // A network specifier that matches either another LocalNetworkSpecifier with the same
   3008         // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
   3009         class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
   3010             private String mString;
   3011 
   3012             LocalStringNetworkSpecifier(String string) {
   3013                 mString = string;
   3014             }
   3015 
   3016             @Override
   3017             public boolean satisfiedBy(NetworkSpecifier other) {
   3018                 if (other instanceof LocalStringNetworkSpecifier) {
   3019                     return TextUtils.equals(mString,
   3020                             ((LocalStringNetworkSpecifier) other).mString);
   3021                 }
   3022                 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
   3023                 return false;
   3024             }
   3025 
   3026             @Override
   3027             public int describeContents() {
   3028                 return 0;
   3029             }
   3030             @Override
   3031             public void writeToParcel(Parcel dest, int flags) {}
   3032         }
   3033 
   3034 
   3035         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
   3036         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
   3037         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
   3038         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
   3039             (NetworkSpecifier) null).build();
   3040         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
   3041                 new LocalStringNetworkSpecifier("foo")).build();
   3042         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
   3043                 new LocalStringNetworkSpecifier("bar")).build();
   3044 
   3045         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
   3046         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
   3047         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
   3048         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
   3049         TestNetworkCallback cFoo = new TestNetworkCallback();
   3050         TestNetworkCallback cBar = new TestNetworkCallback();
   3051         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
   3052                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
   3053 
   3054         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
   3055         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
   3056         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
   3057         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
   3058         mCm.registerNetworkCallback(rFoo, cFoo);
   3059         mCm.registerNetworkCallback(rBar, cBar);
   3060 
   3061         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
   3062         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
   3063 
   3064         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3065         mWiFiNetworkAgent.connect(false);
   3066         cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3067         cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3068         cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3069         cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3070         assertNoCallbacks(cFoo, cBar);
   3071 
   3072         mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
   3073         cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3074         for (TestNetworkCallback c: emptyCallbacks) {
   3075             c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
   3076                     mWiFiNetworkAgent);
   3077         }
   3078         cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
   3079                 mWiFiNetworkAgent);
   3080         assertEquals(nsFoo,
   3081                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
   3082         cFoo.assertNoCallback();
   3083 
   3084         mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
   3085         cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3086         cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3087         for (TestNetworkCallback c: emptyCallbacks) {
   3088             c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
   3089                     mWiFiNetworkAgent);
   3090         }
   3091         cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
   3092                 mWiFiNetworkAgent);
   3093         assertEquals(nsBar,
   3094                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
   3095         cBar.assertNoCallback();
   3096 
   3097         mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
   3098         cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3099         for (TestNetworkCallback c : emptyCallbacks) {
   3100             c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
   3101                     mWiFiNetworkAgent);
   3102         }
   3103         cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
   3104                 mWiFiNetworkAgent);
   3105         cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
   3106                 mWiFiNetworkAgent);
   3107         assertNull(
   3108                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
   3109         cFoo.assertNoCallback();
   3110         cBar.assertNoCallback();
   3111 
   3112         mWiFiNetworkAgent.setNetworkSpecifier(null);
   3113         cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3114         cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3115         for (TestNetworkCallback c: emptyCallbacks) {
   3116             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
   3117         }
   3118 
   3119         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
   3120     }
   3121 
   3122     @Test
   3123     public void testInvalidNetworkSpecifier() {
   3124         try {
   3125             NetworkRequest.Builder builder = new NetworkRequest.Builder();
   3126             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
   3127             fail("NetworkRequest builder with MatchAllNetworkSpecifier");
   3128         } catch (IllegalArgumentException expected) {
   3129             // expected
   3130         }
   3131 
   3132         try {
   3133             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
   3134             networkCapabilities.addTransportType(TRANSPORT_WIFI)
   3135                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
   3136             mService.requestNetwork(networkCapabilities, null, 0, null,
   3137                     ConnectivityManager.TYPE_WIFI);
   3138             fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
   3139         } catch (IllegalArgumentException expected) {
   3140             // expected
   3141         }
   3142 
   3143         class NonParcelableSpecifier extends NetworkSpecifier {
   3144             public boolean satisfiedBy(NetworkSpecifier other) { return false; }
   3145         };
   3146         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
   3147             @Override public int describeContents() { return 0; }
   3148             @Override public void writeToParcel(Parcel p, int flags) {}
   3149         }
   3150         NetworkRequest.Builder builder;
   3151 
   3152         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
   3153         try {
   3154             builder.setNetworkSpecifier(new NonParcelableSpecifier());
   3155             Parcel parcelW = Parcel.obtain();
   3156             builder.build().writeToParcel(parcelW, 0);
   3157             fail("Parceling a non-parcelable specifier did not throw an exception");
   3158         } catch (Exception e) {
   3159             // expected
   3160         }
   3161 
   3162         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
   3163         builder.setNetworkSpecifier(new ParcelableSpecifier());
   3164         NetworkRequest nr = builder.build();
   3165         assertNotNull(nr);
   3166 
   3167         try {
   3168             Parcel parcelW = Parcel.obtain();
   3169             nr.writeToParcel(parcelW, 0);
   3170             byte[] bytes = parcelW.marshall();
   3171             parcelW.recycle();
   3172 
   3173             Parcel parcelR = Parcel.obtain();
   3174             parcelR.unmarshall(bytes, 0, bytes.length);
   3175             parcelR.setDataPosition(0);
   3176             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
   3177             fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
   3178         } catch (Exception e) {
   3179             // expected
   3180         }
   3181     }
   3182 
   3183     @Test
   3184     public void testNetworkSpecifierUidSpoofSecurityException() {
   3185         class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
   3186             @Override
   3187             public boolean satisfiedBy(NetworkSpecifier other) {
   3188                 return true;
   3189             }
   3190 
   3191             @Override
   3192             public void assertValidFromUid(int requestorUid) {
   3193                 throw new SecurityException("failure");
   3194             }
   3195 
   3196             @Override
   3197             public int describeContents() { return 0; }
   3198             @Override
   3199             public void writeToParcel(Parcel dest, int flags) {}
   3200         }
   3201 
   3202         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3203         mWiFiNetworkAgent.connect(false);
   3204 
   3205         UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
   3206         NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
   3207                 networkSpecifier).build();
   3208         TestNetworkCallback networkCallback = new TestNetworkCallback();
   3209         try {
   3210             mCm.requestNetwork(networkRequest, networkCallback);
   3211             fail("Network request with spoofed UID did not throw a SecurityException");
   3212         } catch (SecurityException e) {
   3213             // expected
   3214         }
   3215     }
   3216 
   3217     @Test
   3218     public void testInvalidSignalStrength() {
   3219         NetworkRequest r = new NetworkRequest.Builder()
   3220                 .addCapability(NET_CAPABILITY_INTERNET)
   3221                 .addTransportType(TRANSPORT_WIFI)
   3222                 .setSignalStrength(-75)
   3223                 .build();
   3224         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
   3225         // permission should get SecurityException.
   3226         try {
   3227             mCm.registerNetworkCallback(r, new NetworkCallback());
   3228             fail("Expected SecurityException filing a callback with signal strength");
   3229         } catch (SecurityException expected) {
   3230             // expected
   3231         }
   3232 
   3233         try {
   3234             mCm.registerNetworkCallback(r, PendingIntent.getService(
   3235                     mServiceContext, 0, new Intent(), 0));
   3236             fail("Expected SecurityException filing a callback with signal strength");
   3237         } catch (SecurityException expected) {
   3238             // expected
   3239         }
   3240 
   3241         // Requesting a Network with signal strength should get IllegalArgumentException.
   3242         try {
   3243             mCm.requestNetwork(r, new NetworkCallback());
   3244             fail("Expected IllegalArgumentException filing a request with signal strength");
   3245         } catch (IllegalArgumentException expected) {
   3246             // expected
   3247         }
   3248 
   3249         try {
   3250             mCm.requestNetwork(r, PendingIntent.getService(
   3251                     mServiceContext, 0, new Intent(), 0));
   3252             fail("Expected IllegalArgumentException filing a request with signal strength");
   3253         } catch (IllegalArgumentException expected) {
   3254             // expected
   3255         }
   3256     }
   3257 
   3258     @Test
   3259     public void testRegisterDefaultNetworkCallback() throws Exception {
   3260         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
   3261         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
   3262         defaultNetworkCallback.assertNoCallback();
   3263 
   3264         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
   3265         // whenever Wi-Fi is up. Without this, the mobile network agent is
   3266         // reaped before any other activity can take place.
   3267         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   3268         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3269                 .addTransportType(TRANSPORT_CELLULAR).build();
   3270         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   3271         cellNetworkCallback.assertNoCallback();
   3272 
   3273         // Bring up cell and expect CALLBACK_AVAILABLE.
   3274         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3275         mCellNetworkAgent.connect(true);
   3276         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3277         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3278         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   3279 
   3280         // Bring up wifi and expect CALLBACK_AVAILABLE.
   3281         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3282         mWiFiNetworkAgent.connect(true);
   3283         cellNetworkCallback.assertNoCallback();
   3284         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3285         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   3286 
   3287         // Bring down cell. Expect no default network callback, since it wasn't the default.
   3288         mCellNetworkAgent.disconnect();
   3289         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3290         defaultNetworkCallback.assertNoCallback();
   3291         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   3292 
   3293         // Bring up cell. Expect no default network callback, since it won't be the default.
   3294         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3295         mCellNetworkAgent.connect(true);
   3296         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3297         defaultNetworkCallback.assertNoCallback();
   3298         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   3299 
   3300         // Bring down wifi. Expect the default network callback to notified of LOST wifi
   3301         // followed by AVAILABLE cell.
   3302         mWiFiNetworkAgent.disconnect();
   3303         cellNetworkCallback.assertNoCallback();
   3304         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3305         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3306         mCellNetworkAgent.disconnect();
   3307         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3308         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3309         waitForIdle();
   3310         assertEquals(null, mCm.getActiveNetwork());
   3311 
   3312         final int uid = Process.myUid();
   3313         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   3314         final ArraySet<UidRange> ranges = new ArraySet<>();
   3315         ranges.add(new UidRange(uid, uid));
   3316         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   3317         mMockVpn.setUids(ranges);
   3318         vpnNetworkAgent.connect(true);
   3319         mMockVpn.connect();
   3320         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   3321         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   3322 
   3323         vpnNetworkAgent.disconnect();
   3324         defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   3325         waitForIdle();
   3326         assertEquals(null, mCm.getActiveNetwork());
   3327     }
   3328 
   3329     @Test
   3330     public void testAdditionalStateCallbacks() throws Exception {
   3331         // File a network request for mobile.
   3332         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   3333         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3334                 .addTransportType(TRANSPORT_CELLULAR).build();
   3335         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   3336 
   3337         // Bring up the mobile network.
   3338         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3339         mCellNetworkAgent.connect(true);
   3340 
   3341         // We should get onAvailable(), onCapabilitiesChanged(), and
   3342         // onLinkPropertiesChanged() in rapid succession. Additionally, we
   3343         // should get onCapabilitiesChanged() when the mobile network validates.
   3344         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3345         cellNetworkCallback.assertNoCallback();
   3346 
   3347         // Update LinkProperties.
   3348         final LinkProperties lp = new LinkProperties();
   3349         lp.setInterfaceName("foonet_data0");
   3350         mCellNetworkAgent.sendLinkProperties(lp);
   3351         // We should get onLinkPropertiesChanged().
   3352         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   3353         cellNetworkCallback.assertNoCallback();
   3354 
   3355         // Suspend the network.
   3356         mCellNetworkAgent.suspend();
   3357         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
   3358                 mCellNetworkAgent);
   3359         cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
   3360         cellNetworkCallback.assertNoCallback();
   3361 
   3362         // Register a garden variety default network request.
   3363         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
   3364         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
   3365         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
   3366         // as well as onNetworkSuspended() in rapid succession.
   3367         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
   3368         dfltNetworkCallback.assertNoCallback();
   3369         mCm.unregisterNetworkCallback(dfltNetworkCallback);
   3370 
   3371         mCellNetworkAgent.resume();
   3372         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
   3373                 mCellNetworkAgent);
   3374         cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
   3375         cellNetworkCallback.assertNoCallback();
   3376 
   3377         dfltNetworkCallback = new TestNetworkCallback();
   3378         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
   3379         // This time onNetworkSuspended should not be called.
   3380         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3381         dfltNetworkCallback.assertNoCallback();
   3382 
   3383         mCm.unregisterNetworkCallback(dfltNetworkCallback);
   3384         mCm.unregisterNetworkCallback(cellNetworkCallback);
   3385     }
   3386 
   3387     private void setCaptivePortalMode(int mode) {
   3388         ContentResolver cr = mServiceContext.getContentResolver();
   3389         Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
   3390     }
   3391 
   3392     private void setAlwaysOnNetworks(boolean enable) {
   3393         ContentResolver cr = mServiceContext.getContentResolver();
   3394         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
   3395         mService.updateAlwaysOnNetworks();
   3396         waitForIdle();
   3397     }
   3398 
   3399     private void setPrivateDnsSettings(String mode, String specifier) {
   3400         final ContentResolver cr = mServiceContext.getContentResolver();
   3401         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
   3402         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
   3403         mService.updatePrivateDnsSettings();
   3404         waitForIdle();
   3405     }
   3406 
   3407     private boolean isForegroundNetwork(MockNetworkAgent network) {
   3408         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
   3409         assertNotNull(nc);
   3410         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
   3411     }
   3412 
   3413     @Test
   3414     public void testBackgroundNetworks() throws Exception {
   3415         // Create a background request. We can't do this ourselves because ConnectivityService
   3416         // doesn't have an API for it. So just turn on mobile data always on.
   3417         setAlwaysOnNetworks(true);
   3418         final NetworkRequest request = new NetworkRequest.Builder().build();
   3419         final NetworkRequest fgRequest = new NetworkRequest.Builder()
   3420                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
   3421         final TestNetworkCallback callback = new TestNetworkCallback();
   3422         final TestNetworkCallback fgCallback = new TestNetworkCallback();
   3423         mCm.registerNetworkCallback(request, callback);
   3424         mCm.registerNetworkCallback(fgRequest, fgCallback);
   3425 
   3426         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3427         mCellNetworkAgent.connect(true);
   3428         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3429         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3430         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   3431 
   3432         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3433         mWiFiNetworkAgent.connect(true);
   3434 
   3435         // When wifi connects, cell lingers.
   3436         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3437         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   3438         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   3439         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3440         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   3441         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   3442         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   3443         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   3444 
   3445         // When lingering is complete, cell is still there but is now in the background.
   3446         waitForIdle();
   3447         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
   3448         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
   3449         // Expect a network capabilities update sans FOREGROUND.
   3450         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   3451         assertFalse(isForegroundNetwork(mCellNetworkAgent));
   3452         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   3453 
   3454         // File a cell request and check that cell comes into the foreground.
   3455         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3456                 .addTransportType(TRANSPORT_CELLULAR).build();
   3457         final TestNetworkCallback cellCallback = new TestNetworkCallback();
   3458         mCm.requestNetwork(cellRequest, cellCallback);
   3459         // NOTE: This request causes the network's capabilities to change. This
   3460         // is currently delivered before the onAvailable() callbacks.
   3461         // TODO: Fix this.
   3462         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   3463         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3464         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3465         // Expect a network capabilities update with FOREGROUND, because the most recent
   3466         // request causes its state to change.
   3467         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   3468         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   3469         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   3470 
   3471         // Release the request. The network immediately goes into the background, since it was not
   3472         // lingering.
   3473         mCm.unregisterNetworkCallback(cellCallback);
   3474         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3475         // Expect a network capabilities update sans FOREGROUND.
   3476         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   3477         assertFalse(isForegroundNetwork(mCellNetworkAgent));
   3478         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   3479 
   3480         // Disconnect wifi and check that cell is foreground again.
   3481         mWiFiNetworkAgent.disconnect();
   3482         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3483         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3484         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3485         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   3486 
   3487         mCm.unregisterNetworkCallback(callback);
   3488         mCm.unregisterNetworkCallback(fgCallback);
   3489     }
   3490 
   3491     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
   3492     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
   3493         // TODO: turn this unit test into a real benchmarking test.
   3494         // Benchmarks connecting and switching performance in the presence of a large number of
   3495         // NetworkRequests.
   3496         // 1. File NUM_REQUESTS requests.
   3497         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
   3498         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
   3499         //    and NUM_REQUESTS onAvailable callbacks to fire.
   3500         // See how long it took.
   3501         final int NUM_REQUESTS = 90;
   3502         final int REGISTER_TIME_LIMIT_MS = 200;
   3503         final int CONNECT_TIME_LIMIT_MS = 60;
   3504         final int SWITCH_TIME_LIMIT_MS = 60;
   3505         final int UNREGISTER_TIME_LIMIT_MS = 20;
   3506 
   3507         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
   3508         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
   3509         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
   3510         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
   3511 
   3512         for (int i = 0; i < NUM_REQUESTS; i++) {
   3513             callbacks[i] = new NetworkCallback() {
   3514                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
   3515                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
   3516             };
   3517         }
   3518 
   3519         assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
   3520             for (NetworkCallback cb : callbacks) {
   3521                 mCm.registerNetworkCallback(request, cb);
   3522             }
   3523         });
   3524 
   3525         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3526         // Don't request that the network validate, because otherwise connect() will block until
   3527         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
   3528         // and we won't actually measure anything.
   3529         mCellNetworkAgent.connect(false);
   3530 
   3531         long onAvailableDispatchingDuration = durationOf(() -> {
   3532             awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
   3533         });
   3534         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
   3535                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
   3536                 onAvailableDispatchingDuration));
   3537         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
   3538                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
   3539                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
   3540 
   3541         // Give wifi a high enough score that we'll linger cell when wifi comes up.
   3542         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3543         mWiFiNetworkAgent.adjustScore(40);
   3544         mWiFiNetworkAgent.connect(false);
   3545 
   3546         long onLostDispatchingDuration = durationOf(() -> {
   3547             awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
   3548         });
   3549         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
   3550                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
   3551         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
   3552                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
   3553                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
   3554 
   3555         assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
   3556             for (NetworkCallback cb : callbacks) {
   3557                 mCm.unregisterNetworkCallback(cb);
   3558             }
   3559         });
   3560     }
   3561 
   3562     private long durationOf(Runnable fn) {
   3563         long startTime = SystemClock.elapsedRealtime();
   3564         fn.run();
   3565         return SystemClock.elapsedRealtime() - startTime;
   3566     }
   3567 
   3568     private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
   3569         long timeTaken = durationOf(fn);
   3570         String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
   3571         Log.d(TAG, msg);
   3572         assertTrue(msg, timeTaken <= timeLimit);
   3573     }
   3574 
   3575     private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
   3576         try {
   3577             return l.await(timeoutMs, TimeUnit.MILLISECONDS);
   3578         } catch (InterruptedException e) {}
   3579         return false;
   3580     }
   3581 
   3582     @Test
   3583     public void testMobileDataAlwaysOn() throws Exception {
   3584         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   3585         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3586                 .addTransportType(TRANSPORT_CELLULAR).build();
   3587         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   3588 
   3589         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
   3590         handlerThread.start();
   3591         NetworkCapabilities filter = new NetworkCapabilities()
   3592                 .addTransportType(TRANSPORT_CELLULAR)
   3593                 .addCapability(NET_CAPABILITY_INTERNET);
   3594         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   3595                 mServiceContext, "testFactory", filter);
   3596         testFactory.setScoreFilter(40);
   3597 
   3598         // Register the factory and expect it to start looking for a network.
   3599         testFactory.expectAddRequestsWithScores(0);  // Score 0 as the request is not served yet.
   3600         testFactory.register();
   3601         testFactory.waitForNetworkRequests(1);
   3602         assertTrue(testFactory.getMyStartRequested());
   3603 
   3604         // Bring up wifi. The factory stops looking for a network.
   3605         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3606         // Score 60 - 40 penalty for not validated yet, then 60 when it validates
   3607         testFactory.expectAddRequestsWithScores(20, 60);
   3608         mWiFiNetworkAgent.connect(true);
   3609         testFactory.waitForRequests();
   3610         assertFalse(testFactory.getMyStartRequested());
   3611 
   3612         ContentResolver cr = mServiceContext.getContentResolver();
   3613 
   3614         // Turn on mobile data always on. The factory starts looking again.
   3615         testFactory.expectAddRequestsWithScores(0);  // Always on requests comes up with score 0
   3616         setAlwaysOnNetworks(true);
   3617         testFactory.waitForNetworkRequests(2);
   3618         assertTrue(testFactory.getMyStartRequested());
   3619 
   3620         // Bring up cell data and check that the factory stops looking.
   3621         assertLength(1, mCm.getAllNetworks());
   3622         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3623         testFactory.expectAddRequestsWithScores(10, 50);  // Unvalidated, then validated
   3624         mCellNetworkAgent.connect(true);
   3625         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3626         testFactory.waitForNetworkRequests(2);
   3627         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
   3628 
   3629         // Check that cell data stays up.
   3630         waitForIdle();
   3631         verifyActiveNetwork(TRANSPORT_WIFI);
   3632         assertLength(2, mCm.getAllNetworks());
   3633 
   3634         // Turn off mobile data always on and expect the request to disappear...
   3635         testFactory.expectRemoveRequests(1);
   3636         setAlwaysOnNetworks(false);
   3637         testFactory.waitForNetworkRequests(1);
   3638 
   3639         // ...  and cell data to be torn down.
   3640         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3641         assertLength(1, mCm.getAllNetworks());
   3642 
   3643         testFactory.unregister();
   3644         mCm.unregisterNetworkCallback(cellNetworkCallback);
   3645         handlerThread.quit();
   3646     }
   3647 
   3648     @Test
   3649     public void testAvoidBadWifiSetting() throws Exception {
   3650         final ContentResolver cr = mServiceContext.getContentResolver();
   3651         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
   3652         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
   3653 
   3654         tracker.configRestrictsAvoidBadWifi = false;
   3655         String[] values = new String[] {null, "0", "1"};
   3656         for (int i = 0; i < values.length; i++) {
   3657             Settings.Global.putInt(cr, settingName, 1);
   3658             tracker.reevaluate();
   3659             waitForIdle();
   3660             String msg = String.format("config=false, setting=%s", values[i]);
   3661             assertTrue(mService.avoidBadWifi());
   3662             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
   3663         }
   3664 
   3665         tracker.configRestrictsAvoidBadWifi = true;
   3666 
   3667         Settings.Global.putInt(cr, settingName, 0);
   3668         tracker.reevaluate();
   3669         waitForIdle();
   3670         assertFalse(mService.avoidBadWifi());
   3671         assertFalse(tracker.shouldNotifyWifiUnvalidated());
   3672 
   3673         Settings.Global.putInt(cr, settingName, 1);
   3674         tracker.reevaluate();
   3675         waitForIdle();
   3676         assertTrue(mService.avoidBadWifi());
   3677         assertFalse(tracker.shouldNotifyWifiUnvalidated());
   3678 
   3679         Settings.Global.putString(cr, settingName, null);
   3680         tracker.reevaluate();
   3681         waitForIdle();
   3682         assertFalse(mService.avoidBadWifi());
   3683         assertTrue(tracker.shouldNotifyWifiUnvalidated());
   3684     }
   3685 
   3686     @Test
   3687     public void testAvoidBadWifi() throws Exception {
   3688         final ContentResolver cr = mServiceContext.getContentResolver();
   3689         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
   3690 
   3691         // Pretend we're on a carrier that restricts switching away from bad wifi.
   3692         tracker.configRestrictsAvoidBadWifi = true;
   3693 
   3694         // File a request for cell to ensure it doesn't go down.
   3695         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   3696         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3697                 .addTransportType(TRANSPORT_CELLULAR).build();
   3698         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   3699 
   3700         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   3701         mCm.registerDefaultNetworkCallback(defaultCallback);
   3702 
   3703         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
   3704                 .addTransportType(TRANSPORT_WIFI)
   3705                 .addCapability(NET_CAPABILITY_VALIDATED)
   3706                 .build();
   3707         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
   3708         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
   3709 
   3710         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
   3711         tracker.reevaluate();
   3712 
   3713         // Bring up validated cell.
   3714         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3715         mCellNetworkAgent.connect(true);
   3716         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3717         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3718         Network cellNetwork = mCellNetworkAgent.getNetwork();
   3719 
   3720         // Bring up validated wifi.
   3721         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3722         mWiFiNetworkAgent.connect(true);
   3723         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3724         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3725         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
   3726 
   3727         // Fail validation on wifi.
   3728         mWiFiNetworkAgent.setNetworkInvalid();
   3729         mCm.reportNetworkConnectivity(wifiNetwork, false);
   3730         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   3731         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3732 
   3733         // Because avoid bad wifi is off, we don't switch to cellular.
   3734         defaultCallback.assertNoCallback();
   3735         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   3736                 NET_CAPABILITY_VALIDATED));
   3737         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   3738                 NET_CAPABILITY_VALIDATED));
   3739         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   3740 
   3741         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
   3742         // that we switch back to cell.
   3743         tracker.configRestrictsAvoidBadWifi = false;
   3744         tracker.reevaluate();
   3745         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3746         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3747 
   3748         // Switch back to a restrictive carrier.
   3749         tracker.configRestrictsAvoidBadWifi = true;
   3750         tracker.reevaluate();
   3751         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3752         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   3753 
   3754         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
   3755         mCm.setAvoidUnvalidated(wifiNetwork);
   3756         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3757         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   3758                 NET_CAPABILITY_VALIDATED));
   3759         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   3760                 NET_CAPABILITY_VALIDATED));
   3761         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3762 
   3763         // Disconnect and reconnect wifi to clear the one-time switch above.
   3764         mWiFiNetworkAgent.disconnect();
   3765         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3766         mWiFiNetworkAgent.connect(true);
   3767         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3768         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3769         wifiNetwork = mWiFiNetworkAgent.getNetwork();
   3770 
   3771         // Fail validation on wifi and expect the dialog to appear.
   3772         mWiFiNetworkAgent.setNetworkInvalid();
   3773         mCm.reportNetworkConnectivity(wifiNetwork, false);
   3774         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   3775         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3776 
   3777         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
   3778         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
   3779         tracker.reevaluate();
   3780 
   3781         // We now switch to cell.
   3782         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3783         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   3784                 NET_CAPABILITY_VALIDATED));
   3785         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   3786                 NET_CAPABILITY_VALIDATED));
   3787         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3788 
   3789         // Simulate the user turning the cellular fallback setting off and then on.
   3790         // We switch to wifi and then to cell.
   3791         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
   3792         tracker.reevaluate();
   3793         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3794         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   3795         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
   3796         tracker.reevaluate();
   3797         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3798         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3799 
   3800         // If cell goes down, we switch to wifi.
   3801         mCellNetworkAgent.disconnect();
   3802         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3803         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3804         validatedWifiCallback.assertNoCallback();
   3805 
   3806         mCm.unregisterNetworkCallback(cellNetworkCallback);
   3807         mCm.unregisterNetworkCallback(validatedWifiCallback);
   3808         mCm.unregisterNetworkCallback(defaultCallback);
   3809     }
   3810 
   3811     @Test
   3812     public void testMeteredMultipathPreferenceSetting() throws Exception {
   3813         final ContentResolver cr = mServiceContext.getContentResolver();
   3814         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
   3815         final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
   3816 
   3817         for (int config : Arrays.asList(0, 3, 2)) {
   3818             for (String setting: Arrays.asList(null, "0", "2", "1")) {
   3819                 tracker.configMeteredMultipathPreference = config;
   3820                 Settings.Global.putString(cr, settingName, setting);
   3821                 tracker.reevaluate();
   3822                 waitForIdle();
   3823 
   3824                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
   3825                 String msg = String.format("config=%d, setting=%s", config, setting);
   3826                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
   3827             }
   3828         }
   3829     }
   3830 
   3831     /**
   3832      * Validate that a satisfied network request does not trigger onUnavailable() once the
   3833      * time-out period expires.
   3834      */
   3835     @Test
   3836     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
   3837         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3838                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3839         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3840         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
   3841 
   3842         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3843         mWiFiNetworkAgent.connect(false);
   3844         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
   3845                 TEST_CALLBACK_TIMEOUT_MS);
   3846 
   3847         // pass timeout and validate that UNAVAILABLE is not called
   3848         networkCallback.assertNoCallback();
   3849     }
   3850 
   3851     /**
   3852      * Validate that a satisfied network request followed by a disconnected (lost) network does
   3853      * not trigger onUnavailable() once the time-out period expires.
   3854      */
   3855     @Test
   3856     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
   3857         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3858                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3859         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3860         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
   3861 
   3862         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3863         mWiFiNetworkAgent.connect(false);
   3864         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
   3865                 TEST_CALLBACK_TIMEOUT_MS);
   3866         mWiFiNetworkAgent.disconnect();
   3867         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3868 
   3869         // Validate that UNAVAILABLE is not called
   3870         networkCallback.assertNoCallback();
   3871     }
   3872 
   3873     /**
   3874      * Validate that when a time-out is specified for a network request the onUnavailable()
   3875      * callback is called when time-out expires. Then validate that if network request is
   3876      * (somehow) satisfied - the callback isn't called later.
   3877      */
   3878     @Test
   3879     public void testTimedoutNetworkRequest() {
   3880         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3881                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3882         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3883         final int timeoutMs = 10;
   3884         mCm.requestNetwork(nr, networkCallback, timeoutMs);
   3885 
   3886         // pass timeout and validate that UNAVAILABLE is called
   3887         networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
   3888 
   3889         // create a network satisfying request - validate that request not triggered
   3890         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3891         mWiFiNetworkAgent.connect(false);
   3892         networkCallback.assertNoCallback();
   3893     }
   3894 
   3895     /**
   3896      * Validate that when a network request is unregistered (cancelled), no posterior event can
   3897      * trigger the callback.
   3898      */
   3899     @Test
   3900     public void testNoCallbackAfterUnregisteredNetworkRequest() {
   3901         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3902                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3903         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3904         final int timeoutMs = 10;
   3905 
   3906         mCm.requestNetwork(nr, networkCallback, timeoutMs);
   3907         mCm.unregisterNetworkCallback(networkCallback);
   3908         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
   3909         // that this callback will not be called.
   3910         networkCallback.assertNoCallback();
   3911 
   3912         // create a network satisfying request - validate that request not triggered
   3913         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3914         mWiFiNetworkAgent.connect(false);
   3915         networkCallback.assertNoCallback();
   3916     }
   3917 
   3918     @Test
   3919     public void testUnfulfillableNetworkRequest() throws Exception {
   3920         runUnfulfillableNetworkRequest(false);
   3921     }
   3922 
   3923     @Test
   3924     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
   3925         runUnfulfillableNetworkRequest(true);
   3926     }
   3927 
   3928     /**
   3929      * Validate the callback flow for a factory releasing a request as unfulfillable.
   3930      */
   3931     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
   3932         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3933                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3934         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3935 
   3936         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
   3937         handlerThread.start();
   3938         NetworkCapabilities filter = new NetworkCapabilities()
   3939                 .addTransportType(TRANSPORT_WIFI)
   3940                 .addCapability(NET_CAPABILITY_INTERNET);
   3941         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   3942                 mServiceContext, "testFactory", filter);
   3943         testFactory.setScoreFilter(40);
   3944 
   3945         // Register the factory and expect it to receive the default request.
   3946         testFactory.expectAddRequestsWithScores(0);
   3947         testFactory.register();
   3948         SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
   3949 
   3950         assertEquals(1, requests.size()); // have 1 request at this point
   3951         int origRequestId = requests.valueAt(0).requestId;
   3952 
   3953         // Now file the test request and expect it.
   3954         testFactory.expectAddRequestsWithScores(0);
   3955         mCm.requestNetwork(nr, networkCallback);
   3956         requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
   3957 
   3958         int newRequestId = 0;
   3959         for (int i = 0; i < requests.size(); ++i) {
   3960             if (requests.valueAt(i).requestId != origRequestId) {
   3961                 newRequestId = requests.valueAt(i).requestId;
   3962                 break;
   3963             }
   3964         }
   3965 
   3966         testFactory.expectRemoveRequests(1);
   3967         if (preUnregister) {
   3968             mCm.unregisterNetworkCallback(networkCallback);
   3969 
   3970             // Simulate the factory releasing the request as unfulfillable: no-op since
   3971             // the callback has already been unregistered (but a test that no exceptions are
   3972             // thrown).
   3973             testFactory.triggerUnfulfillable(requests.get(newRequestId));
   3974         } else {
   3975             // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
   3976             testFactory.triggerUnfulfillable(requests.get(newRequestId));
   3977 
   3978             networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
   3979             testFactory.waitForRequests();
   3980 
   3981             // unregister network callback - a no-op (since already freed by the
   3982             // on-unavailable), but should not fail or throw exceptions.
   3983             mCm.unregisterNetworkCallback(networkCallback);
   3984         }
   3985 
   3986         testFactory.unregister();
   3987         handlerThread.quit();
   3988     }
   3989 
   3990     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
   3991 
   3992         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
   3993 
   3994         private class CallbackValue {
   3995             public CallbackType callbackType;
   3996             public int error;
   3997 
   3998             public CallbackValue(CallbackType type) {
   3999                 this.callbackType = type;
   4000                 this.error = PacketKeepalive.SUCCESS;
   4001                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
   4002             }
   4003 
   4004             public CallbackValue(CallbackType type, int error) {
   4005                 this.callbackType = type;
   4006                 this.error = error;
   4007                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
   4008             }
   4009 
   4010             @Override
   4011             public boolean equals(Object o) {
   4012                 return o instanceof CallbackValue &&
   4013                         this.callbackType == ((CallbackValue) o).callbackType &&
   4014                         this.error == ((CallbackValue) o).error;
   4015             }
   4016 
   4017             @Override
   4018             public String toString() {
   4019                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
   4020             }
   4021         }
   4022 
   4023         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
   4024 
   4025         @Override
   4026         public void onStarted() {
   4027             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
   4028         }
   4029 
   4030         @Override
   4031         public void onStopped() {
   4032             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
   4033         }
   4034 
   4035         @Override
   4036         public void onError(int error) {
   4037             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
   4038         }
   4039 
   4040         private void expectCallback(CallbackValue callbackValue) {
   4041             try {
   4042                 assertEquals(
   4043                         callbackValue,
   4044                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
   4045             } catch (InterruptedException e) {
   4046                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
   4047             }
   4048         }
   4049 
   4050         public void expectStarted() {
   4051             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
   4052         }
   4053 
   4054         public void expectStopped() {
   4055             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
   4056         }
   4057 
   4058         public void expectError(int error) {
   4059             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
   4060         }
   4061     }
   4062 
   4063     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
   4064 
   4065         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
   4066 
   4067         private class CallbackValue {
   4068             public CallbackType callbackType;
   4069             public int error;
   4070 
   4071             CallbackValue(CallbackType type) {
   4072                 this.callbackType = type;
   4073                 this.error = SocketKeepalive.SUCCESS;
   4074                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
   4075             }
   4076 
   4077             CallbackValue(CallbackType type, int error) {
   4078                 this.callbackType = type;
   4079                 this.error = error;
   4080                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
   4081             }
   4082 
   4083             @Override
   4084             public boolean equals(Object o) {
   4085                 return o instanceof CallbackValue
   4086                         && this.callbackType == ((CallbackValue) o).callbackType
   4087                         && this.error == ((CallbackValue) o).error;
   4088             }
   4089 
   4090             @Override
   4091             public String toString() {
   4092                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
   4093                         error);
   4094             }
   4095         }
   4096 
   4097         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
   4098         private final Executor mExecutor;
   4099 
   4100         TestSocketKeepaliveCallback(@NonNull Executor executor) {
   4101             mExecutor = executor;
   4102         }
   4103 
   4104         @Override
   4105         public void onStarted() {
   4106             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
   4107         }
   4108 
   4109         @Override
   4110         public void onStopped() {
   4111             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
   4112         }
   4113 
   4114         @Override
   4115         public void onError(int error) {
   4116             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
   4117         }
   4118 
   4119         private void expectCallback(CallbackValue callbackValue) {
   4120             try {
   4121                 assertEquals(
   4122                         callbackValue,
   4123                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
   4124             } catch (InterruptedException e) {
   4125                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
   4126             }
   4127         }
   4128 
   4129         public void expectStarted() {
   4130             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
   4131         }
   4132 
   4133         public void expectStopped() {
   4134             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
   4135         }
   4136 
   4137         public void expectError(int error) {
   4138             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
   4139         }
   4140 
   4141         public void assertNoCallback() {
   4142             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
   4143             CallbackValue cv = mCallbacks.peek();
   4144             assertNull("Unexpected callback: " + cv, cv);
   4145         }
   4146     }
   4147 
   4148     private Network connectKeepaliveNetwork(LinkProperties lp) {
   4149         // Ensure the network is disconnected before we do anything.
   4150         if (mWiFiNetworkAgent != null) {
   4151             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
   4152         }
   4153 
   4154         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4155         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   4156         mWiFiNetworkAgent.connect(true);
   4157         waitFor(cv);
   4158         verifyActiveNetwork(TRANSPORT_WIFI);
   4159         mWiFiNetworkAgent.sendLinkProperties(lp);
   4160         waitForIdle();
   4161         return mWiFiNetworkAgent.getNetwork();
   4162     }
   4163 
   4164     @Test
   4165     public void testPacketKeepalives() throws Exception {
   4166         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
   4167         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
   4168         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
   4169         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
   4170         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
   4171 
   4172         final int validKaInterval = 15;
   4173         final int invalidKaInterval = 9;
   4174 
   4175         LinkProperties lp = new LinkProperties();
   4176         lp.setInterfaceName("wlan12");
   4177         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
   4178         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
   4179         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
   4180         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
   4181 
   4182         Network notMyNet = new Network(61234);
   4183         Network myNet = connectKeepaliveNetwork(lp);
   4184 
   4185         TestKeepaliveCallback callback = new TestKeepaliveCallback();
   4186         PacketKeepalive ka;
   4187 
   4188         // Attempt to start keepalives with invalid parameters and check for errors.
   4189         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
   4190         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
   4191 
   4192         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
   4193         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
   4194 
   4195         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
   4196         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4197 
   4198         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
   4199         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4200 
   4201         // NAT-T is only supported for IPv4.
   4202         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
   4203         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4204 
   4205         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
   4206         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
   4207 
   4208         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
   4209         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
   4210 
   4211         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   4212         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
   4213 
   4214         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   4215         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
   4216 
   4217         // Check that a started keepalive can be stopped.
   4218         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   4219         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   4220         callback.expectStarted();
   4221         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
   4222         ka.stop();
   4223         callback.expectStopped();
   4224 
   4225         // Check that deleting the IP address stops the keepalive.
   4226         LinkProperties bogusLp = new LinkProperties(lp);
   4227         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   4228         callback.expectStarted();
   4229         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
   4230         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
   4231         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
   4232         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4233         mWiFiNetworkAgent.sendLinkProperties(lp);
   4234 
   4235         // Check that a started keepalive is stopped correctly when the network disconnects.
   4236         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   4237         callback.expectStarted();
   4238         mWiFiNetworkAgent.disconnect();
   4239         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   4240         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
   4241 
   4242         // ... and that stopping it after that has no adverse effects.
   4243         waitForIdle();
   4244         final Network myNetAlias = myNet;
   4245         assertNull(mCm.getNetworkCapabilities(myNetAlias));
   4246         ka.stop();
   4247 
   4248         // Reconnect.
   4249         myNet = connectKeepaliveNetwork(lp);
   4250         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   4251 
   4252         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
   4253         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   4254         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   4255         callback.expectStarted();
   4256 
   4257         // The second one gets slot 2.
   4258         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
   4259         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
   4260         PacketKeepalive ka2 = mCm.startNattKeepalive(
   4261                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
   4262         callback2.expectStarted();
   4263 
   4264         // Now stop the first one and create a third. This also gets slot 1.
   4265         ka.stop();
   4266         callback.expectStopped();
   4267 
   4268         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   4269         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
   4270         PacketKeepalive ka3 = mCm.startNattKeepalive(
   4271                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
   4272         callback3.expectStarted();
   4273 
   4274         ka2.stop();
   4275         callback2.expectStopped();
   4276 
   4277         ka3.stop();
   4278         callback3.expectStopped();
   4279     }
   4280 
   4281     @FunctionalInterface
   4282     private interface ThrowingConsumer<T> {
   4283         void accept(T t) throws Exception;
   4284     }
   4285 
   4286     // Helper method to prepare the executor and run test
   4287     private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
   4288         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
   4289         final Executor executorInline = (Runnable r) -> r.run();
   4290         functor.accept(executorSingleThread);
   4291         executorSingleThread.shutdown();
   4292         functor.accept(executorInline);
   4293     }
   4294 
   4295     @Test
   4296     public void testNattSocketKeepalives() throws Exception {
   4297         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
   4298         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
   4299     }
   4300 
   4301     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
   4302         // TODO: 1. Move this outside of ConnectivityServiceTest.
   4303         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
   4304         //       3. Mock ipsec service.
   4305         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
   4306         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
   4307         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
   4308         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
   4309         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
   4310 
   4311         final int validKaInterval = 15;
   4312         final int invalidKaInterval = 9;
   4313 
   4314         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
   4315         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
   4316         final int srcPort = testSocket.getPort();
   4317 
   4318         LinkProperties lp = new LinkProperties();
   4319         lp.setInterfaceName("wlan12");
   4320         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
   4321         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
   4322         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
   4323         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
   4324 
   4325         Network notMyNet = new Network(61234);
   4326         Network myNet = connectKeepaliveNetwork(lp);
   4327 
   4328         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
   4329 
   4330         // Attempt to start keepalives with invalid parameters and check for errors.
   4331         // Invalid network.
   4332         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4333                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4334             ka.start(validKaInterval);
   4335             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
   4336         }
   4337 
   4338         // Invalid interval.
   4339         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4340                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4341             ka.start(invalidKaInterval);
   4342             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
   4343         }
   4344 
   4345         // Invalid destination.
   4346         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4347                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
   4348             ka.start(validKaInterval);
   4349             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4350         }
   4351 
   4352         // Invalid source;
   4353         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4354                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
   4355             ka.start(validKaInterval);
   4356             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4357         }
   4358 
   4359         // NAT-T is only supported for IPv4.
   4360         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4361                 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
   4362             ka.start(validKaInterval);
   4363             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4364         }
   4365 
   4366         // Sanity check before testing started keepalive.
   4367         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4368                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4369             ka.start(validKaInterval);
   4370             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
   4371         }
   4372 
   4373         // Check that a started keepalive can be stopped.
   4374         mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
   4375         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4376                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4377             ka.start(validKaInterval);
   4378             callback.expectStarted();
   4379             mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
   4380             ka.stop();
   4381             callback.expectStopped();
   4382 
   4383             // Check that keepalive could be restarted.
   4384             ka.start(validKaInterval);
   4385             callback.expectStarted();
   4386             ka.stop();
   4387             callback.expectStopped();
   4388 
   4389             // Check that keepalive can be restarted without waiting for callback.
   4390             ka.start(validKaInterval);
   4391             callback.expectStarted();
   4392             ka.stop();
   4393             ka.start(validKaInterval);
   4394             callback.expectStopped();
   4395             callback.expectStarted();
   4396             ka.stop();
   4397             callback.expectStopped();
   4398         }
   4399 
   4400         // Check that deleting the IP address stops the keepalive.
   4401         LinkProperties bogusLp = new LinkProperties(lp);
   4402         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4403                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4404             ka.start(validKaInterval);
   4405             callback.expectStarted();
   4406             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
   4407             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
   4408             mWiFiNetworkAgent.sendLinkProperties(bogusLp);
   4409             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
   4410             mWiFiNetworkAgent.sendLinkProperties(lp);
   4411         }
   4412 
   4413         // Check that a started keepalive is stopped correctly when the network disconnects.
   4414         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4415                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4416             ka.start(validKaInterval);
   4417             callback.expectStarted();
   4418             mWiFiNetworkAgent.disconnect();
   4419             waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   4420             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
   4421 
   4422             // ... and that stopping it after that has no adverse effects.
   4423             waitForIdle();
   4424             final Network myNetAlias = myNet;
   4425             assertNull(mCm.getNetworkCapabilities(myNetAlias));
   4426             ka.stop();
   4427             callback.assertNoCallback();
   4428         }
   4429 
   4430         // Reconnect.
   4431         myNet = connectKeepaliveNetwork(lp);
   4432         mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
   4433 
   4434         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
   4435         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   4436         int srcPort2 = 0;
   4437         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4438                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
   4439             ka.start(validKaInterval);
   4440             callback.expectStarted();
   4441 
   4442             // The second one gets slot 2.
   4443             mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
   4444             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
   4445             srcPort2 = testSocket2.getPort();
   4446             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
   4447             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
   4448                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
   4449                 ka2.start(validKaInterval);
   4450                 callback2.expectStarted();
   4451 
   4452                 ka.stop();
   4453                 callback.expectStopped();
   4454 
   4455                 ka2.stop();
   4456                 callback2.expectStopped();
   4457 
   4458                 testSocket.close();
   4459                 testSocket2.close();
   4460             }
   4461         }
   4462 
   4463         // Check that there is no port leaked after all keepalives and sockets are closed.
   4464         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
   4465         // assertFalse(isUdpPortInUse(srcPort));
   4466         // assertFalse(isUdpPortInUse(srcPort2));
   4467 
   4468         mWiFiNetworkAgent.disconnect();
   4469         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   4470         mWiFiNetworkAgent = null;
   4471     }
   4472 
   4473     @Test
   4474     public void testTcpSocketKeepalives() throws Exception {
   4475         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
   4476     }
   4477 
   4478     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
   4479         final int srcPortV4 = 12345;
   4480         final int srcPortV6 = 23456;
   4481         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
   4482         final InetAddress myIPv6 = InetAddress.getByName("::1");
   4483 
   4484         final int validKaInterval = 15;
   4485 
   4486         final LinkProperties lp = new LinkProperties();
   4487         lp.setInterfaceName("wlan12");
   4488         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
   4489         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
   4490         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
   4491         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
   4492 
   4493         final Network notMyNet = new Network(61234);
   4494         final Network myNet = connectKeepaliveNetwork(lp);
   4495 
   4496         final Socket testSocketV4 = new Socket();
   4497         final Socket testSocketV6 = new Socket();
   4498 
   4499         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
   4500 
   4501         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
   4502         // Invalid network.
   4503         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4504             notMyNet, testSocketV4, executor, callback)) {
   4505             ka.start(validKaInterval);
   4506             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
   4507         }
   4508 
   4509         // Invalid Socket (socket is not bound with IPv4 address).
   4510         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4511             myNet, testSocketV4, executor, callback)) {
   4512             ka.start(validKaInterval);
   4513             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
   4514         }
   4515 
   4516         // Invalid Socket (socket is not bound with IPv6 address).
   4517         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4518             myNet, testSocketV6, executor, callback)) {
   4519             ka.start(validKaInterval);
   4520             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
   4521         }
   4522 
   4523         // Bind the socket address
   4524         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
   4525         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
   4526 
   4527         // Invalid Socket (socket is bound with IPv4 address).
   4528         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4529             myNet, testSocketV4, executor, callback)) {
   4530             ka.start(validKaInterval);
   4531             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
   4532         }
   4533 
   4534         // Invalid Socket (socket is bound with IPv6 address).
   4535         try (SocketKeepalive ka = mCm.createSocketKeepalive(
   4536             myNet, testSocketV6, executor, callback)) {
   4537             ka.start(validKaInterval);
   4538             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
   4539         }
   4540 
   4541         testSocketV4.close();
   4542         testSocketV6.close();
   4543 
   4544         mWiFiNetworkAgent.disconnect();
   4545         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   4546         mWiFiNetworkAgent = null;
   4547     }
   4548 
   4549     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
   4550         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
   4551         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
   4552         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
   4553         final int validKaInterval = 15;
   4554 
   4555         // Prepare the target network.
   4556         LinkProperties lp = new LinkProperties();
   4557         lp.setInterfaceName("wlan12");
   4558         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
   4559         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
   4560         Network myNet = connectKeepaliveNetwork(lp);
   4561         mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
   4562         mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
   4563 
   4564         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
   4565 
   4566         // Prepare the target file descriptor, keep only one instance.
   4567         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
   4568         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
   4569         final int srcPort = testSocket.getPort();
   4570         final ParcelFileDescriptor testPfd =
   4571                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
   4572         testSocket.close();
   4573         assertTrue(isUdpPortInUse(srcPort));
   4574 
   4575         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
   4576         // block.
   4577         try (SocketKeepalive ka = mCm.createNattKeepalive(
   4578                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
   4579             ka.start(validKaInterval);
   4580             callback.expectStarted();
   4581             ka.stop();
   4582             callback.expectStopped();
   4583         }
   4584 
   4585         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
   4586         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
   4587         // address.
   4588         assertTrue(isUdpPortInUse(srcPort));
   4589         final InetSocketAddress sa =
   4590                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
   4591         assertEquals(anyIPv4, sa.getAddress());
   4592 
   4593         testPfd.close();
   4594         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
   4595         // assertFalse(isUdpPortInUse(srcPort));
   4596 
   4597         mWiFiNetworkAgent.disconnect();
   4598         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   4599         mWiFiNetworkAgent = null;
   4600     }
   4601 
   4602     private static boolean isUdpPortInUse(int port) {
   4603         try (DatagramSocket ignored = new DatagramSocket(port)) {
   4604             return false;
   4605         } catch (IOException ignored) {
   4606             return true;
   4607         }
   4608     }
   4609 
   4610     @Test
   4611     public void testGetCaptivePortalServerUrl() throws Exception {
   4612         String url = mCm.getCaptivePortalServerUrl();
   4613         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
   4614     }
   4615 
   4616     private static class TestNetworkPinner extends NetworkPinner {
   4617         public static boolean awaitPin(int timeoutMs) {
   4618             synchronized(sLock) {
   4619                 if (sNetwork == null) {
   4620                     try {
   4621                         sLock.wait(timeoutMs);
   4622                     } catch (InterruptedException e) {}
   4623                 }
   4624                 return sNetwork != null;
   4625             }
   4626         }
   4627 
   4628         public static boolean awaitUnpin(int timeoutMs) {
   4629             synchronized(sLock) {
   4630                 if (sNetwork != null) {
   4631                     try {
   4632                         sLock.wait(timeoutMs);
   4633                     } catch (InterruptedException e) {}
   4634                 }
   4635                 return sNetwork == null;
   4636             }
   4637         }
   4638     }
   4639 
   4640     private void assertPinnedToWifiWithCellDefault() {
   4641         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
   4642         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   4643     }
   4644 
   4645     private void assertPinnedToWifiWithWifiDefault() {
   4646         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
   4647         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   4648     }
   4649 
   4650     private void assertNotPinnedToWifi() {
   4651         assertNull(mCm.getBoundNetworkForProcess());
   4652         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   4653     }
   4654 
   4655     @Test
   4656     public void testNetworkPinner() {
   4657         NetworkRequest wifiRequest = new NetworkRequest.Builder()
   4658                 .addTransportType(TRANSPORT_WIFI)
   4659                 .build();
   4660         assertNull(mCm.getBoundNetworkForProcess());
   4661 
   4662         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   4663         assertNull(mCm.getBoundNetworkForProcess());
   4664 
   4665         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   4666         mCellNetworkAgent.connect(true);
   4667         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4668         mWiFiNetworkAgent.connect(false);
   4669 
   4670         // When wi-fi connects, expect to be pinned.
   4671         assertTrue(TestNetworkPinner.awaitPin(100));
   4672         assertPinnedToWifiWithCellDefault();
   4673 
   4674         // Disconnect and expect the pin to drop.
   4675         mWiFiNetworkAgent.disconnect();
   4676         assertTrue(TestNetworkPinner.awaitUnpin(100));
   4677         assertNotPinnedToWifi();
   4678 
   4679         // Reconnecting does not cause the pin to come back.
   4680         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4681         mWiFiNetworkAgent.connect(false);
   4682         assertFalse(TestNetworkPinner.awaitPin(100));
   4683         assertNotPinnedToWifi();
   4684 
   4685         // Pinning while connected causes the pin to take effect immediately.
   4686         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   4687         assertTrue(TestNetworkPinner.awaitPin(100));
   4688         assertPinnedToWifiWithCellDefault();
   4689 
   4690         // Explicitly unpin and expect to use the default network again.
   4691         TestNetworkPinner.unpin();
   4692         assertNotPinnedToWifi();
   4693 
   4694         // Disconnect cell and wifi.
   4695         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
   4696         mCellNetworkAgent.disconnect();
   4697         mWiFiNetworkAgent.disconnect();
   4698         waitFor(cv);
   4699 
   4700         // Pinning takes effect even if the pinned network is the default when the pin is set...
   4701         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   4702         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4703         mWiFiNetworkAgent.connect(false);
   4704         assertTrue(TestNetworkPinner.awaitPin(100));
   4705         assertPinnedToWifiWithWifiDefault();
   4706 
   4707         // ... and is maintained even when that network is no longer the default.
   4708         cv = waitForConnectivityBroadcasts(1);
   4709         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4710         mCellNetworkAgent.connect(true);
   4711         waitFor(cv);
   4712         assertPinnedToWifiWithCellDefault();
   4713     }
   4714 
   4715     @Test
   4716     public void testNetworkCallbackMaximum() {
   4717         // We can only have 99 callbacks, because MultipathPolicyTracker is
   4718         // already one of them.
   4719         final int MAX_REQUESTS = 99;
   4720         final int CALLBACKS = 89;
   4721         final int INTENTS = 10;
   4722         assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
   4723 
   4724         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
   4725         ArrayList<Object> registered = new ArrayList<>();
   4726 
   4727         int j = 0;
   4728         while (j++ < CALLBACKS / 2) {
   4729             NetworkCallback cb = new NetworkCallback();
   4730             mCm.requestNetwork(networkRequest, cb);
   4731             registered.add(cb);
   4732         }
   4733         while (j++ < CALLBACKS) {
   4734             NetworkCallback cb = new NetworkCallback();
   4735             mCm.registerNetworkCallback(networkRequest, cb);
   4736             registered.add(cb);
   4737         }
   4738         j = 0;
   4739         while (j++ < INTENTS / 2) {
   4740             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
   4741             mCm.requestNetwork(networkRequest, pi);
   4742             registered.add(pi);
   4743         }
   4744         while (j++ < INTENTS) {
   4745             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
   4746             mCm.registerNetworkCallback(networkRequest, pi);
   4747             registered.add(pi);
   4748         }
   4749 
   4750         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
   4751         try {
   4752             mCm.requestNetwork(networkRequest, new NetworkCallback());
   4753             fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
   4754         } catch (TooManyRequestsException expected) {}
   4755         try {
   4756             mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
   4757             fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
   4758         } catch (TooManyRequestsException expected) {}
   4759         try {
   4760             mCm.requestNetwork(networkRequest,
   4761                 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
   4762             fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
   4763         } catch (TooManyRequestsException expected) {}
   4764         try {
   4765             mCm.registerNetworkCallback(networkRequest,
   4766                 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
   4767             fail("Registering " + MAX_REQUESTS
   4768                     + " PendingIntent callbacks did not throw exception");
   4769         } catch (TooManyRequestsException expected) {}
   4770 
   4771         for (Object o : registered) {
   4772             if (o instanceof NetworkCallback) {
   4773                 mCm.unregisterNetworkCallback((NetworkCallback)o);
   4774             }
   4775             if (o instanceof PendingIntent) {
   4776                 mCm.unregisterNetworkCallback((PendingIntent)o);
   4777             }
   4778         }
   4779         waitForIdle();
   4780 
   4781         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
   4782         for (int i = 0; i < MAX_REQUESTS; i++) {
   4783             NetworkCallback networkCallback = new NetworkCallback();
   4784             mCm.requestNetwork(networkRequest, networkCallback);
   4785             mCm.unregisterNetworkCallback(networkCallback);
   4786         }
   4787         waitForIdle();
   4788 
   4789         for (int i = 0; i < MAX_REQUESTS; i++) {
   4790             NetworkCallback networkCallback = new NetworkCallback();
   4791             mCm.registerNetworkCallback(networkRequest, networkCallback);
   4792             mCm.unregisterNetworkCallback(networkCallback);
   4793         }
   4794         waitForIdle();
   4795 
   4796         for (int i = 0; i < MAX_REQUESTS; i++) {
   4797             PendingIntent pendingIntent =
   4798                     PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
   4799             mCm.requestNetwork(networkRequest, pendingIntent);
   4800             mCm.unregisterNetworkCallback(pendingIntent);
   4801         }
   4802         waitForIdle();
   4803 
   4804         for (int i = 0; i < MAX_REQUESTS; i++) {
   4805             PendingIntent pendingIntent =
   4806                     PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
   4807             mCm.registerNetworkCallback(networkRequest, pendingIntent);
   4808             mCm.unregisterNetworkCallback(pendingIntent);
   4809         }
   4810     }
   4811 
   4812     @Test
   4813     public void testNetworkInfoOfTypeNone() {
   4814         ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
   4815 
   4816         verifyNoNetwork();
   4817         MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
   4818         assertNull(mCm.getActiveNetworkInfo());
   4819 
   4820         Network[] allNetworks = mCm.getAllNetworks();
   4821         assertLength(1, allNetworks);
   4822         Network network = allNetworks[0];
   4823         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
   4824         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
   4825 
   4826         final NetworkRequest request =
   4827                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
   4828         final TestNetworkCallback callback = new TestNetworkCallback();
   4829         mCm.registerNetworkCallback(request, callback);
   4830 
   4831         // Bring up wifi aware network.
   4832         wifiAware.connect(false, false);
   4833         callback.expectAvailableCallbacksUnvalidated(wifiAware);
   4834 
   4835         assertNull(mCm.getActiveNetworkInfo());
   4836         assertNull(mCm.getActiveNetwork());
   4837         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
   4838         // of this test. Fix it and uncomment the assert below.
   4839         //assertEmpty(mCm.getAllNetworkInfo());
   4840 
   4841         // Disconnect wifi aware network.
   4842         wifiAware.disconnect();
   4843         callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
   4844         mCm.unregisterNetworkCallback(callback);
   4845 
   4846         verifyNoNetwork();
   4847         if (broadcastCV.block(10)) {
   4848             fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
   4849         }
   4850     }
   4851 
   4852     @Test
   4853     public void testDeprecatedAndUnsupportedOperations() throws Exception {
   4854         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
   4855         assertNull(mCm.getNetworkInfo(TYPE_NONE));
   4856         assertNull(mCm.getNetworkForType(TYPE_NONE));
   4857         assertNull(mCm.getLinkProperties(TYPE_NONE));
   4858         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
   4859 
   4860         assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
   4861                 IllegalArgumentException.class);
   4862 
   4863         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
   4864         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
   4865         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
   4866         // TODO: let test context have configuration application target sdk version
   4867         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
   4868         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
   4869         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
   4870         assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
   4871     }
   4872 
   4873     @Test
   4874     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
   4875         final NetworkRequest networkRequest = new NetworkRequest.Builder()
   4876                 .addTransportType(TRANSPORT_WIFI).build();
   4877         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   4878         mCm.registerNetworkCallback(networkRequest, networkCallback);
   4879 
   4880         LinkProperties lp = new LinkProperties();
   4881         lp.setInterfaceName(WIFI_IFNAME);
   4882         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
   4883         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
   4884                 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
   4885         lp.addLinkAddress(myIpv4Address);
   4886         lp.addRoute(myIpv4DefaultRoute);
   4887 
   4888         // Verify direct routes are added when network agent is first registered in
   4889         // ConnectivityService.
   4890         MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
   4891         networkAgent.connect(true);
   4892         networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
   4893         networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
   4894         CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   4895                 networkAgent);
   4896         networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
   4897         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
   4898         networkCallback.assertNoCallback();
   4899         checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
   4900                 Arrays.asList(myIpv4DefaultRoute));
   4901         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
   4902                 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
   4903 
   4904         // Verify direct routes are added during subsequent link properties updates.
   4905         LinkProperties newLp = new LinkProperties(lp);
   4906         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
   4907         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
   4908         newLp.addLinkAddress(myIpv6Address1);
   4909         newLp.addLinkAddress(myIpv6Address2);
   4910         networkAgent.sendLinkProperties(newLp);
   4911         cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
   4912         networkCallback.assertNoCallback();
   4913         checkDirectlyConnectedRoutes(cbi.arg,
   4914                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
   4915                 Arrays.asList(myIpv4DefaultRoute));
   4916         mCm.unregisterNetworkCallback(networkCallback);
   4917     }
   4918 
   4919     @Test
   4920     public void testStatsIfacesChanged() throws Exception {
   4921         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   4922         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4923 
   4924         Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
   4925         Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
   4926 
   4927         LinkProperties cellLp = new LinkProperties();
   4928         cellLp.setInterfaceName(MOBILE_IFNAME);
   4929         LinkProperties wifiLp = new LinkProperties();
   4930         wifiLp.setInterfaceName(WIFI_IFNAME);
   4931 
   4932         // Simple connection should have updated ifaces
   4933         mCellNetworkAgent.connect(false);
   4934         mCellNetworkAgent.sendLinkProperties(cellLp);
   4935         waitForIdle();
   4936         verify(mStatsService, atLeastOnce())
   4937                 .forceUpdateIfaces(
   4938                         eq(onlyCell),
   4939                         eq(new VpnInfo[0]),
   4940                         any(NetworkState[].class),
   4941                         eq(MOBILE_IFNAME));
   4942         reset(mStatsService);
   4943 
   4944         // Default network switch should update ifaces.
   4945         mWiFiNetworkAgent.connect(false);
   4946         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
   4947         waitForIdle();
   4948         assertEquals(wifiLp, mService.getActiveLinkProperties());
   4949         verify(mStatsService, atLeastOnce())
   4950                 .forceUpdateIfaces(
   4951                         eq(onlyWifi),
   4952                         eq(new VpnInfo[0]),
   4953                         any(NetworkState[].class),
   4954                         eq(WIFI_IFNAME));
   4955         reset(mStatsService);
   4956 
   4957         // Disconnect should update ifaces.
   4958         mWiFiNetworkAgent.disconnect();
   4959         waitForIdle();
   4960         verify(mStatsService, atLeastOnce())
   4961                 .forceUpdateIfaces(
   4962                         eq(onlyCell),
   4963                         eq(new VpnInfo[0]),
   4964                         any(NetworkState[].class),
   4965                         eq(MOBILE_IFNAME));
   4966         reset(mStatsService);
   4967 
   4968         // Metered change should update ifaces
   4969         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   4970         waitForIdle();
   4971         verify(mStatsService, atLeastOnce())
   4972                 .forceUpdateIfaces(
   4973                         eq(onlyCell),
   4974                         eq(new VpnInfo[0]),
   4975                         any(NetworkState[].class),
   4976                         eq(MOBILE_IFNAME));
   4977         reset(mStatsService);
   4978 
   4979         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   4980         waitForIdle();
   4981         verify(mStatsService, atLeastOnce())
   4982                 .forceUpdateIfaces(
   4983                         eq(onlyCell),
   4984                         eq(new VpnInfo[0]),
   4985                         any(NetworkState[].class),
   4986                         eq(MOBILE_IFNAME));
   4987         reset(mStatsService);
   4988 
   4989         // Captive portal change shouldn't update ifaces
   4990         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
   4991         waitForIdle();
   4992         verify(mStatsService, never())
   4993                 .forceUpdateIfaces(
   4994                         eq(onlyCell),
   4995                         eq(new VpnInfo[0]),
   4996                         any(NetworkState[].class),
   4997                         eq(MOBILE_IFNAME));
   4998         reset(mStatsService);
   4999 
   5000         // Roaming change should update ifaces
   5001         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
   5002         waitForIdle();
   5003         verify(mStatsService, atLeastOnce())
   5004                 .forceUpdateIfaces(
   5005                         eq(onlyCell),
   5006                         eq(new VpnInfo[0]),
   5007                         any(NetworkState[].class),
   5008                         eq(MOBILE_IFNAME));
   5009         reset(mStatsService);
   5010     }
   5011 
   5012     @Test
   5013     public void testBasicDnsConfigurationPushed() throws Exception {
   5014         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   5015 
   5016         // Clear any interactions that occur as a result of CS starting up.
   5017         reset(mMockDnsResolver);
   5018 
   5019         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5020         waitForIdle();
   5021         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
   5022         verifyNoMoreInteractions(mMockDnsResolver);
   5023 
   5024         final LinkProperties cellLp = new LinkProperties();
   5025         cellLp.setInterfaceName(MOBILE_IFNAME);
   5026         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
   5027         // "is-reachable" testing in order to not program netd with unreachable
   5028         // nameservers that it might try repeated to validate.
   5029         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
   5030         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
   5031                 MOBILE_IFNAME));
   5032         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
   5033         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
   5034                 MOBILE_IFNAME));
   5035         mCellNetworkAgent.sendLinkProperties(cellLp);
   5036         mCellNetworkAgent.connect(false);
   5037         waitForIdle();
   5038 
   5039         verify(mMockDnsResolver, times(1)).createNetworkCache(
   5040                 eq(mCellNetworkAgent.getNetwork().netId));
   5041         // CS tells dnsresolver about the empty DNS config for this network.
   5042         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
   5043         reset(mMockDnsResolver);
   5044 
   5045         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
   5046         mCellNetworkAgent.sendLinkProperties(cellLp);
   5047         waitForIdle();
   5048         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
   5049                 mResolverParamsParcelCaptor.capture());
   5050         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
   5051         assertEquals(1, resolvrParams.servers.length);
   5052         assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
   5053         // Opportunistic mode.
   5054         assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
   5055         reset(mMockDnsResolver);
   5056 
   5057         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
   5058         mCellNetworkAgent.sendLinkProperties(cellLp);
   5059         waitForIdle();
   5060         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
   5061                 mResolverParamsParcelCaptor.capture());
   5062         resolvrParams = mResolverParamsParcelCaptor.getValue();
   5063         assertEquals(2, resolvrParams.servers.length);
   5064         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
   5065                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5066         // Opportunistic mode.
   5067         assertEquals(2, resolvrParams.tlsServers.length);
   5068         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
   5069                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5070         reset(mMockDnsResolver);
   5071 
   5072         final String TLS_SPECIFIER = "tls.example.com";
   5073         final String TLS_SERVER6 = "2001:db8:53::53";
   5074         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
   5075         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
   5076         mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
   5077                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
   5078 
   5079         waitForIdle();
   5080         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
   5081                 mResolverParamsParcelCaptor.capture());
   5082         resolvrParams = mResolverParamsParcelCaptor.getValue();
   5083         assertEquals(2, resolvrParams.servers.length);
   5084         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
   5085                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5086         reset(mMockDnsResolver);
   5087     }
   5088 
   5089     @Test
   5090     public void testPrivateDnsSettingsChange() throws Exception {
   5091         // Clear any interactions that occur as a result of CS starting up.
   5092         reset(mMockDnsResolver);
   5093 
   5094         // The default on Android is opportunistic mode ("Automatic").
   5095         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   5096 
   5097         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   5098         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   5099                 .addTransportType(TRANSPORT_CELLULAR).build();
   5100         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   5101 
   5102         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5103         waitForIdle();
   5104         // CS tells netd about the empty DNS config for this network.
   5105         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
   5106         verifyNoMoreInteractions(mMockDnsResolver);
   5107 
   5108         final LinkProperties cellLp = new LinkProperties();
   5109         cellLp.setInterfaceName(MOBILE_IFNAME);
   5110         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
   5111         // "is-reachable" testing in order to not program netd with unreachable
   5112         // nameservers that it might try repeated to validate.
   5113         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
   5114         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
   5115                 MOBILE_IFNAME));
   5116         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
   5117         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
   5118                 MOBILE_IFNAME));
   5119         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
   5120         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
   5121 
   5122         mCellNetworkAgent.sendLinkProperties(cellLp);
   5123         mCellNetworkAgent.connect(false);
   5124         waitForIdle();
   5125         verify(mMockDnsResolver, times(1)).createNetworkCache(
   5126                 eq(mCellNetworkAgent.getNetwork().netId));
   5127         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
   5128                 mResolverParamsParcelCaptor.capture());
   5129         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
   5130         assertEquals(2, resolvrParams.tlsServers.length);
   5131         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
   5132                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5133         // Opportunistic mode.
   5134         assertEquals(2, resolvrParams.tlsServers.length);
   5135         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
   5136                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5137         reset(mMockDnsResolver);
   5138         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   5139         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
   5140                 mCellNetworkAgent);
   5141         CallbackInfo cbi = cellNetworkCallback.expectCallback(
   5142                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   5143         cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
   5144         cellNetworkCallback.assertNoCallback();
   5145         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5146         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5147 
   5148         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
   5149         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
   5150                 mResolverParamsParcelCaptor.capture());
   5151         resolvrParams = mResolverParamsParcelCaptor.getValue();
   5152         assertEquals(2, resolvrParams.servers.length);
   5153         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
   5154                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5155         reset(mMockDnsResolver);
   5156         cellNetworkCallback.assertNoCallback();
   5157 
   5158         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   5159         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
   5160                 mResolverParamsParcelCaptor.capture());
   5161         resolvrParams = mResolverParamsParcelCaptor.getValue();
   5162         assertEquals(2, resolvrParams.servers.length);
   5163         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
   5164                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5165         assertEquals(2, resolvrParams.tlsServers.length);
   5166         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
   5167                 new String[]{"2001:db8::1", "192.0.2.1"}));
   5168         reset(mMockDnsResolver);
   5169         cellNetworkCallback.assertNoCallback();
   5170 
   5171         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
   5172         // Can't test dns configuration for strict mode without properly mocking
   5173         // out the DNS lookups, but can test that LinkProperties is updated.
   5174         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   5175                 mCellNetworkAgent);
   5176         cellNetworkCallback.assertNoCallback();
   5177         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5178         assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5179     }
   5180 
   5181     @Test
   5182     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
   5183         // The default on Android is opportunistic mode ("Automatic").
   5184         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   5185 
   5186         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   5187         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   5188                 .addTransportType(TRANSPORT_CELLULAR).build();
   5189         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   5190 
   5191         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5192         waitForIdle();
   5193         LinkProperties lp = new LinkProperties();
   5194         mCellNetworkAgent.sendLinkProperties(lp);
   5195         mCellNetworkAgent.connect(false);
   5196         waitForIdle();
   5197         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   5198         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
   5199                 mCellNetworkAgent);
   5200         CallbackInfo cbi = cellNetworkCallback.expectCallback(
   5201                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   5202         cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
   5203         cellNetworkCallback.assertNoCallback();
   5204         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5205         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5206         Set<InetAddress> dnsServers = new HashSet<>();
   5207         checkDnsServers(cbi.arg, dnsServers);
   5208 
   5209         // Send a validation event for a server that is not part of the current
   5210         // resolver config. The validation event should be ignored.
   5211         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   5212                 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
   5213         cellNetworkCallback.assertNoCallback();
   5214 
   5215         // Add a dns server to the LinkProperties.
   5216         LinkProperties lp2 = new LinkProperties(lp);
   5217         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
   5218         mCellNetworkAgent.sendLinkProperties(lp2);
   5219         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   5220                 mCellNetworkAgent);
   5221         cellNetworkCallback.assertNoCallback();
   5222         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5223         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5224         dnsServers.add(InetAddress.getByName("145.100.185.16"));
   5225         checkDnsServers(cbi.arg, dnsServers);
   5226 
   5227         // Send a validation event containing a hostname that is not part of
   5228         // the current resolver config. The validation event should be ignored.
   5229         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   5230                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
   5231         cellNetworkCallback.assertNoCallback();
   5232 
   5233         // Send a validation event where validation failed.
   5234         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   5235                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
   5236         cellNetworkCallback.assertNoCallback();
   5237 
   5238         // Send a validation event where validation succeeded for a server in
   5239         // the current resolver config. A LinkProperties callback with updated
   5240         // private dns fields should be sent.
   5241         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   5242                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
   5243         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   5244                 mCellNetworkAgent);
   5245         cellNetworkCallback.assertNoCallback();
   5246         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5247         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5248         checkDnsServers(cbi.arg, dnsServers);
   5249 
   5250         // The private dns fields in LinkProperties should be preserved when
   5251         // the network agent sends unrelated changes.
   5252         LinkProperties lp3 = new LinkProperties(lp2);
   5253         lp3.setMtu(1300);
   5254         mCellNetworkAgent.sendLinkProperties(lp3);
   5255         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   5256                 mCellNetworkAgent);
   5257         cellNetworkCallback.assertNoCallback();
   5258         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5259         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5260         checkDnsServers(cbi.arg, dnsServers);
   5261         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
   5262 
   5263         // Removing the only validated server should affect the private dns
   5264         // fields in LinkProperties.
   5265         LinkProperties lp4 = new LinkProperties(lp3);
   5266         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
   5267         mCellNetworkAgent.sendLinkProperties(lp4);
   5268         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   5269                 mCellNetworkAgent);
   5270         cellNetworkCallback.assertNoCallback();
   5271         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   5272         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   5273         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
   5274         checkDnsServers(cbi.arg, dnsServers);
   5275         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
   5276     }
   5277 
   5278     private void checkDirectlyConnectedRoutes(Object callbackObj,
   5279             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
   5280         assertTrue(callbackObj instanceof LinkProperties);
   5281         LinkProperties lp = (LinkProperties) callbackObj;
   5282 
   5283         Set<RouteInfo> expectedRoutes = new ArraySet<>();
   5284         expectedRoutes.addAll(otherRoutes);
   5285         for (LinkAddress address : linkAddresses) {
   5286             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
   5287             // Duplicates in linkAddresses are considered failures
   5288             assertTrue(expectedRoutes.add(localRoute));
   5289         }
   5290         List<RouteInfo> observedRoutes = lp.getRoutes();
   5291         assertEquals(expectedRoutes.size(), observedRoutes.size());
   5292         assertTrue(observedRoutes.containsAll(expectedRoutes));
   5293     }
   5294 
   5295     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
   5296         assertTrue(callbackObj instanceof LinkProperties);
   5297         LinkProperties lp = (LinkProperties) callbackObj;
   5298         assertEquals(dnsServers.size(), lp.getDnsServers().size());
   5299         assertTrue(lp.getDnsServers().containsAll(dnsServers));
   5300     }
   5301 
   5302     private static <T> void assertEmpty(T[] ts) {
   5303         int length = ts.length;
   5304         assertEquals("expected empty array, but length was " + length, 0, length);
   5305     }
   5306 
   5307     private static <T> void assertLength(int expected, T[] got) {
   5308         int length = got.length;
   5309         assertEquals(String.format("expected array of length %s, but length was %s for %s",
   5310                 expected, length, Arrays.toString(got)), expected, length);
   5311     }
   5312 
   5313     private static <T> void assertException(Runnable block, Class<T> expected) {
   5314         try {
   5315             block.run();
   5316             fail("Expected exception of type " + expected);
   5317         } catch (Exception got) {
   5318             if (!got.getClass().equals(expected)) {
   5319                 fail("Expected exception of type " + expected + " but got " + got);
   5320             }
   5321             return;
   5322         }
   5323     }
   5324 
   5325     @Test
   5326     public void testVpnNetworkActive() {
   5327         final int uid = Process.myUid();
   5328 
   5329         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
   5330         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
   5331         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
   5332         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
   5333         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
   5334         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
   5335         final NetworkRequest genericRequest = new NetworkRequest.Builder()
   5336                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
   5337         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
   5338                 .addTransportType(TRANSPORT_WIFI).build();
   5339         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
   5340                 .removeCapability(NET_CAPABILITY_NOT_VPN)
   5341                 .addTransportType(TRANSPORT_VPN).build();
   5342         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
   5343         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
   5344         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
   5345         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
   5346         mCm.registerDefaultNetworkCallback(defaultCallback);
   5347         defaultCallback.assertNoCallback();
   5348 
   5349         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5350         mWiFiNetworkAgent.connect(false);
   5351 
   5352         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   5353         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   5354         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   5355         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   5356         vpnNetworkCallback.assertNoCallback();
   5357         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5358 
   5359         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5360         final ArraySet<UidRange> ranges = new ArraySet<>();
   5361         ranges.add(new UidRange(uid, uid));
   5362         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5363         mMockVpn.setUids(ranges);
   5364         // VPN networks do not satisfy the default request and are automatically validated
   5365         // by NetworkMonitor
   5366         assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
   5367         vpnNetworkAgent.setNetworkValid();
   5368 
   5369         vpnNetworkAgent.connect(false);
   5370         mMockVpn.connect();
   5371         mMockVpn.setUnderlyingNetworks(new Network[0]);
   5372 
   5373         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   5374         genericNotVpnNetworkCallback.assertNoCallback();
   5375         wifiNetworkCallback.assertNoCallback();
   5376         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   5377         defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   5378         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5379 
   5380         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   5381         genericNotVpnNetworkCallback.assertNoCallback();
   5382         vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
   5383         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   5384         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5385 
   5386         ranges.clear();
   5387         vpnNetworkAgent.setUids(ranges);
   5388 
   5389         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5390         genericNotVpnNetworkCallback.assertNoCallback();
   5391         wifiNetworkCallback.assertNoCallback();
   5392         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5393 
   5394         // TODO : The default network callback should actually get a LOST call here (also see the
   5395         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
   5396         // ranges at all when determining whether a network should be rematched. In practice, VPNs
   5397         // can't currently update their UIDs without disconnecting, so this does not matter too
   5398         // much, but that is the reason the test here has to check for an update to the
   5399         // capabilities instead of the expected LOST then AVAILABLE.
   5400         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   5401 
   5402         ranges.add(new UidRange(uid, uid));
   5403         mMockVpn.setUids(ranges);
   5404         vpnNetworkAgent.setUids(ranges);
   5405 
   5406         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
   5407         genericNotVpnNetworkCallback.assertNoCallback();
   5408         wifiNetworkCallback.assertNoCallback();
   5409         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
   5410         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
   5411         // happen outside of the test, ConnectivityService does not rematch callbacks.
   5412         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   5413 
   5414         mWiFiNetworkAgent.disconnect();
   5415 
   5416         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   5417         genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   5418         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   5419         vpnNetworkCallback.assertNoCallback();
   5420         defaultCallback.assertNoCallback();
   5421 
   5422         vpnNetworkAgent.disconnect();
   5423 
   5424         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5425         genericNotVpnNetworkCallback.assertNoCallback();
   5426         wifiNetworkCallback.assertNoCallback();
   5427         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5428         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5429         assertEquals(null, mCm.getActiveNetwork());
   5430 
   5431         mCm.unregisterNetworkCallback(genericNetworkCallback);
   5432         mCm.unregisterNetworkCallback(wifiNetworkCallback);
   5433         mCm.unregisterNetworkCallback(vpnNetworkCallback);
   5434         mCm.unregisterNetworkCallback(defaultCallback);
   5435     }
   5436 
   5437     @Test
   5438     public void testVpnWithoutInternet() {
   5439         final int uid = Process.myUid();
   5440 
   5441         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
   5442         mCm.registerDefaultNetworkCallback(defaultCallback);
   5443 
   5444         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5445         mWiFiNetworkAgent.connect(true);
   5446 
   5447         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   5448         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5449 
   5450         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5451         final ArraySet<UidRange> ranges = new ArraySet<>();
   5452         ranges.add(new UidRange(uid, uid));
   5453         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5454         mMockVpn.setUids(ranges);
   5455         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
   5456         mMockVpn.connect();
   5457 
   5458         defaultCallback.assertNoCallback();
   5459         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5460 
   5461         vpnNetworkAgent.disconnect();
   5462         defaultCallback.assertNoCallback();
   5463 
   5464         mCm.unregisterNetworkCallback(defaultCallback);
   5465     }
   5466 
   5467     @Test
   5468     public void testVpnWithInternet() {
   5469         final int uid = Process.myUid();
   5470 
   5471         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
   5472         mCm.registerDefaultNetworkCallback(defaultCallback);
   5473 
   5474         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5475         mWiFiNetworkAgent.connect(true);
   5476 
   5477         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   5478         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5479 
   5480         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5481         final ArraySet<UidRange> ranges = new ArraySet<>();
   5482         ranges.add(new UidRange(uid, uid));
   5483         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5484         mMockVpn.setUids(ranges);
   5485         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
   5486         mMockVpn.connect();
   5487 
   5488         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   5489         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   5490 
   5491         vpnNetworkAgent.disconnect();
   5492         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5493         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   5494 
   5495         mCm.unregisterNetworkCallback(defaultCallback);
   5496     }
   5497 
   5498     @Test
   5499     public void testVpnUnvalidated() throws Exception {
   5500         final TestNetworkCallback callback = new TestNetworkCallback();
   5501         mCm.registerDefaultNetworkCallback(callback);
   5502 
   5503         // Bring up Ethernet.
   5504         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   5505         mEthernetNetworkAgent.connect(true);
   5506         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
   5507         callback.assertNoCallback();
   5508 
   5509         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
   5510         final int uid = Process.myUid();
   5511         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5512         final ArraySet<UidRange> ranges = new ArraySet<>();
   5513         ranges.add(new UidRange(uid, uid));
   5514         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5515         mMockVpn.setUids(ranges);
   5516         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
   5517         mMockVpn.connect();
   5518 
   5519         // Even though the VPN is unvalidated, it becomes the default network for our app.
   5520         callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   5521         // TODO: this looks like a spurious callback.
   5522         callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   5523         callback.assertNoCallback();
   5524 
   5525         assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
   5526         assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
   5527         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   5528 
   5529         NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
   5530         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
   5531         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
   5532 
   5533         assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
   5534         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
   5535                 vpnNetworkAgent.mNetworkCapabilities));
   5536 
   5537         // Pretend that the VPN network validates.
   5538         vpnNetworkAgent.setNetworkValid();
   5539         vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
   5540         // Expect to see the validated capability, but no other changes, because the VPN is already
   5541         // the default network for the app.
   5542         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
   5543         callback.assertNoCallback();
   5544 
   5545         vpnNetworkAgent.disconnect();
   5546         callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   5547         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
   5548     }
   5549 
   5550     @Test
   5551     public void testVpnSetUnderlyingNetworks() {
   5552         final int uid = Process.myUid();
   5553 
   5554         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
   5555         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
   5556                 .removeCapability(NET_CAPABILITY_NOT_VPN)
   5557                 .addTransportType(TRANSPORT_VPN)
   5558                 .build();
   5559         NetworkCapabilities nc;
   5560         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
   5561         vpnNetworkCallback.assertNoCallback();
   5562 
   5563         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5564         final ArraySet<UidRange> ranges = new ArraySet<>();
   5565         ranges.add(new UidRange(uid, uid));
   5566         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5567         mMockVpn.connect();
   5568         mMockVpn.setUids(ranges);
   5569         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
   5570 
   5571         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   5572         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
   5573         assertTrue(nc.hasTransport(TRANSPORT_VPN));
   5574         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
   5575         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
   5576         // For safety reasons a VPN without underlying networks is considered metered.
   5577         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
   5578 
   5579         // Connect cell and use it as an underlying network.
   5580         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5581         mCellNetworkAgent.connect(true);
   5582 
   5583         mService.setUnderlyingNetworksForVpn(
   5584                 new Network[] { mCellNetworkAgent.getNetwork() });
   5585 
   5586         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5587                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   5588                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5589                 vpnNetworkAgent);
   5590 
   5591         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5592         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5593         mWiFiNetworkAgent.connect(true);
   5594 
   5595         mService.setUnderlyingNetworksForVpn(
   5596                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
   5597 
   5598         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5599                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   5600                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5601                 vpnNetworkAgent);
   5602 
   5603         // Don't disconnect, but note the VPN is not using wifi any more.
   5604         mService.setUnderlyingNetworksForVpn(
   5605                 new Network[] { mCellNetworkAgent.getNetwork() });
   5606 
   5607         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5608                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   5609                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5610                 vpnNetworkAgent);
   5611 
   5612         // Use Wifi but not cell. Note the VPN is now unmetered.
   5613         mService.setUnderlyingNetworksForVpn(
   5614                 new Network[] { mWiFiNetworkAgent.getNetwork() });
   5615 
   5616         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5617                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   5618                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5619                 vpnNetworkAgent);
   5620 
   5621         // Use both again.
   5622         mService.setUnderlyingNetworksForVpn(
   5623                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
   5624 
   5625         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5626                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   5627                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5628                 vpnNetworkAgent);
   5629 
   5630         // Disconnect cell. Receive update without even removing the dead network from the
   5631         // underlying networks  it's dead anyway. Not metered any more.
   5632         mCellNetworkAgent.disconnect();
   5633         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5634                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   5635                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5636                 vpnNetworkAgent);
   5637 
   5638         // Disconnect wifi too. No underlying networks means this is now metered.
   5639         mWiFiNetworkAgent.disconnect();
   5640         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5641                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   5642                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5643                 vpnNetworkAgent);
   5644 
   5645         mMockVpn.disconnect();
   5646     }
   5647 
   5648     @Test
   5649     public void testNullUnderlyingNetworks() {
   5650         final int uid = Process.myUid();
   5651 
   5652         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
   5653         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
   5654                 .removeCapability(NET_CAPABILITY_NOT_VPN)
   5655                 .addTransportType(TRANSPORT_VPN)
   5656                 .build();
   5657         NetworkCapabilities nc;
   5658         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
   5659         vpnNetworkCallback.assertNoCallback();
   5660 
   5661         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5662         final ArraySet<UidRange> ranges = new ArraySet<>();
   5663         ranges.add(new UidRange(uid, uid));
   5664         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5665         mMockVpn.connect();
   5666         mMockVpn.setUids(ranges);
   5667         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
   5668 
   5669         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   5670         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
   5671         assertTrue(nc.hasTransport(TRANSPORT_VPN));
   5672         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
   5673         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
   5674         // By default, VPN is set to track default network (i.e. its underlying networks is null).
   5675         // In case of no default network, VPN is considered metered.
   5676         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
   5677 
   5678         // Connect to Cell; Cell is the default network.
   5679         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5680         mCellNetworkAgent.connect(true);
   5681 
   5682         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5683                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   5684                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5685                 vpnNetworkAgent);
   5686 
   5687         // Connect to WiFi; WiFi is the new default.
   5688         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5689         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5690         mWiFiNetworkAgent.connect(true);
   5691 
   5692         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5693                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   5694                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5695                 vpnNetworkAgent);
   5696 
   5697         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
   5698         // the capabilities.
   5699         mCellNetworkAgent.disconnect();
   5700 
   5701         // Disconnect wifi too. Now we have no default network.
   5702         mWiFiNetworkAgent.disconnect();
   5703 
   5704         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   5705                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   5706                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   5707                 vpnNetworkAgent);
   5708 
   5709         mMockVpn.disconnect();
   5710     }
   5711 
   5712     @Test
   5713     public void testIsActiveNetworkMeteredOverWifi() {
   5714         // Returns true by default when no network is available.
   5715         assertTrue(mCm.isActiveNetworkMetered());
   5716         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5717         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5718         mWiFiNetworkAgent.connect(true);
   5719         waitForIdle();
   5720 
   5721         assertFalse(mCm.isActiveNetworkMetered());
   5722     }
   5723 
   5724     @Test
   5725     public void testIsActiveNetworkMeteredOverCell() {
   5726         // Returns true by default when no network is available.
   5727         assertTrue(mCm.isActiveNetworkMetered());
   5728         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5729         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   5730         mCellNetworkAgent.connect(true);
   5731         waitForIdle();
   5732 
   5733         assertTrue(mCm.isActiveNetworkMetered());
   5734     }
   5735 
   5736     @Test
   5737     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
   5738         // Returns true by default when no network is available.
   5739         assertTrue(mCm.isActiveNetworkMetered());
   5740         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5741         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   5742         mCellNetworkAgent.connect(true);
   5743         waitForIdle();
   5744         assertTrue(mCm.isActiveNetworkMetered());
   5745 
   5746         // Connect VPN network. By default it is using current default network (Cell).
   5747         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5748         final ArraySet<UidRange> ranges = new ArraySet<>();
   5749         final int uid = Process.myUid();
   5750         ranges.add(new UidRange(uid, uid));
   5751         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5752         mMockVpn.setUids(ranges);
   5753         vpnNetworkAgent.connect(true);
   5754         mMockVpn.connect();
   5755         waitForIdle();
   5756         // Ensure VPN is now the active network.
   5757         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   5758 
   5759         // Expect VPN to be metered.
   5760         assertTrue(mCm.isActiveNetworkMetered());
   5761 
   5762         // Connect WiFi.
   5763         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5764         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5765         mWiFiNetworkAgent.connect(true);
   5766         waitForIdle();
   5767         // VPN should still be the active network.
   5768         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   5769 
   5770         // Expect VPN to be unmetered as it should now be using WiFi (new default).
   5771         assertFalse(mCm.isActiveNetworkMetered());
   5772 
   5773         // Disconnecting Cell should not affect VPN's meteredness.
   5774         mCellNetworkAgent.disconnect();
   5775         waitForIdle();
   5776 
   5777         assertFalse(mCm.isActiveNetworkMetered());
   5778 
   5779         // Disconnect WiFi; Now there is no platform default network.
   5780         mWiFiNetworkAgent.disconnect();
   5781         waitForIdle();
   5782 
   5783         // VPN without any underlying networks is treated as metered.
   5784         assertTrue(mCm.isActiveNetworkMetered());
   5785 
   5786         vpnNetworkAgent.disconnect();
   5787         mMockVpn.disconnect();
   5788     }
   5789 
   5790    @Test
   5791    public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
   5792         // Returns true by default when no network is available.
   5793         assertTrue(mCm.isActiveNetworkMetered());
   5794         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5795         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   5796         mCellNetworkAgent.connect(true);
   5797         waitForIdle();
   5798         assertTrue(mCm.isActiveNetworkMetered());
   5799 
   5800         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5801         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5802         mWiFiNetworkAgent.connect(true);
   5803         waitForIdle();
   5804         assertFalse(mCm.isActiveNetworkMetered());
   5805 
   5806         // Connect VPN network.
   5807         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5808         final ArraySet<UidRange> ranges = new ArraySet<>();
   5809         final int uid = Process.myUid();
   5810         ranges.add(new UidRange(uid, uid));
   5811         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5812         mMockVpn.setUids(ranges);
   5813         vpnNetworkAgent.connect(true);
   5814         mMockVpn.connect();
   5815         waitForIdle();
   5816         // Ensure VPN is now the active network.
   5817         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   5818         // VPN is using Cell
   5819         mService.setUnderlyingNetworksForVpn(
   5820                 new Network[] { mCellNetworkAgent.getNetwork() });
   5821         waitForIdle();
   5822 
   5823         // Expect VPN to be metered.
   5824         assertTrue(mCm.isActiveNetworkMetered());
   5825 
   5826         // VPN is now using WiFi
   5827         mService.setUnderlyingNetworksForVpn(
   5828                 new Network[] { mWiFiNetworkAgent.getNetwork() });
   5829         waitForIdle();
   5830 
   5831         // Expect VPN to be unmetered
   5832         assertFalse(mCm.isActiveNetworkMetered());
   5833 
   5834         // VPN is using Cell | WiFi.
   5835         mService.setUnderlyingNetworksForVpn(
   5836                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
   5837         waitForIdle();
   5838 
   5839         // Expect VPN to be metered.
   5840         assertTrue(mCm.isActiveNetworkMetered());
   5841 
   5842         // VPN is using WiFi | Cell.
   5843         mService.setUnderlyingNetworksForVpn(
   5844                 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
   5845         waitForIdle();
   5846 
   5847         // Order should not matter and VPN should still be metered.
   5848         assertTrue(mCm.isActiveNetworkMetered());
   5849 
   5850         // VPN is not using any underlying networks.
   5851         mService.setUnderlyingNetworksForVpn(new Network[0]);
   5852         waitForIdle();
   5853 
   5854         // VPN without underlying networks is treated as metered.
   5855         assertTrue(mCm.isActiveNetworkMetered());
   5856 
   5857         vpnNetworkAgent.disconnect();
   5858         mMockVpn.disconnect();
   5859     }
   5860 
   5861     @Test
   5862     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
   5863         // Returns true by default when no network is available.
   5864         assertTrue(mCm.isActiveNetworkMetered());
   5865         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5866         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5867         mWiFiNetworkAgent.connect(true);
   5868         waitForIdle();
   5869         assertFalse(mCm.isActiveNetworkMetered());
   5870 
   5871         // Connect VPN network.
   5872         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   5873         final ArraySet<UidRange> ranges = new ArraySet<>();
   5874         final int uid = Process.myUid();
   5875         ranges.add(new UidRange(uid, uid));
   5876         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   5877         mMockVpn.setUids(ranges);
   5878         vpnNetworkAgent.connect(true);
   5879         mMockVpn.connectAsAlwaysMetered();
   5880         waitForIdle();
   5881         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   5882 
   5883         // VPN is tracking current platform default (WiFi).
   5884         mService.setUnderlyingNetworksForVpn(null);
   5885         waitForIdle();
   5886 
   5887         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
   5888         assertTrue(mCm.isActiveNetworkMetered());
   5889 
   5890         // VPN explicitly declares WiFi as its underlying network.
   5891         mService.setUnderlyingNetworksForVpn(
   5892                 new Network[] { mWiFiNetworkAgent.getNetwork() });
   5893         waitForIdle();
   5894 
   5895         // Doesn't really matter whether VPN declares its underlying networks explicitly.
   5896         assertTrue(mCm.isActiveNetworkMetered());
   5897 
   5898         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
   5899         // anyways suppose to be metered.
   5900         mWiFiNetworkAgent.disconnect();
   5901         waitForIdle();
   5902 
   5903         assertTrue(mCm.isActiveNetworkMetered());
   5904 
   5905         vpnNetworkAgent.disconnect();
   5906     }
   5907 
   5908     @Test
   5909     public void testNetworkBlockedStatus() {
   5910         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   5911         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   5912                 .addTransportType(TRANSPORT_CELLULAR)
   5913                 .build();
   5914         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   5915 
   5916         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5917         mCellNetworkAgent.connect(true);
   5918         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   5919 
   5920         mService.setUidRulesChanged(RULE_REJECT_ALL);
   5921         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
   5922 
   5923         // ConnectivityService should cache it not to invoke the callback again.
   5924         mService.setUidRulesChanged(RULE_REJECT_METERED);
   5925         cellNetworkCallback.assertNoCallback();
   5926 
   5927         mService.setUidRulesChanged(RULE_NONE);
   5928         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
   5929 
   5930         mService.setUidRulesChanged(RULE_REJECT_METERED);
   5931         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
   5932 
   5933         // Restrict the network based on UID rule and NOT_METERED capability change.
   5934         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5935         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
   5936         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
   5937         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   5938         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
   5939                 mCellNetworkAgent);
   5940         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
   5941         mService.setUidRulesChanged(RULE_ALLOW_METERED);
   5942         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
   5943 
   5944         mService.setUidRulesChanged(RULE_NONE);
   5945         cellNetworkCallback.assertNoCallback();
   5946 
   5947         // Restrict the network based on BackgroundRestricted.
   5948         mService.setRestrictBackgroundChanged(true);
   5949         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
   5950         mService.setRestrictBackgroundChanged(true);
   5951         cellNetworkCallback.assertNoCallback();
   5952         mService.setRestrictBackgroundChanged(false);
   5953         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
   5954         cellNetworkCallback.assertNoCallback();
   5955 
   5956         mCm.unregisterNetworkCallback(cellNetworkCallback);
   5957     }
   5958 
   5959     @Test
   5960     public void testNetworkBlockedStatusBeforeAndAfterConnect() {
   5961         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
   5962         mCm.registerDefaultNetworkCallback(defaultCallback);
   5963 
   5964         // No Networkcallbacks invoked before any network is active.
   5965         mService.setUidRulesChanged(RULE_REJECT_ALL);
   5966         mService.setUidRulesChanged(RULE_NONE);
   5967         mService.setUidRulesChanged(RULE_REJECT_METERED);
   5968         defaultCallback.assertNoCallback();
   5969 
   5970         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   5971         mCellNetworkAgent.connect(true);
   5972         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
   5973         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
   5974 
   5975         // Allow to use the network after switching to NOT_METERED network.
   5976         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   5977         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5978         mWiFiNetworkAgent.connect(true);
   5979         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   5980 
   5981         // Switch to METERED network. Restrict the use of the network.
   5982         mWiFiNetworkAgent.disconnect();
   5983         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   5984         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
   5985 
   5986         // Network becomes NOT_METERED.
   5987         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   5988         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
   5989         defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
   5990 
   5991         // Verify there's no Networkcallbacks invoked after data saver on/off.
   5992         mService.setRestrictBackgroundChanged(true);
   5993         mService.setRestrictBackgroundChanged(false);
   5994         defaultCallback.assertNoCallback();
   5995 
   5996         mCellNetworkAgent.disconnect();
   5997         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   5998         defaultCallback.assertNoCallback();
   5999 
   6000         mCm.unregisterNetworkCallback(defaultCallback);
   6001     }
   6002 
   6003     /**
   6004      * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
   6005      */
   6006     private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
   6007         InterfaceConfiguration cfg = new InterfaceConfiguration();
   6008         cfg.setHardwareAddress("11:22:33:44:55:66");
   6009         cfg.setLinkAddress(la);
   6010         return cfg;
   6011     }
   6012 
   6013     /**
   6014      * Make expected stack link properties, copied from Nat464Xlat.
   6015      */
   6016     private LinkProperties makeClatLinkProperties(LinkAddress la) {
   6017         LinkAddress clatAddress = la;
   6018         LinkProperties stacked = new LinkProperties();
   6019         stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
   6020         RouteInfo ipv4Default = new RouteInfo(
   6021                 new LinkAddress(Inet4Address.ANY, 0),
   6022                 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
   6023         stacked.addRoute(ipv4Default);
   6024         stacked.addLinkAddress(clatAddress);
   6025         return stacked;
   6026     }
   6027 
   6028     @Test
   6029     public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
   6030         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
   6031         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
   6032         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
   6033         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
   6034 
   6035         final NetworkRequest networkRequest = new NetworkRequest.Builder()
   6036                 .addTransportType(TRANSPORT_CELLULAR)
   6037                 .addCapability(NET_CAPABILITY_INTERNET)
   6038                 .build();
   6039         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   6040         mCm.registerNetworkCallback(networkRequest, networkCallback);
   6041 
   6042         // Prepare ipv6 only link properties.
   6043         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   6044         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
   6045         final LinkProperties cellLp = new LinkProperties();
   6046         cellLp.setInterfaceName(MOBILE_IFNAME);
   6047         cellLp.addLinkAddress(myIpv6);
   6048         cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
   6049         cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
   6050         reset(mNetworkManagementService);
   6051         reset(mMockDnsResolver);
   6052         reset(mMockNetd);
   6053         when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
   6054                 .thenReturn(getClatInterfaceConfig(myIpv4));
   6055 
   6056         // Connect with ipv6 link properties. Expect prefix discovery to be started.
   6057         mCellNetworkAgent.sendLinkProperties(cellLp);
   6058         mCellNetworkAgent.connect(true);
   6059 
   6060         verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
   6061         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
   6062 
   6063         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   6064         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
   6065 
   6066         // Switching default network updates TCP buffer sizes.
   6067         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
   6068 
   6069         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
   6070         // the NAT64 prefix was removed because one was never discovered.
   6071         cellLp.addLinkAddress(myIpv4);
   6072         mCellNetworkAgent.sendLinkProperties(cellLp);
   6073         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6074         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
   6075         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
   6076 
   6077         verifyNoMoreInteractions(mMockNetd);
   6078         verifyNoMoreInteractions(mMockDnsResolver);
   6079         reset(mMockNetd);
   6080         reset(mMockDnsResolver);
   6081 
   6082         // Remove IPv4 address. Expect prefix discovery to be started again.
   6083         cellLp.removeLinkAddress(myIpv4);
   6084         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
   6085         mCellNetworkAgent.sendLinkProperties(cellLp);
   6086         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6087         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
   6088 
   6089         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
   6090         Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
   6091         assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
   6092         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
   6093                 kNat64PrefixString, 96);
   6094         LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
   6095                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
   6096         assertEquals(0, lpBeforeClat.getStackedLinks().size());
   6097         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
   6098         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
   6099 
   6100         // Clat iface comes up. Expect stacked link to be added.
   6101         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
   6102         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6103         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
   6104                 .getStackedLinks();
   6105         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
   6106 
   6107         // Change trivial linkproperties and see if stacked link is preserved.
   6108         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
   6109         mCellNetworkAgent.sendLinkProperties(cellLp);
   6110         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6111 
   6112         List<LinkProperties> stackedLpsAfterChange =
   6113                 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
   6114         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
   6115         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
   6116 
   6117         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
   6118                 mResolverParamsParcelCaptor.capture());
   6119         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
   6120         assertEquals(1, resolvrParams.servers.length);
   6121         assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
   6122 
   6123         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
   6124         // linkproperties are cleaned up.
   6125         cellLp.addLinkAddress(myIpv4);
   6126         cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
   6127         mCellNetworkAgent.sendLinkProperties(cellLp);
   6128         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6129         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
   6130         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
   6131 
   6132         // As soon as stop is called, the linkproperties lose the stacked interface.
   6133         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6134         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
   6135         LinkProperties expected = new LinkProperties(cellLp);
   6136         expected.setNat64Prefix(kNat64Prefix);
   6137         assertEquals(expected, actualLpAfterIpv4);
   6138         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
   6139 
   6140         // The interface removed callback happens but has no effect after stop is called.
   6141         clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
   6142         networkCallback.assertNoCallback();
   6143 
   6144         verifyNoMoreInteractions(mMockNetd);
   6145         verifyNoMoreInteractions(mMockDnsResolver);
   6146         reset(mMockNetd);
   6147         reset(mMockDnsResolver);
   6148 
   6149         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
   6150         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
   6151                 kNat64PrefixString, 96);
   6152         networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
   6153                 mCellNetworkAgent);
   6154 
   6155         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
   6156         cellLp.removeLinkAddress(myIpv4);
   6157         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
   6158         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
   6159         mCellNetworkAgent.sendLinkProperties(cellLp);
   6160         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6161         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
   6162         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
   6163                 kNat64PrefixString, 96);
   6164         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   6165         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
   6166 
   6167 
   6168         // Clat iface comes up. Expect stacked link to be added.
   6169         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
   6170         networkCallback.expectLinkPropertiesLike(
   6171                 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
   6172                 mCellNetworkAgent);
   6173 
   6174         // NAT64 prefix is removed. Expect that clat is stopped.
   6175         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
   6176                 kNat64PrefixString, 96);
   6177         networkCallback.expectLinkPropertiesLike(
   6178                 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
   6179                 mCellNetworkAgent);
   6180         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
   6181         networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
   6182                 mCellNetworkAgent);
   6183 
   6184         // Clean up.
   6185         mCellNetworkAgent.disconnect();
   6186         networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   6187         networkCallback.assertNoCallback();
   6188         mCm.unregisterNetworkCallback(networkCallback);
   6189     }
   6190 
   6191     @Test
   6192     public void testDataActivityTracking() throws RemoteException {
   6193         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   6194         final NetworkRequest networkRequest = new NetworkRequest.Builder()
   6195                 .addCapability(NET_CAPABILITY_INTERNET)
   6196                 .build();
   6197         mCm.registerNetworkCallback(networkRequest, networkCallback);
   6198 
   6199         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   6200         final LinkProperties cellLp = new LinkProperties();
   6201         cellLp.setInterfaceName(MOBILE_IFNAME);
   6202         mCellNetworkAgent.sendLinkProperties(cellLp);
   6203         reset(mNetworkManagementService);
   6204         mCellNetworkAgent.connect(true);
   6205         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   6206         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
   6207                 eq(ConnectivityManager.TYPE_MOBILE));
   6208 
   6209         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   6210         final LinkProperties wifiLp = new LinkProperties();
   6211         wifiLp.setInterfaceName(WIFI_IFNAME);
   6212         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
   6213 
   6214         // Network switch
   6215         reset(mNetworkManagementService);
   6216         mWiFiNetworkAgent.connect(true);
   6217         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   6218         networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   6219         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   6220         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
   6221                 eq(ConnectivityManager.TYPE_WIFI));
   6222         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
   6223 
   6224         // Disconnect wifi and switch back to cell
   6225         reset(mNetworkManagementService);
   6226         mWiFiNetworkAgent.disconnect();
   6227         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   6228         assertNoCallbacks(networkCallback);
   6229         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
   6230         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
   6231                 eq(ConnectivityManager.TYPE_MOBILE));
   6232 
   6233         // reconnect wifi
   6234         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   6235         wifiLp.setInterfaceName(WIFI_IFNAME);
   6236         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
   6237         mWiFiNetworkAgent.connect(true);
   6238         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   6239         networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   6240         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   6241 
   6242         // Disconnect cell
   6243         reset(mNetworkManagementService);
   6244         reset(mMockNetd);
   6245         mCellNetworkAgent.disconnect();
   6246         networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   6247         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
   6248         // sent as network being switched. Ensure rule removal for cell will not be triggered
   6249         // unexpectedly before network being removed.
   6250         waitForIdle();
   6251         verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
   6252         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
   6253         verify(mMockDnsResolver, times(1))
   6254                 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
   6255 
   6256         // Disconnect wifi
   6257         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   6258         reset(mNetworkManagementService);
   6259         mWiFiNetworkAgent.disconnect();
   6260         waitFor(cv);
   6261         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
   6262 
   6263         // Clean up
   6264         mCm.unregisterNetworkCallback(networkCallback);
   6265     }
   6266 
   6267     private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
   6268         String[] values = tcpBufferSizes.split(",");
   6269         String rmemValues = String.join(" ", values[0], values[1], values[2]);
   6270         String wmemValues = String.join(" ", values[3], values[4], values[5]);
   6271         waitForIdle();
   6272         try {
   6273             verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
   6274         } catch (RemoteException e) {
   6275             fail("mMockNetd should never throw RemoteException");
   6276         }
   6277         reset(mMockNetd);
   6278     }
   6279 
   6280     @Test
   6281     public void testTcpBufferReset() {
   6282         final String testTcpBufferSizes = "1,2,3,4,5,6";
   6283 
   6284         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   6285         reset(mMockNetd);
   6286         // Switching default network updates TCP buffer sizes.
   6287         mCellNetworkAgent.connect(false);
   6288         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
   6289 
   6290         // Change link Properties should have updated tcp buffer size.
   6291         LinkProperties lp = new LinkProperties();
   6292         lp.setTcpBufferSizes(testTcpBufferSizes);
   6293         mCellNetworkAgent.sendLinkProperties(lp);
   6294         verifyTcpBufferSizeChange(testTcpBufferSizes);
   6295     }
   6296 
   6297     @Test
   6298     public void testGetGlobalProxyForNetwork() {
   6299         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
   6300         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   6301         final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
   6302         when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
   6303         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
   6304     }
   6305 
   6306     @Test
   6307     public void testGetProxyForActiveNetwork() {
   6308         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
   6309         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   6310         mWiFiNetworkAgent.connect(true);
   6311         waitForIdle();
   6312         assertNull(mService.getProxyForNetwork(null));
   6313 
   6314         final LinkProperties testLinkProperties = new LinkProperties();
   6315         testLinkProperties.setHttpProxy(testProxyInfo);
   6316 
   6317         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
   6318         waitForIdle();
   6319 
   6320         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
   6321     }
   6322 
   6323     @Test
   6324     public void testGetProxyForVPN() {
   6325         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
   6326 
   6327         // Set up a WiFi network with no proxy
   6328         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   6329         mWiFiNetworkAgent.connect(true);
   6330         waitForIdle();
   6331         assertNull(mService.getProxyForNetwork(null));
   6332 
   6333         // Set up a VPN network with a proxy
   6334         final int uid = Process.myUid();
   6335         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   6336         final ArraySet<UidRange> ranges = new ArraySet<>();
   6337         ranges.add(new UidRange(uid, uid));
   6338         mMockVpn.setUids(ranges);
   6339         LinkProperties testLinkProperties = new LinkProperties();
   6340         testLinkProperties.setHttpProxy(testProxyInfo);
   6341         vpnNetworkAgent.sendLinkProperties(testLinkProperties);
   6342         waitForIdle();
   6343 
   6344         // Connect to VPN with proxy
   6345         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   6346         vpnNetworkAgent.connect(true);
   6347         mMockVpn.connect();
   6348         waitForIdle();
   6349 
   6350         // Test that the VPN network returns a proxy, and the WiFi does not.
   6351         assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
   6352         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
   6353         assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
   6354 
   6355         // Test that the VPN network returns no proxy when it is set to null.
   6356         testLinkProperties.setHttpProxy(null);
   6357         vpnNetworkAgent.sendLinkProperties(testLinkProperties);
   6358         waitForIdle();
   6359         assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
   6360         assertNull(mService.getProxyForNetwork(null));
   6361 
   6362         // Set WiFi proxy and check that the vpn proxy is still null.
   6363         testLinkProperties.setHttpProxy(testProxyInfo);
   6364         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
   6365         waitForIdle();
   6366         assertNull(mService.getProxyForNetwork(null));
   6367 
   6368         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
   6369         // correct proxy setting.
   6370         vpnNetworkAgent.disconnect();
   6371         waitForIdle();
   6372         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   6373         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
   6374         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
   6375     }
   6376 
   6377     @Test
   6378     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
   6379         LinkProperties lp = new LinkProperties();
   6380         lp.setInterfaceName("tun0");
   6381         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
   6382         // The uid range needs to cover the test app so the network is visible to it.
   6383         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
   6384         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
   6385 
   6386         // Connected VPN should have interface rules set up. There are two expected invocations,
   6387         // one during VPN uid update, one during VPN LinkProperties update
   6388         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
   6389         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
   6390         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
   6391         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
   6392         assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
   6393 
   6394         vpnNetworkAgent.disconnect();
   6395         waitForIdle();
   6396 
   6397         // Disconnected VPN should have interface rules removed
   6398         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
   6399         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
   6400         assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
   6401     }
   6402 
   6403     @Test
   6404     public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
   6405         LinkProperties lp = new LinkProperties();
   6406         lp.setInterfaceName("tun0");
   6407         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
   6408         // The uid range needs to cover the test app so the network is visible to it.
   6409         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
   6410         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
   6411 
   6412         // Legacy VPN should not have interface rules set up
   6413         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
   6414     }
   6415 
   6416     @Test
   6417     public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
   6418             throws Exception {
   6419         LinkProperties lp = new LinkProperties();
   6420         lp.setInterfaceName("tun0");
   6421         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
   6422         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
   6423         // The uid range needs to cover the test app so the network is visible to it.
   6424         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
   6425         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
   6426 
   6427         // IPv6 unreachable route should not be misinterpreted as a default route
   6428         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
   6429     }
   6430 
   6431     @Test
   6432     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
   6433         LinkProperties lp = new LinkProperties();
   6434         lp.setInterfaceName("tun0");
   6435         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
   6436         // The uid range needs to cover the test app so the network is visible to it.
   6437         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
   6438         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
   6439 
   6440         // Connected VPN should have interface rules set up. There are two expected invocations,
   6441         // one during VPN uid update, one during VPN LinkProperties update
   6442         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
   6443         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
   6444         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
   6445         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
   6446 
   6447         reset(mMockNetd);
   6448         InOrder inOrder = inOrder(mMockNetd);
   6449         lp.setInterfaceName("tun1");
   6450         vpnNetworkAgent.sendLinkProperties(lp);
   6451         waitForIdle();
   6452         // VPN handover (switch to a new interface) should result in rules being updated (old rules
   6453         // removed first, then new rules added)
   6454         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
   6455         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
   6456         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
   6457         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
   6458 
   6459         reset(mMockNetd);
   6460         lp = new LinkProperties();
   6461         lp.setInterfaceName("tun1");
   6462         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
   6463         vpnNetworkAgent.sendLinkProperties(lp);
   6464         waitForIdle();
   6465         // VPN not routing everything should no longer have interface filtering rules
   6466         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
   6467         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
   6468 
   6469         reset(mMockNetd);
   6470         lp = new LinkProperties();
   6471         lp.setInterfaceName("tun1");
   6472         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
   6473         vpnNetworkAgent.sendLinkProperties(lp);
   6474         waitForIdle();
   6475         // Back to routing all IPv6 traffic should have filtering rules
   6476         verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
   6477         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
   6478     }
   6479 
   6480     @Test
   6481     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
   6482         LinkProperties lp = new LinkProperties();
   6483         lp.setInterfaceName("tun0");
   6484         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
   6485         // The uid range needs to cover the test app so the network is visible to it.
   6486         final UidRange vpnRange = UidRange.createForUser(VPN_USER);
   6487         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
   6488                 Collections.singleton(vpnRange));
   6489 
   6490         reset(mMockNetd);
   6491         InOrder inOrder = inOrder(mMockNetd);
   6492 
   6493         // Update to new range which is old range minus APP1, i.e. only APP2
   6494         final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
   6495                 new UidRange(vpnRange.start, APP1_UID - 1),
   6496                 new UidRange(APP1_UID + 1, vpnRange.stop)));
   6497         vpnNetworkAgent.setUids(newRanges);
   6498         waitForIdle();
   6499 
   6500         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
   6501         // Verify old rules are removed before new rules are added
   6502         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
   6503         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
   6504         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
   6505         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
   6506     }
   6507 
   6508 
   6509     private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
   6510             Set<UidRange> vpnRange) {
   6511         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
   6512         vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
   6513         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   6514         mMockVpn.connect();
   6515         mMockVpn.setUids(vpnRange);
   6516         vpnNetworkAgent.connect(true);
   6517         waitForIdle();
   6518         return vpnNetworkAgent;
   6519     }
   6520 
   6521     private void assertContainsExactly(int[] actual, int... expected) {
   6522         int[] sortedActual = Arrays.copyOf(actual, actual.length);
   6523         int[] sortedExpected = Arrays.copyOf(expected, expected.length);
   6524         Arrays.sort(sortedActual);
   6525         Arrays.sort(sortedExpected);
   6526         assertArrayEquals(sortedExpected, sortedActual);
   6527     }
   6528 
   6529     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
   6530         final PackageInfo packageInfo = new PackageInfo();
   6531         packageInfo.requestedPermissions = new String[0];
   6532         packageInfo.applicationInfo = new ApplicationInfo();
   6533         packageInfo.applicationInfo.privateFlags = 0;
   6534         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
   6535                 UserHandle.getAppId(uid));
   6536         return packageInfo;
   6537     }
   6538 }
   6539