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.net.ConnectivityManager.CONNECTIVITY_ACTION;
     20 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
     21 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
     22 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
     23 import static android.net.ConnectivityManager.TYPE_ETHERNET;
     24 import static android.net.ConnectivityManager.TYPE_MOBILE;
     25 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
     26 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
     27 import static android.net.ConnectivityManager.TYPE_NONE;
     28 import static android.net.ConnectivityManager.TYPE_WIFI;
     29 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
     30 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
     31 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
     32 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
     33 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
     34 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
     35 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
     36 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
     37 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
     38 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
     39 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
     40 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
     41 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
     42 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
     43 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
     44 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
     45 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
     46 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
     47 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
     48 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
     49 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
     50 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
     51 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
     52 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
     53 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
     54 
     55 import static com.android.internal.util.TestUtils.waitForIdleHandler;
     56 import static com.android.internal.util.TestUtils.waitForIdleLooper;
     57 
     58 import static org.junit.Assert.assertEquals;
     59 import static org.junit.Assert.assertFalse;
     60 import static org.junit.Assert.assertNotNull;
     61 import static org.junit.Assert.assertNull;
     62 import static org.junit.Assert.assertTrue;
     63 import static org.junit.Assert.fail;
     64 import static org.mockito.Matchers.anyBoolean;
     65 import static org.mockito.Matchers.anyInt;
     66 import static org.mockito.Matchers.anyString;
     67 import static org.mockito.Mockito.any;
     68 import static org.mockito.Mockito.atLeastOnce;
     69 import static org.mockito.Mockito.eq;
     70 import static org.mockito.Mockito.mock;
     71 import static org.mockito.Mockito.never;
     72 import static org.mockito.Mockito.reset;
     73 import static org.mockito.Mockito.spy;
     74 import static org.mockito.Mockito.times;
     75 import static org.mockito.Mockito.verify;
     76 import static org.mockito.Mockito.verifyNoMoreInteractions;
     77 import static org.mockito.Mockito.when;
     78 
     79 
     80 import android.app.NotificationManager;
     81 import android.app.PendingIntent;
     82 import android.content.BroadcastReceiver;
     83 import android.content.ContentResolver;
     84 import android.content.Context;
     85 import android.content.Intent;
     86 import android.content.IntentFilter;
     87 import android.content.pm.UserInfo;
     88 import android.content.res.Resources;
     89 import android.net.CaptivePortal;
     90 import android.net.ConnectivityManager;
     91 import android.net.ConnectivityManager.NetworkCallback;
     92 import android.net.ConnectivityManager.PacketKeepalive;
     93 import android.net.ConnectivityManager.PacketKeepaliveCallback;
     94 import android.net.ConnectivityManager.TooManyRequestsException;
     95 import android.net.ConnectivityThread;
     96 import android.net.INetworkPolicyManager;
     97 import android.net.INetworkStatsService;
     98 import android.net.IpPrefix;
     99 import android.net.LinkAddress;
    100 import android.net.LinkProperties;
    101 import android.net.MatchAllNetworkSpecifier;
    102 import android.net.Network;
    103 import android.net.NetworkAgent;
    104 import android.net.NetworkCapabilities;
    105 import android.net.NetworkFactory;
    106 import android.net.NetworkInfo;
    107 import android.net.NetworkInfo.DetailedState;
    108 import android.net.NetworkMisc;
    109 import android.net.NetworkRequest;
    110 import android.net.NetworkSpecifier;
    111 import android.net.NetworkUtils;
    112 import android.net.RouteInfo;
    113 import android.net.StringNetworkSpecifier;
    114 import android.net.UidRange;
    115 import android.net.VpnService;
    116 import android.net.captiveportal.CaptivePortalProbeResult;
    117 import android.net.metrics.IpConnectivityLog;
    118 import android.net.util.MultinetworkPolicyTracker;
    119 import android.os.ConditionVariable;
    120 import android.os.Handler;
    121 import android.os.HandlerThread;
    122 import android.os.INetworkManagementService;
    123 import android.os.Looper;
    124 import android.os.Message;
    125 import android.os.Parcel;
    126 import android.os.Parcelable;
    127 import android.os.Process;
    128 import android.os.SystemClock;
    129 import android.os.UserHandle;
    130 import android.provider.Settings;
    131 import android.support.test.InstrumentationRegistry;
    132 import android.support.test.filters.SmallTest;
    133 import android.support.test.runner.AndroidJUnit4;
    134 import android.test.mock.MockContentResolver;
    135 import android.util.ArraySet;
    136 import android.util.Log;
    137 
    138 import com.android.internal.net.VpnConfig;
    139 import com.android.internal.util.ArrayUtils;
    140 import com.android.internal.util.WakeupMessage;
    141 import com.android.internal.util.test.BroadcastInterceptingContext;
    142 import com.android.internal.util.test.FakeSettingsProvider;
    143 import com.android.server.connectivity.ConnectivityConstants;
    144 import com.android.server.connectivity.DefaultNetworkMetrics;
    145 import com.android.server.connectivity.DnsManager;
    146 import com.android.server.connectivity.IpConnectivityMetrics;
    147 import com.android.server.connectivity.MockableSystemProperties;
    148 import com.android.server.connectivity.NetworkAgentInfo;
    149 import com.android.server.connectivity.NetworkMonitor;
    150 import com.android.server.connectivity.Vpn;
    151 import com.android.server.net.NetworkPinner;
    152 import com.android.server.net.NetworkPolicyManagerInternal;
    153 
    154 import org.junit.After;
    155 import org.junit.Before;
    156 import org.junit.Ignore;
    157 import org.junit.Test;
    158 import org.junit.runner.RunWith;
    159 import org.mockito.ArgumentCaptor;
    160 import org.mockito.Mock;
    161 import org.mockito.MockitoAnnotations;
    162 import org.mockito.Spy;
    163 
    164 import java.net.InetAddress;
    165 import java.util.ArrayList;
    166 import java.util.Arrays;
    167 import java.util.Collection;
    168 import java.util.HashSet;
    169 import java.util.List;
    170 import java.util.Objects;
    171 import java.util.Set;
    172 import java.util.concurrent.CountDownLatch;
    173 import java.util.concurrent.LinkedBlockingQueue;
    174 import java.util.concurrent.TimeUnit;
    175 import java.util.concurrent.atomic.AtomicBoolean;
    176 import java.util.function.Predicate;
    177 
    178 
    179 /**
    180  * Tests for {@link ConnectivityService}.
    181  *
    182  * Build, install and run with:
    183  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
    184  */
    185 @RunWith(AndroidJUnit4.class)
    186 @SmallTest
    187 public class ConnectivityServiceTest {
    188     private static final String TAG = "ConnectivityServiceTest";
    189 
    190     private static final int TIMEOUT_MS = 500;
    191     private static final int TEST_LINGER_DELAY_MS = 120;
    192 
    193     private static final String MOBILE_IFNAME = "test_rmnet_data0";
    194     private static final String WIFI_IFNAME = "test_wlan0";
    195 
    196     private MockContext mServiceContext;
    197     private WrappedConnectivityService mService;
    198     private WrappedConnectivityManager mCm;
    199     private MockNetworkAgent mWiFiNetworkAgent;
    200     private MockNetworkAgent mCellNetworkAgent;
    201     private MockNetworkAgent mEthernetNetworkAgent;
    202     private MockVpn mMockVpn;
    203     private Context mContext;
    204 
    205     @Mock IpConnectivityMetrics.Logger mMetricsService;
    206     @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
    207     @Mock INetworkManagementService mNetworkManagementService;
    208     @Mock INetworkStatsService mStatsService;
    209 
    210     private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
    211 
    212     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
    213     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
    214     // reflect the state of our test ConnectivityService.
    215     private class WrappedConnectivityManager extends ConnectivityManager {
    216         private Network mFakeBoundNetwork;
    217 
    218         public synchronized boolean bindProcessToNetwork(Network network) {
    219             mFakeBoundNetwork = network;
    220             return true;
    221         }
    222 
    223         public synchronized Network getBoundNetworkForProcess() {
    224             return mFakeBoundNetwork;
    225         }
    226 
    227         public WrappedConnectivityManager(Context context, ConnectivityService service) {
    228             super(context, service);
    229         }
    230     }
    231 
    232     private class MockContext extends BroadcastInterceptingContext {
    233         private final MockContentResolver mContentResolver;
    234 
    235         @Spy private Resources mResources;
    236         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
    237 
    238         MockContext(Context base) {
    239             super(base);
    240 
    241             mResources = spy(base.getResources());
    242             when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
    243                     thenReturn(new String[] {
    244                             "wifi,1,1,1,-1,true",
    245                             "mobile,0,0,0,-1,true",
    246                             "mobile_mms,2,0,2,60000,true",
    247                     });
    248 
    249             mContentResolver = new MockContentResolver();
    250             mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
    251         }
    252 
    253         @Override
    254         public void startActivityAsUser(Intent intent, UserHandle handle) {
    255             mStartedActivities.offer(intent);
    256         }
    257 
    258         public Intent expectStartActivityIntent(int timeoutMs) {
    259             Intent intent = null;
    260             try {
    261                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
    262             } catch (InterruptedException e) {}
    263             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
    264             return intent;
    265         }
    266 
    267         public void expectNoStartActivityIntent(int timeoutMs) {
    268             try {
    269                 assertNull("Received unexpected Intent to start activity",
    270                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
    271             } catch (InterruptedException e) {}
    272         }
    273 
    274         @Override
    275         public Object getSystemService(String name) {
    276             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
    277             if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
    278             return super.getSystemService(name);
    279         }
    280 
    281         @Override
    282         public ContentResolver getContentResolver() {
    283             return mContentResolver;
    284         }
    285 
    286         @Override
    287         public Resources getResources() {
    288             return mResources;
    289         }
    290     }
    291 
    292     public void waitForIdle(int timeoutMsAsInt) {
    293         long timeoutMs = timeoutMsAsInt;
    294         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
    295         waitForIdle(mCellNetworkAgent, timeoutMs);
    296         waitForIdle(mWiFiNetworkAgent, timeoutMs);
    297         waitForIdle(mEthernetNetworkAgent, timeoutMs);
    298         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
    299         waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
    300     }
    301 
    302     public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
    303         if (agent == null) {
    304             return;
    305         }
    306         waitForIdleHandler(agent.mHandlerThread, timeoutMs);
    307     }
    308 
    309     private void waitForIdle() {
    310         waitForIdle(TIMEOUT_MS);
    311     }
    312 
    313     @Test
    314     public void testWaitForIdle() {
    315         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
    316 
    317         // Tests that waitForIdle returns immediately if the service is already idle.
    318         for (int i = 0; i < attempts; i++) {
    319             waitForIdle();
    320         }
    321 
    322         // Bring up a network that we can use to send messages to ConnectivityService.
    323         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    324         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    325         mWiFiNetworkAgent.connect(false);
    326         waitFor(cv);
    327         Network n = mWiFiNetworkAgent.getNetwork();
    328         assertNotNull(n);
    329 
    330         // Tests that calling waitForIdle waits for messages to be processed.
    331         for (int i = 0; i < attempts; i++) {
    332             mWiFiNetworkAgent.setSignalStrength(i);
    333             waitForIdle();
    334             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
    335         }
    336     }
    337 
    338     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
    339     // or presubmit tests. It is kept for manual runs and documentation purposes.
    340     @Ignore
    341     public void verifyThatNotWaitingForIdleCausesRaceConditions() {
    342         // Bring up a network that we can use to send messages to ConnectivityService.
    343         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    344         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    345         mWiFiNetworkAgent.connect(false);
    346         waitFor(cv);
    347         Network n = mWiFiNetworkAgent.getNetwork();
    348         assertNotNull(n);
    349 
    350         // Ensure that not calling waitForIdle causes a race condition.
    351         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
    352         for (int i = 0; i < attempts; i++) {
    353             mWiFiNetworkAgent.setSignalStrength(i);
    354             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
    355                 // We hit a race condition, as expected. Pass the test.
    356                 return;
    357             }
    358         }
    359 
    360         // No race? There is a bug in this test.
    361         fail("expected race condition at least once in " + attempts + " attempts");
    362     }
    363 
    364     private class MockNetworkAgent {
    365         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
    366         private final NetworkInfo mNetworkInfo;
    367         private final NetworkCapabilities mNetworkCapabilities;
    368         private final HandlerThread mHandlerThread;
    369         private final ConditionVariable mDisconnected = new ConditionVariable();
    370         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
    371         private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
    372         private int mScore;
    373         private NetworkAgent mNetworkAgent;
    374         private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
    375         private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
    376         private Integer mExpectedKeepaliveSlot = null;
    377         // Contains the redirectUrl from networkStatus(). Before reading, wait for
    378         // mNetworkStatusReceived.
    379         private String mRedirectUrl;
    380 
    381         MockNetworkAgent(int transport) {
    382             this(transport, new LinkProperties());
    383         }
    384 
    385         MockNetworkAgent(int transport, LinkProperties linkProperties) {
    386             final int type = transportToLegacyType(transport);
    387             final String typeName = ConnectivityManager.getNetworkTypeName(transport);
    388             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
    389             mNetworkCapabilities = new NetworkCapabilities();
    390             mNetworkCapabilities.addTransportType(transport);
    391             switch (transport) {
    392                 case TRANSPORT_ETHERNET:
    393                     mScore = 70;
    394                     break;
    395                 case TRANSPORT_WIFI:
    396                     mScore = 60;
    397                     break;
    398                 case TRANSPORT_CELLULAR:
    399                     mScore = 50;
    400                     break;
    401                 case TRANSPORT_WIFI_AWARE:
    402                     mScore = 20;
    403                     break;
    404                 case TRANSPORT_VPN:
    405                     mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
    406                     mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
    407                     break;
    408                 default:
    409                     throw new UnsupportedOperationException("unimplemented network type");
    410             }
    411             mHandlerThread = new HandlerThread("Mock-" + typeName);
    412             mHandlerThread.start();
    413             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
    414                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
    415                     linkProperties, mScore, new NetworkMisc()) {
    416                 @Override
    417                 public void unwanted() { mDisconnected.open(); }
    418 
    419                 @Override
    420                 public void startPacketKeepalive(Message msg) {
    421                     int slot = msg.arg1;
    422                     if (mExpectedKeepaliveSlot != null) {
    423                         assertEquals((int) mExpectedKeepaliveSlot, slot);
    424                     }
    425                     onPacketKeepaliveEvent(slot, mStartKeepaliveError);
    426                 }
    427 
    428                 @Override
    429                 public void stopPacketKeepalive(Message msg) {
    430                     onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
    431                 }
    432 
    433                 @Override
    434                 public void networkStatus(int status, String redirectUrl) {
    435                     mRedirectUrl = redirectUrl;
    436                     mNetworkStatusReceived.open();
    437                 }
    438 
    439                 @Override
    440                 protected void preventAutomaticReconnect() {
    441                     mPreventReconnectReceived.open();
    442                 }
    443             };
    444             // Waits for the NetworkAgent to be registered, which includes the creation of the
    445             // NetworkMonitor.
    446             waitForIdle();
    447             mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
    448         }
    449 
    450         public void adjustScore(int change) {
    451             mScore += change;
    452             mNetworkAgent.sendNetworkScore(mScore);
    453         }
    454 
    455         public void explicitlySelected(boolean acceptUnvalidated) {
    456             mNetworkAgent.explicitlySelected(acceptUnvalidated);
    457         }
    458 
    459         public void addCapability(int capability) {
    460             mNetworkCapabilities.addCapability(capability);
    461             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    462         }
    463 
    464         public void removeCapability(int capability) {
    465             mNetworkCapabilities.removeCapability(capability);
    466             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    467         }
    468 
    469         public void setUids(Set<UidRange> uids) {
    470             mNetworkCapabilities.setUids(uids);
    471             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    472         }
    473 
    474         public void setSignalStrength(int signalStrength) {
    475             mNetworkCapabilities.setSignalStrength(signalStrength);
    476             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    477         }
    478 
    479         public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
    480             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
    481             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    482         }
    483 
    484         public void setNetworkCapabilities(NetworkCapabilities nc,
    485                 boolean sendToConnectivityService) {
    486             mNetworkCapabilities.set(nc);
    487             if (sendToConnectivityService) {
    488                 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    489             }
    490         }
    491 
    492         public void connectWithoutInternet() {
    493             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
    494             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    495         }
    496 
    497         /**
    498          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
    499          * @param validated Indicate if network should pretend to be validated.
    500          */
    501         public void connect(boolean validated) {
    502             connect(validated, true);
    503         }
    504 
    505         /**
    506          * Transition this NetworkAgent to CONNECTED state.
    507          * @param validated Indicate if network should pretend to be validated.
    508          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
    509          */
    510         public void connect(boolean validated, boolean hasInternet) {
    511             assertEquals("MockNetworkAgents can only be connected once",
    512                     mNetworkInfo.getDetailedState(), DetailedState.IDLE);
    513             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
    514 
    515             NetworkCallback callback = null;
    516             final ConditionVariable validatedCv = new ConditionVariable();
    517             if (validated) {
    518                 mWrappedNetworkMonitor.gen204ProbeResult = 204;
    519                 NetworkRequest request = new NetworkRequest.Builder()
    520                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
    521                         .clearCapabilities()
    522                         .build();
    523                 callback = new NetworkCallback() {
    524                     public void onCapabilitiesChanged(Network network,
    525                             NetworkCapabilities networkCapabilities) {
    526                         if (network.equals(getNetwork()) &&
    527                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
    528                             validatedCv.open();
    529                         }
    530                     }
    531                 };
    532                 mCm.registerNetworkCallback(request, callback);
    533             }
    534             if (hasInternet) {
    535                 addCapability(NET_CAPABILITY_INTERNET);
    536             }
    537 
    538             connectWithoutInternet();
    539 
    540             if (validated) {
    541                 // Wait for network to validate.
    542                 waitFor(validatedCv);
    543                 mWrappedNetworkMonitor.gen204ProbeResult = 500;
    544             }
    545 
    546             if (callback != null) mCm.unregisterNetworkCallback(callback);
    547         }
    548 
    549         public void connectWithCaptivePortal(String redirectUrl) {
    550             mWrappedNetworkMonitor.gen204ProbeResult = 200;
    551             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
    552             connect(false);
    553         }
    554 
    555         public void suspend() {
    556             mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
    557             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    558         }
    559 
    560         public void resume() {
    561             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
    562             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    563         }
    564 
    565         public void disconnect() {
    566             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
    567             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    568         }
    569 
    570         public Network getNetwork() {
    571             return new Network(mNetworkAgent.netId);
    572         }
    573 
    574         public ConditionVariable getPreventReconnectReceived() {
    575             return mPreventReconnectReceived;
    576         }
    577 
    578         public ConditionVariable getDisconnectedCV() {
    579             return mDisconnected;
    580         }
    581 
    582         public WrappedNetworkMonitor getWrappedNetworkMonitor() {
    583             return mWrappedNetworkMonitor;
    584         }
    585 
    586         public void sendLinkProperties(LinkProperties lp) {
    587             mNetworkAgent.sendLinkProperties(lp);
    588         }
    589 
    590         public void setStartKeepaliveError(int error) {
    591             mStartKeepaliveError = error;
    592         }
    593 
    594         public void setStopKeepaliveError(int error) {
    595             mStopKeepaliveError = error;
    596         }
    597 
    598         public void setExpectedKeepaliveSlot(Integer slot) {
    599             mExpectedKeepaliveSlot = slot;
    600         }
    601 
    602         public String waitForRedirectUrl() {
    603             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
    604             return mRedirectUrl;
    605         }
    606 
    607         public NetworkAgent getNetworkAgent() {
    608             return mNetworkAgent;
    609         }
    610 
    611         public NetworkCapabilities getNetworkCapabilities() {
    612             return mNetworkCapabilities;
    613         }
    614     }
    615 
    616     /**
    617      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
    618      * operations have been processed. Before ConnectivityService can add or remove any requests,
    619      * the factory must be told to expect those operations by calling expectAddRequests or
    620      * expectRemoveRequests.
    621      */
    622     private static class MockNetworkFactory extends NetworkFactory {
    623         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
    624         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
    625         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
    626 
    627         // Used to expect that requests be removed or added on a separate thread, without sleeping.
    628         // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
    629         // cause some other thread to add or remove requests, then call waitForRequests(). We can
    630         // either expect requests to be added or removed, but not both, because CountDownLatch can
    631         // only count in one direction.
    632         private CountDownLatch mExpectations;
    633 
    634         // Whether we are currently expecting requests to be added or removed. Valid only if
    635         // mExpectations is non-null.
    636         private boolean mExpectingAdditions;
    637 
    638         public MockNetworkFactory(Looper looper, Context context, String logTag,
    639                 NetworkCapabilities filter) {
    640             super(looper, context, logTag, filter);
    641         }
    642 
    643         public int getMyRequestCount() {
    644             return getRequestCount();
    645         }
    646 
    647         protected void startNetwork() {
    648             mNetworkStarted.set(true);
    649             mNetworkStartedCV.open();
    650         }
    651 
    652         protected void stopNetwork() {
    653             mNetworkStarted.set(false);
    654             mNetworkStoppedCV.open();
    655         }
    656 
    657         public boolean getMyStartRequested() {
    658             return mNetworkStarted.get();
    659         }
    660 
    661         public ConditionVariable getNetworkStartedCV() {
    662             mNetworkStartedCV.close();
    663             return mNetworkStartedCV;
    664         }
    665 
    666         public ConditionVariable getNetworkStoppedCV() {
    667             mNetworkStoppedCV.close();
    668             return mNetworkStoppedCV;
    669         }
    670 
    671         @Override
    672         protected void handleAddRequest(NetworkRequest request, int score) {
    673             // If we're expecting anything, we must be expecting additions.
    674             if (mExpectations != null && !mExpectingAdditions) {
    675                 fail("Can't add requests while expecting requests to be removed");
    676             }
    677 
    678             // Add the request.
    679             super.handleAddRequest(request, score);
    680 
    681             // Reduce the number of request additions we're waiting for.
    682             if (mExpectingAdditions) {
    683                 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
    684                 mExpectations.countDown();
    685             }
    686         }
    687 
    688         @Override
    689         protected void handleRemoveRequest(NetworkRequest request) {
    690             // If we're expecting anything, we must be expecting removals.
    691             if (mExpectations != null && mExpectingAdditions) {
    692                 fail("Can't remove requests while expecting requests to be added");
    693             }
    694 
    695             // Remove the request.
    696             super.handleRemoveRequest(request);
    697 
    698             // Reduce the number of request removals we're waiting for.
    699             if (!mExpectingAdditions) {
    700                 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
    701                 mExpectations.countDown();
    702             }
    703         }
    704 
    705         private void assertNoExpectations() {
    706             if (mExpectations != null) {
    707                 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
    708             }
    709         }
    710 
    711         // Expects that count requests will be added.
    712         public void expectAddRequests(final int count) {
    713             assertNoExpectations();
    714             mExpectingAdditions = true;
    715             mExpectations = new CountDownLatch(count);
    716         }
    717 
    718         // Expects that count requests will be removed.
    719         public void expectRemoveRequests(final int count) {
    720             assertNoExpectations();
    721             mExpectingAdditions = false;
    722             mExpectations = new CountDownLatch(count);
    723         }
    724 
    725         // Waits for the expected request additions or removals to happen within a timeout.
    726         public void waitForRequests() throws InterruptedException {
    727             assertNotNull("Nothing to wait for", mExpectations);
    728             mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    729             final long count = mExpectations.getCount();
    730             final String msg = count + " requests still not " +
    731                     (mExpectingAdditions ? "added" : "removed") +
    732                     " after " + TIMEOUT_MS + " ms";
    733             assertEquals(msg, 0, count);
    734             mExpectations = null;
    735         }
    736 
    737         public void waitForNetworkRequests(final int count) throws InterruptedException {
    738             waitForRequests();
    739             assertEquals(count, getMyRequestCount());
    740         }
    741     }
    742 
    743     private static Looper startHandlerThreadAndReturnLooper() {
    744         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
    745         handlerThread.start();
    746         return handlerThread.getLooper();
    747     }
    748 
    749     private class MockVpn extends Vpn {
    750         // TODO : the interactions between this mock and the mock network agent are too
    751         // hard to get right at this moment, because it's unclear in which case which
    752         // target needs to get a method call or both, and in what order. It's because
    753         // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
    754         // parent class of MockVpn agent wants that responsibility.
    755         // That being said inside the test it should be possible to make the interactions
    756         // harder to get wrong with precise speccing, judicious comments, helper methods
    757         // and a few sprinkled assertions.
    758 
    759         private boolean mConnected = false;
    760         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
    761         // not inherit from NetworkAgent.
    762         private MockNetworkAgent mMockNetworkAgent;
    763 
    764         public MockVpn(int userId) {
    765             super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
    766                     userId);
    767         }
    768 
    769         public void setNetworkAgent(MockNetworkAgent agent) {
    770             waitForIdle(agent, TIMEOUT_MS);
    771             mMockNetworkAgent = agent;
    772             mNetworkAgent = agent.getNetworkAgent();
    773             mNetworkCapabilities.set(agent.getNetworkCapabilities());
    774         }
    775 
    776         public void setUids(Set<UidRange> uids) {
    777             mNetworkCapabilities.setUids(uids);
    778             updateCapabilities();
    779         }
    780 
    781         @Override
    782         public int getNetId() {
    783             return mMockNetworkAgent.getNetwork().netId;
    784         }
    785 
    786         @Override
    787         public boolean appliesToUid(int uid) {
    788             return mConnected;  // Trickery to simplify testing.
    789         }
    790 
    791         @Override
    792         protected boolean isCallerEstablishedOwnerLocked() {
    793             return mConnected;  // Similar trickery
    794         }
    795 
    796         public void connect() {
    797             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
    798             mConnected = true;
    799             mConfig = new VpnConfig();
    800         }
    801 
    802         @Override
    803         public void updateCapabilities() {
    804             if (!mConnected) return;
    805             super.updateCapabilities();
    806             // Because super.updateCapabilities will update the capabilities of the agent but not
    807             // the mock agent, the mock agent needs to know about them.
    808             copyCapabilitiesToNetworkAgent();
    809         }
    810 
    811         private void copyCapabilitiesToNetworkAgent() {
    812             if (null != mMockNetworkAgent) {
    813                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
    814                         false /* sendToConnectivityService */);
    815             }
    816         }
    817 
    818         public void disconnect() {
    819             mConnected = false;
    820             mConfig = null;
    821         }
    822     }
    823 
    824     private class FakeWakeupMessage extends WakeupMessage {
    825         private static final int UNREASONABLY_LONG_WAIT = 1000;
    826 
    827         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
    828             super(context, handler, cmdName, cmd);
    829         }
    830 
    831         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
    832                 int arg1, int arg2, Object obj) {
    833             super(context, handler, cmdName, cmd, arg1, arg2, obj);
    834         }
    835 
    836         @Override
    837         public void schedule(long when) {
    838             long delayMs = when - SystemClock.elapsedRealtime();
    839             if (delayMs < 0) delayMs = 0;
    840             if (delayMs > UNREASONABLY_LONG_WAIT) {
    841                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
    842                         "ms into the future: " + delayMs);
    843             }
    844             Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
    845             mHandler.sendMessageDelayed(msg, delayMs);
    846         }
    847 
    848         @Override
    849         public void cancel() {
    850             mHandler.removeMessages(mCmd, mObj);
    851         }
    852 
    853         @Override
    854         public void onAlarm() {
    855             throw new AssertionError("Should never happen. Update this fake.");
    856         }
    857     }
    858 
    859     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
    860     private class WrappedNetworkMonitor extends NetworkMonitor {
    861         public final Handler connectivityHandler;
    862         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
    863         public int gen204ProbeResult = 500;
    864         public String gen204ProbeRedirectUrl = null;
    865 
    866         public WrappedNetworkMonitor(Context context, Handler handler,
    867                 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
    868                 IpConnectivityLog log) {
    869             super(context, handler, networkAgentInfo, defaultRequest, log,
    870                     NetworkMonitor.NetworkMonitorSettings.DEFAULT);
    871             connectivityHandler = handler;
    872         }
    873 
    874         @Override
    875         protected CaptivePortalProbeResult isCaptivePortal() {
    876             if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
    877             return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
    878         }
    879     }
    880 
    881     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
    882         public volatile boolean configRestrictsAvoidBadWifi;
    883         public volatile int configMeteredMultipathPreference;
    884 
    885         public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
    886             super(c, h, r);
    887         }
    888 
    889         @Override
    890         public boolean configRestrictsAvoidBadWifi() {
    891             return configRestrictsAvoidBadWifi;
    892         }
    893 
    894         @Override
    895         public int configMeteredMultipathPreference() {
    896             return configMeteredMultipathPreference;
    897         }
    898     }
    899 
    900     private class WrappedConnectivityService extends ConnectivityService {
    901         public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
    902         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
    903         private MockableSystemProperties mSystemProperties;
    904 
    905         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
    906                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
    907                 IpConnectivityLog log) {
    908             super(context, netManager, statsService, policyManager, log);
    909             mLingerDelayMs = TEST_LINGER_DELAY_MS;
    910         }
    911 
    912         @Override
    913         protected MockableSystemProperties getSystemProperties() {
    914             // Minimal approach to overriding system properties: let most calls fall through to real
    915             // device values, and only override ones values that are important to this test.
    916             mSystemProperties = spy(new MockableSystemProperties());
    917             when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
    918             when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
    919             return mSystemProperties;
    920         }
    921 
    922         @Override
    923         protected int reserveNetId() {
    924             while (true) {
    925                 final int netId = super.reserveNetId();
    926 
    927                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
    928                 // can have odd side-effects, like network validations succeeding.
    929                 Context context = InstrumentationRegistry.getContext();
    930                 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
    931                 boolean overlaps = false;
    932                 for (Network network : networks) {
    933                     if (netId == network.netId) {
    934                         overlaps = true;
    935                         break;
    936                     }
    937                 }
    938                 if (overlaps) continue;
    939 
    940                 return netId;
    941             }
    942         }
    943 
    944         @Override
    945         public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
    946                 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
    947             final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
    948                     context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
    949             mLastCreatedNetworkMonitor = monitor;
    950             return monitor;
    951         }
    952 
    953         @Override
    954         public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
    955                 Context c, Handler h, Runnable r) {
    956             final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
    957             return tracker;
    958         }
    959 
    960         public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
    961             return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
    962         }
    963 
    964         @Override
    965         public WakeupMessage makeWakeupMessage(
    966                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
    967             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
    968         }
    969 
    970         @Override
    971         public boolean hasService(String name) {
    972             // Currenty, the only relevant service that ConnectivityService checks for is
    973             // ETHERNET_SERVICE.
    974             return Context.ETHERNET_SERVICE.equals(name);
    975         }
    976 
    977         @Override
    978         protected IpConnectivityMetrics.Logger metricsLogger() {
    979             return mMetricsService;
    980         }
    981 
    982         @Override
    983         protected void registerNetdEventCallback() {
    984         }
    985 
    986         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
    987             return mLastCreatedNetworkMonitor;
    988         }
    989 
    990         public void mockVpn(int uid) {
    991             synchronized (mVpns) {
    992                 int userId = UserHandle.getUserId(uid);
    993                 mMockVpn = new MockVpn(userId);
    994                 // This has no effect unless the VPN is actually connected, because things like
    995                 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
    996                 // netId, and check if that network is actually connected.
    997                 mVpns.put(userId, mMockVpn);
    998             }
    999         }
   1000 
   1001         public void waitForIdle(int timeoutMs) {
   1002             waitForIdleHandler(mHandlerThread, timeoutMs);
   1003         }
   1004 
   1005         public void waitForIdle() {
   1006             waitForIdle(TIMEOUT_MS);
   1007         }
   1008     }
   1009 
   1010     /**
   1011      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
   1012      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
   1013      */
   1014     static private void waitFor(ConditionVariable conditionVariable) {
   1015         if (conditionVariable.block(TIMEOUT_MS)) {
   1016             return;
   1017         }
   1018         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
   1019     }
   1020 
   1021     @Before
   1022     public void setUp() throws Exception {
   1023         mContext = InstrumentationRegistry.getContext();
   1024 
   1025         MockitoAnnotations.initMocks(this);
   1026         when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
   1027 
   1028         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
   1029         // http://b/25897652 .
   1030         if (Looper.myLooper() == null) {
   1031             Looper.prepare();
   1032         }
   1033 
   1034         mServiceContext = new MockContext(InstrumentationRegistry.getContext());
   1035         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
   1036         LocalServices.addService(
   1037                 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
   1038         mService = new WrappedConnectivityService(mServiceContext,
   1039                 mNetworkManagementService,
   1040                 mStatsService,
   1041                 mock(INetworkPolicyManager.class),
   1042                 mock(IpConnectivityLog.class));
   1043 
   1044         // Create local CM before sending system ready so that we can answer
   1045         // getSystemService() correctly.
   1046         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
   1047         mService.systemReady();
   1048         mService.mockVpn(Process.myUid());
   1049         mCm.bindProcessToNetwork(null);
   1050 
   1051         // Ensure that the default setting for Captive Portals is used for most tests
   1052         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
   1053         setMobileDataAlwaysOn(false);
   1054         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
   1055     }
   1056 
   1057     @After
   1058     public void tearDown() throws Exception {
   1059         setMobileDataAlwaysOn(false);
   1060         if (mCellNetworkAgent != null) {
   1061             mCellNetworkAgent.disconnect();
   1062             mCellNetworkAgent = null;
   1063         }
   1064         if (mWiFiNetworkAgent != null) {
   1065             mWiFiNetworkAgent.disconnect();
   1066             mWiFiNetworkAgent = null;
   1067         }
   1068         if (mEthernetNetworkAgent != null) {
   1069             mEthernetNetworkAgent.disconnect();
   1070             mEthernetNetworkAgent = null;
   1071         }
   1072     }
   1073 
   1074     private static int transportToLegacyType(int transport) {
   1075         switch (transport) {
   1076             case TRANSPORT_ETHERNET:
   1077                 return TYPE_ETHERNET;
   1078             case TRANSPORT_WIFI:
   1079                 return TYPE_WIFI;
   1080             case TRANSPORT_CELLULAR:
   1081                 return TYPE_MOBILE;
   1082             default:
   1083                 return TYPE_NONE;
   1084         }
   1085     }
   1086 
   1087     private void verifyActiveNetwork(int transport) {
   1088         // Test getActiveNetworkInfo()
   1089         assertNotNull(mCm.getActiveNetworkInfo());
   1090         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
   1091         // Test getActiveNetwork()
   1092         assertNotNull(mCm.getActiveNetwork());
   1093         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
   1094         if (!NetworkCapabilities.isValidTransport(transport)) {
   1095             throw new IllegalStateException("Unknown transport " + transport);
   1096         }
   1097         switch (transport) {
   1098             case TRANSPORT_WIFI:
   1099                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
   1100                 break;
   1101             case TRANSPORT_CELLULAR:
   1102                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
   1103                 break;
   1104             default:
   1105                 break;
   1106         }
   1107         // Test getNetworkInfo(Network)
   1108         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
   1109         assertEquals(transportToLegacyType(transport),
   1110                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
   1111         // Test getNetworkCapabilities(Network)
   1112         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
   1113         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
   1114     }
   1115 
   1116     private void verifyNoNetwork() {
   1117         waitForIdle();
   1118         // Test getActiveNetworkInfo()
   1119         assertNull(mCm.getActiveNetworkInfo());
   1120         // Test getActiveNetwork()
   1121         assertNull(mCm.getActiveNetwork());
   1122         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
   1123         // Test getAllNetworks()
   1124         assertEmpty(mCm.getAllNetworks());
   1125     }
   1126 
   1127     /**
   1128      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
   1129      * broadcasts are received.
   1130      */
   1131     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
   1132         final ConditionVariable cv = new ConditionVariable();
   1133         mServiceContext.registerReceiver(new BroadcastReceiver() {
   1134                     private int remaining = count;
   1135                     public void onReceive(Context context, Intent intent) {
   1136                         if (--remaining == 0) {
   1137                             cv.open();
   1138                             mServiceContext.unregisterReceiver(this);
   1139                         }
   1140                     }
   1141                 }, new IntentFilter(CONNECTIVITY_ACTION));
   1142         return cv;
   1143     }
   1144 
   1145     @Test
   1146     public void testNetworkTypes() {
   1147         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
   1148         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
   1149         // will fail. Failing here is much easier to debug.
   1150         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
   1151         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
   1152         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
   1153         assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
   1154 
   1155         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
   1156         // mocks, this assert exercises the ConnectivityService code path that ensures that
   1157         // TYPE_ETHERNET is supported if the ethernet service is running.
   1158         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
   1159     }
   1160 
   1161     @Test
   1162     public void testLingering() throws Exception {
   1163         verifyNoNetwork();
   1164         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1165         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1166         assertNull(mCm.getActiveNetworkInfo());
   1167         assertNull(mCm.getActiveNetwork());
   1168         // Test bringing up validated cellular.
   1169         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1170         mCellNetworkAgent.connect(true);
   1171         waitFor(cv);
   1172         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1173         assertLength(2, mCm.getAllNetworks());
   1174         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
   1175                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
   1176         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
   1177                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
   1178         // Test bringing up validated WiFi.
   1179         cv = waitForConnectivityBroadcasts(2);
   1180         mWiFiNetworkAgent.connect(true);
   1181         waitFor(cv);
   1182         verifyActiveNetwork(TRANSPORT_WIFI);
   1183         assertLength(2, mCm.getAllNetworks());
   1184         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
   1185                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
   1186         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
   1187                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
   1188         // Test cellular linger timeout.
   1189         waitFor(mCellNetworkAgent.getDisconnectedCV());
   1190         waitForIdle();
   1191         assertLength(1, mCm.getAllNetworks());
   1192         verifyActiveNetwork(TRANSPORT_WIFI);
   1193         assertLength(1, mCm.getAllNetworks());
   1194         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
   1195         // Test WiFi disconnect.
   1196         cv = waitForConnectivityBroadcasts(1);
   1197         mWiFiNetworkAgent.disconnect();
   1198         waitFor(cv);
   1199         verifyNoNetwork();
   1200     }
   1201 
   1202     @Test
   1203     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
   1204         // Test bringing up unvalidated WiFi
   1205         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1206         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1207         mWiFiNetworkAgent.connect(false);
   1208         waitFor(cv);
   1209         verifyActiveNetwork(TRANSPORT_WIFI);
   1210         // Test bringing up unvalidated cellular
   1211         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1212         mCellNetworkAgent.connect(false);
   1213         waitForIdle();
   1214         verifyActiveNetwork(TRANSPORT_WIFI);
   1215         // Test cellular disconnect.
   1216         mCellNetworkAgent.disconnect();
   1217         waitForIdle();
   1218         verifyActiveNetwork(TRANSPORT_WIFI);
   1219         // Test bringing up validated cellular
   1220         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1221         cv = waitForConnectivityBroadcasts(2);
   1222         mCellNetworkAgent.connect(true);
   1223         waitFor(cv);
   1224         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1225         // Test cellular disconnect.
   1226         cv = waitForConnectivityBroadcasts(2);
   1227         mCellNetworkAgent.disconnect();
   1228         waitFor(cv);
   1229         verifyActiveNetwork(TRANSPORT_WIFI);
   1230         // Test WiFi disconnect.
   1231         cv = waitForConnectivityBroadcasts(1);
   1232         mWiFiNetworkAgent.disconnect();
   1233         waitFor(cv);
   1234         verifyNoNetwork();
   1235     }
   1236 
   1237     @Test
   1238     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
   1239         // Test bringing up unvalidated cellular.
   1240         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1241         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1242         mCellNetworkAgent.connect(false);
   1243         waitFor(cv);
   1244         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1245         // Test bringing up unvalidated WiFi.
   1246         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1247         cv = waitForConnectivityBroadcasts(2);
   1248         mWiFiNetworkAgent.connect(false);
   1249         waitFor(cv);
   1250         verifyActiveNetwork(TRANSPORT_WIFI);
   1251         // Test WiFi disconnect.
   1252         cv = waitForConnectivityBroadcasts(2);
   1253         mWiFiNetworkAgent.disconnect();
   1254         waitFor(cv);
   1255         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1256         // Test cellular disconnect.
   1257         cv = waitForConnectivityBroadcasts(1);
   1258         mCellNetworkAgent.disconnect();
   1259         waitFor(cv);
   1260         verifyNoNetwork();
   1261     }
   1262 
   1263     @Test
   1264     public void testUnlingeringDoesNotValidate() throws Exception {
   1265         // Test bringing up unvalidated WiFi.
   1266         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1267         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1268         mWiFiNetworkAgent.connect(false);
   1269         waitFor(cv);
   1270         verifyActiveNetwork(TRANSPORT_WIFI);
   1271         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1272                 NET_CAPABILITY_VALIDATED));
   1273         // Test bringing up validated cellular.
   1274         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1275         cv = waitForConnectivityBroadcasts(2);
   1276         mCellNetworkAgent.connect(true);
   1277         waitFor(cv);
   1278         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1279         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1280                 NET_CAPABILITY_VALIDATED));
   1281         // Test cellular disconnect.
   1282         cv = waitForConnectivityBroadcasts(2);
   1283         mCellNetworkAgent.disconnect();
   1284         waitFor(cv);
   1285         verifyActiveNetwork(TRANSPORT_WIFI);
   1286         // Unlingering a network should not cause it to be marked as validated.
   1287         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1288                 NET_CAPABILITY_VALIDATED));
   1289     }
   1290 
   1291     @Test
   1292     public void testCellularOutscoresWeakWifi() throws Exception {
   1293         // Test bringing up validated cellular.
   1294         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1295         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1296         mCellNetworkAgent.connect(true);
   1297         waitFor(cv);
   1298         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1299         // Test bringing up validated WiFi.
   1300         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1301         cv = waitForConnectivityBroadcasts(2);
   1302         mWiFiNetworkAgent.connect(true);
   1303         waitFor(cv);
   1304         verifyActiveNetwork(TRANSPORT_WIFI);
   1305         // Test WiFi getting really weak.
   1306         cv = waitForConnectivityBroadcasts(2);
   1307         mWiFiNetworkAgent.adjustScore(-11);
   1308         waitFor(cv);
   1309         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1310         // Test WiFi restoring signal strength.
   1311         cv = waitForConnectivityBroadcasts(2);
   1312         mWiFiNetworkAgent.adjustScore(11);
   1313         waitFor(cv);
   1314         verifyActiveNetwork(TRANSPORT_WIFI);
   1315     }
   1316 
   1317     @Test
   1318     public void testReapingNetwork() throws Exception {
   1319         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
   1320         // Expect it to be torn down immediately because it satisfies no requests.
   1321         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1322         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
   1323         mWiFiNetworkAgent.connectWithoutInternet();
   1324         waitFor(cv);
   1325         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
   1326         // Expect it to be torn down immediately because it satisfies no requests.
   1327         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1328         cv = mCellNetworkAgent.getDisconnectedCV();
   1329         mCellNetworkAgent.connectWithoutInternet();
   1330         waitFor(cv);
   1331         // Test bringing up validated WiFi.
   1332         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1333         cv = waitForConnectivityBroadcasts(1);
   1334         mWiFiNetworkAgent.connect(true);
   1335         waitFor(cv);
   1336         verifyActiveNetwork(TRANSPORT_WIFI);
   1337         // Test bringing up unvalidated cellular.
   1338         // Expect it to be torn down because it could never be the highest scoring network
   1339         // satisfying the default request even if it validated.
   1340         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1341         cv = mCellNetworkAgent.getDisconnectedCV();
   1342         mCellNetworkAgent.connect(false);
   1343         waitFor(cv);
   1344         verifyActiveNetwork(TRANSPORT_WIFI);
   1345         cv = mWiFiNetworkAgent.getDisconnectedCV();
   1346         mWiFiNetworkAgent.disconnect();
   1347         waitFor(cv);
   1348     }
   1349 
   1350     @Test
   1351     public void testCellularFallback() throws Exception {
   1352         // Test bringing up validated cellular.
   1353         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1354         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1355         mCellNetworkAgent.connect(true);
   1356         waitFor(cv);
   1357         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1358         // Test bringing up validated WiFi.
   1359         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1360         cv = waitForConnectivityBroadcasts(2);
   1361         mWiFiNetworkAgent.connect(true);
   1362         waitFor(cv);
   1363         verifyActiveNetwork(TRANSPORT_WIFI);
   1364         // Reevaluate WiFi (it'll instantly fail DNS).
   1365         cv = waitForConnectivityBroadcasts(2);
   1366         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1367                 NET_CAPABILITY_VALIDATED));
   1368         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
   1369         // Should quickly fall back to Cellular.
   1370         waitFor(cv);
   1371         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1372                 NET_CAPABILITY_VALIDATED));
   1373         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1374         // Reevaluate cellular (it'll instantly fail DNS).
   1375         cv = waitForConnectivityBroadcasts(2);
   1376         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1377                 NET_CAPABILITY_VALIDATED));
   1378         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
   1379         // Should quickly fall back to WiFi.
   1380         waitFor(cv);
   1381         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1382                 NET_CAPABILITY_VALIDATED));
   1383         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1384                 NET_CAPABILITY_VALIDATED));
   1385         verifyActiveNetwork(TRANSPORT_WIFI);
   1386     }
   1387 
   1388     @Test
   1389     public void testWiFiFallback() throws Exception {
   1390         // Test bringing up unvalidated WiFi.
   1391         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1392         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1393         mWiFiNetworkAgent.connect(false);
   1394         waitFor(cv);
   1395         verifyActiveNetwork(TRANSPORT_WIFI);
   1396         // Test bringing up validated cellular.
   1397         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1398         cv = waitForConnectivityBroadcasts(2);
   1399         mCellNetworkAgent.connect(true);
   1400         waitFor(cv);
   1401         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1402         // Reevaluate cellular (it'll instantly fail DNS).
   1403         cv = waitForConnectivityBroadcasts(2);
   1404         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1405                 NET_CAPABILITY_VALIDATED));
   1406         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
   1407         // Should quickly fall back to WiFi.
   1408         waitFor(cv);
   1409         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1410                 NET_CAPABILITY_VALIDATED));
   1411         verifyActiveNetwork(TRANSPORT_WIFI);
   1412     }
   1413 
   1414     enum CallbackState {
   1415         NONE,
   1416         AVAILABLE,
   1417         NETWORK_CAPABILITIES,
   1418         LINK_PROPERTIES,
   1419         SUSPENDED,
   1420         RESUMED,
   1421         LOSING,
   1422         LOST,
   1423         UNAVAILABLE
   1424     }
   1425 
   1426     private static class CallbackInfo {
   1427         public final CallbackState state;
   1428         public final Network network;
   1429         public final Object arg;
   1430         public CallbackInfo(CallbackState s, Network n, Object o) {
   1431             state = s; network = n; arg = o;
   1432         }
   1433         public String toString() {
   1434             return String.format("%s (%s) (%s)", state, network, arg);
   1435         }
   1436         @Override
   1437         public boolean equals(Object o) {
   1438             if (!(o instanceof CallbackInfo)) return false;
   1439             // Ignore timeMs, since it's unpredictable.
   1440             CallbackInfo other = (CallbackInfo) o;
   1441             return (state == other.state) && Objects.equals(network, other.network);
   1442         }
   1443         @Override
   1444         public int hashCode() {
   1445             return Objects.hash(state, network);
   1446         }
   1447     }
   1448 
   1449     /**
   1450      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
   1451      * this class receives, by calling expectCallback() exactly once each time a callback is
   1452      * received. assertNoCallback may be called at any time.
   1453      */
   1454     private class TestNetworkCallback extends NetworkCallback {
   1455         // Chosen to be much less than the linger timeout. This ensures that we can distinguish
   1456         // between a LOST callback that arrives immediately and a LOST callback that arrives after
   1457         // the linger timeout.
   1458         private final static int TIMEOUT_MS = 100;
   1459 
   1460         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
   1461         private Network mLastAvailableNetwork;
   1462 
   1463         protected void setLastCallback(CallbackState state, Network network, Object o) {
   1464             mCallbacks.offer(new CallbackInfo(state, network, o));
   1465         }
   1466 
   1467         @Override
   1468         public void onAvailable(Network network) {
   1469             mLastAvailableNetwork = network;
   1470             setLastCallback(CallbackState.AVAILABLE, network, null);
   1471         }
   1472 
   1473         @Override
   1474         public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
   1475             setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
   1476         }
   1477 
   1478         @Override
   1479         public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
   1480             setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
   1481         }
   1482 
   1483         @Override
   1484         public void onUnavailable() {
   1485             setLastCallback(CallbackState.UNAVAILABLE, null, null);
   1486         }
   1487 
   1488         @Override
   1489         public void onNetworkSuspended(Network network) {
   1490             setLastCallback(CallbackState.SUSPENDED, network, null);
   1491         }
   1492 
   1493         @Override
   1494         public void onNetworkResumed(Network network) {
   1495             setLastCallback(CallbackState.RESUMED, network, null);
   1496         }
   1497 
   1498         @Override
   1499         public void onLosing(Network network, int maxMsToLive) {
   1500             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
   1501         }
   1502 
   1503         @Override
   1504         public void onLost(Network network) {
   1505             mLastAvailableNetwork = null;
   1506             setLastCallback(CallbackState.LOST, network, null);
   1507         }
   1508 
   1509         public Network getLastAvailableNetwork() {
   1510             return mLastAvailableNetwork;
   1511         }
   1512 
   1513         CallbackInfo nextCallback(int timeoutMs) {
   1514             CallbackInfo cb = null;
   1515             try {
   1516                 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
   1517             } catch (InterruptedException e) {
   1518             }
   1519             if (cb == null) {
   1520                 // LinkedBlockingQueue.poll() returns null if it timeouts.
   1521                 fail("Did not receive callback after " + timeoutMs + "ms");
   1522             }
   1523             return cb;
   1524         }
   1525 
   1526         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
   1527             final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
   1528             CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
   1529             CallbackInfo actual = nextCallback(timeoutMs);
   1530             assertEquals("Unexpected callback:", expected, actual);
   1531 
   1532             if (state == CallbackState.LOSING) {
   1533                 String msg = String.format(
   1534                         "Invalid linger time value %d, must be between %d and %d",
   1535                         actual.arg, 0, TEST_LINGER_DELAY_MS);
   1536                 int maxMsToLive = (Integer) actual.arg;
   1537                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
   1538             }
   1539 
   1540             return actual;
   1541         }
   1542 
   1543         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
   1544             return expectCallback(state, agent, TIMEOUT_MS);
   1545         }
   1546 
   1547         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
   1548             return expectCallbackLike(fn, TIMEOUT_MS);
   1549         }
   1550 
   1551         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
   1552             int timeLeft = timeoutMs;
   1553             while (timeLeft > 0) {
   1554                 long start = SystemClock.elapsedRealtime();
   1555                 CallbackInfo info = nextCallback(timeLeft);
   1556                 if (fn.test(info)) {
   1557                     return info;
   1558                 }
   1559                 timeLeft -= (SystemClock.elapsedRealtime() - start);
   1560             }
   1561             fail("Did not receive expected callback after " + timeoutMs + "ms");
   1562             return null;
   1563         }
   1564 
   1565         // Expects onAvailable and the callbacks that follow it. These are:
   1566         // - onSuspended, iff the network was suspended when the callbacks fire.
   1567         // - onCapabilitiesChanged.
   1568         // - onLinkPropertiesChanged.
   1569         //
   1570         // @param agent the network to expect the callbacks on.
   1571         // @param expectSuspended whether to expect a SUSPENDED callback.
   1572         // @param expectValidated the expected value of the VALIDATED capability in the
   1573         //        onCapabilitiesChanged callback.
   1574         // @param timeoutMs how long to wait for the callbacks.
   1575         void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
   1576                 boolean expectValidated, int timeoutMs) {
   1577             expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
   1578             if (expectSuspended) {
   1579                 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
   1580             }
   1581             if (expectValidated) {
   1582                 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
   1583             } else {
   1584                 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
   1585             }
   1586             expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
   1587         }
   1588 
   1589         // Expects the available callbacks (validated), plus onSuspended.
   1590         void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
   1591             expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS);
   1592         }
   1593 
   1594         void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
   1595             expectAvailableCallbacks(agent, false, true, TIMEOUT_MS);
   1596         }
   1597 
   1598         void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
   1599             expectAvailableCallbacks(agent, false, false, TIMEOUT_MS);
   1600         }
   1601 
   1602         // Expects the available callbacks (where the onCapabilitiesChanged must contain the
   1603         // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
   1604         // one we just sent.
   1605         // TODO: this is likely a bug. Fix it and remove this method.
   1606         void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
   1607             expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS);
   1608             NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
   1609             expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS);
   1610             NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
   1611             assertEquals(nc1, nc2);
   1612         }
   1613 
   1614         // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
   1615         // then expects another onCapabilitiesChanged that has the validated bit set. This is used
   1616         // when a network connects and satisfies a callback, and then immediately validates.
   1617         void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
   1618             expectAvailableCallbacksUnvalidated(agent);
   1619             expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
   1620         }
   1621 
   1622         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
   1623             return expectCapabilitiesWith(capability, agent, TIMEOUT_MS);
   1624         }
   1625 
   1626         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
   1627                 int timeoutMs) {
   1628             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
   1629             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
   1630             assertTrue(nc.hasCapability(capability));
   1631             return nc;
   1632         }
   1633 
   1634         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
   1635             return expectCapabilitiesWithout(capability, agent, TIMEOUT_MS);
   1636         }
   1637 
   1638         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
   1639                 int timeoutMs) {
   1640             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
   1641             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
   1642             assertFalse(nc.hasCapability(capability));
   1643             return nc;
   1644         }
   1645 
   1646         void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
   1647             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
   1648             assertTrue("Received capabilities don't match expectations : " + cbi.arg,
   1649                     fn.test((NetworkCapabilities) cbi.arg));
   1650         }
   1651 
   1652         void assertNoCallback() {
   1653             waitForIdle();
   1654             CallbackInfo c = mCallbacks.peek();
   1655             assertNull("Unexpected callback: " + c, c);
   1656         }
   1657     }
   1658 
   1659     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
   1660     // only be declared in a static or top level type".
   1661     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
   1662         for (TestNetworkCallback c : callbacks) {
   1663             c.assertNoCallback();
   1664         }
   1665     }
   1666 
   1667     @Test
   1668     public void testStateChangeNetworkCallbacks() throws Exception {
   1669         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
   1670         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
   1671         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   1672         final NetworkRequest genericRequest = new NetworkRequest.Builder()
   1673                 .clearCapabilities().build();
   1674         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
   1675                 .addTransportType(TRANSPORT_WIFI).build();
   1676         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   1677                 .addTransportType(TRANSPORT_CELLULAR).build();
   1678         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
   1679         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
   1680         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   1681 
   1682         // Test unvalidated networks
   1683         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1684         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1685         mCellNetworkAgent.connect(false);
   1686         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1687         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1688         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1689         waitFor(cv);
   1690         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1691 
   1692         // This should not trigger spurious onAvailable() callbacks, b/21762680.
   1693         mCellNetworkAgent.adjustScore(-1);
   1694         waitForIdle();
   1695         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1696         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1697 
   1698         cv = waitForConnectivityBroadcasts(2);
   1699         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1700         mWiFiNetworkAgent.connect(false);
   1701         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1702         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1703         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1704         waitFor(cv);
   1705         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1706 
   1707         cv = waitForConnectivityBroadcasts(2);
   1708         mWiFiNetworkAgent.disconnect();
   1709         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1710         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1711         cellNetworkCallback.assertNoCallback();
   1712         waitFor(cv);
   1713         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1714 
   1715         cv = waitForConnectivityBroadcasts(1);
   1716         mCellNetworkAgent.disconnect();
   1717         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1718         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1719         waitFor(cv);
   1720         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1721 
   1722         // Test validated networks
   1723         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1724         mCellNetworkAgent.connect(true);
   1725         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   1726         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   1727         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1728         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1729 
   1730         // This should not trigger spurious onAvailable() callbacks, b/21762680.
   1731         mCellNetworkAgent.adjustScore(-1);
   1732         waitForIdle();
   1733         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1734         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1735 
   1736         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1737         mWiFiNetworkAgent.connect(true);
   1738         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1739         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1740         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   1741         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   1742         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1743         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1744         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1745 
   1746         mWiFiNetworkAgent.disconnect();
   1747         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1748         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1749         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1750 
   1751         mCellNetworkAgent.disconnect();
   1752         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1753         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1754         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1755     }
   1756 
   1757     @Test
   1758     public void testMultipleLingering() {
   1759         NetworkRequest request = new NetworkRequest.Builder()
   1760                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
   1761                 .build();
   1762         TestNetworkCallback callback = new TestNetworkCallback();
   1763         mCm.registerNetworkCallback(request, callback);
   1764 
   1765         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   1766         mCm.registerDefaultNetworkCallback(defaultCallback);
   1767 
   1768         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1769         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1770         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   1771 
   1772         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   1773         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   1774         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   1775 
   1776         mCellNetworkAgent.connect(true);
   1777         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   1778         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   1779         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1780         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1781 
   1782         mWiFiNetworkAgent.connect(true);
   1783         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
   1784         // We then get LOSING when wifi validates and cell is outscored.
   1785         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1786         // TODO: Investigate sending validated before losing.
   1787         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1788         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   1789         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   1790         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1791         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1792 
   1793         mEthernetNetworkAgent.connect(true);
   1794         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
   1795         // TODO: Investigate sending validated before losing.
   1796         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
   1797         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
   1798         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
   1799         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1800         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1801 
   1802         mEthernetNetworkAgent.disconnect();
   1803         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   1804         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   1805         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   1806         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1807 
   1808         for (int i = 0; i < 4; i++) {
   1809             MockNetworkAgent oldNetwork, newNetwork;
   1810             if (i % 2 == 0) {
   1811                 mWiFiNetworkAgent.adjustScore(-15);
   1812                 oldNetwork = mWiFiNetworkAgent;
   1813                 newNetwork = mCellNetworkAgent;
   1814             } else {
   1815                 mWiFiNetworkAgent.adjustScore(15);
   1816                 oldNetwork = mCellNetworkAgent;
   1817                 newNetwork = mWiFiNetworkAgent;
   1818 
   1819             }
   1820             callback.expectCallback(CallbackState.LOSING, oldNetwork);
   1821             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
   1822             // longer lingering?
   1823             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
   1824             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
   1825         }
   1826         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1827 
   1828         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
   1829         // if the network is still up.
   1830         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   1831         // We expect a notification about the capabilities change, and nothing else.
   1832         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
   1833         defaultCallback.assertNoCallback();
   1834         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1835         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1836 
   1837         // Wifi no longer satisfies our listen, which is for an unmetered network.
   1838         // But because its score is 55, it's still up (and the default network).
   1839         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1840 
   1841         // Disconnect our test networks.
   1842         mWiFiNetworkAgent.disconnect();
   1843         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1844         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   1845         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1846         mCellNetworkAgent.disconnect();
   1847         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1848         waitForIdle();
   1849         assertEquals(null, mCm.getActiveNetwork());
   1850 
   1851         mCm.unregisterNetworkCallback(callback);
   1852         waitForIdle();
   1853 
   1854         // Check that a network is only lingered or torn down if it would not satisfy a request even
   1855         // if it validated.
   1856         request = new NetworkRequest.Builder().clearCapabilities().build();
   1857         callback = new TestNetworkCallback();
   1858 
   1859         mCm.registerNetworkCallback(request, callback);
   1860 
   1861         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1862         mCellNetworkAgent.connect(false);   // Score: 10
   1863         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1864         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1865         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1866         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1867 
   1868         // Bring up wifi with a score of 20.
   1869         // Cell stays up because it would satisfy the default request if it validated.
   1870         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1871         mWiFiNetworkAgent.connect(false);   // Score: 20
   1872         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1873         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1874         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1875         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1876 
   1877         mWiFiNetworkAgent.disconnect();
   1878         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1879         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1880         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1881         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1882         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1883 
   1884         // Bring up wifi with a score of 70.
   1885         // Cell is lingered because it would not satisfy any request, even if it validated.
   1886         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1887         mWiFiNetworkAgent.adjustScore(50);
   1888         mWiFiNetworkAgent.connect(false);   // Score: 70
   1889         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1890         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1891         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1892         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1893         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1894 
   1895         // Tear down wifi.
   1896         mWiFiNetworkAgent.disconnect();
   1897         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1898         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1899         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1900         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1901         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1902 
   1903         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
   1904         // it's arguably correct to linger it, since it was the default network before it validated.
   1905         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1906         mWiFiNetworkAgent.connect(true);
   1907         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1908         // TODO: Investigate sending validated before losing.
   1909         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1910         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   1911         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   1912         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1913         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1914 
   1915         mWiFiNetworkAgent.disconnect();
   1916         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1917         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1918         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   1919         mCellNetworkAgent.disconnect();
   1920         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1921         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1922         waitForIdle();
   1923         assertEquals(null, mCm.getActiveNetwork());
   1924 
   1925         // If a network is lingering, and we add and remove a request from it, resume lingering.
   1926         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1927         mCellNetworkAgent.connect(true);
   1928         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   1929         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   1930         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1931         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1932         mWiFiNetworkAgent.connect(true);
   1933         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   1934         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   1935         // TODO: Investigate sending validated before losing.
   1936         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1937         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   1938         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1939 
   1940         NetworkRequest cellRequest = new NetworkRequest.Builder()
   1941                 .addTransportType(TRANSPORT_CELLULAR).build();
   1942         NetworkCallback noopCallback = new NetworkCallback();
   1943         mCm.requestNetwork(cellRequest, noopCallback);
   1944         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
   1945         // lingering?
   1946         mCm.unregisterNetworkCallback(noopCallback);
   1947         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1948 
   1949         // Similar to the above: lingering can start even after the lingered request is removed.
   1950         // Disconnect wifi and switch to cell.
   1951         mWiFiNetworkAgent.disconnect();
   1952         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1953         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1954         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   1955         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1956 
   1957         // Cell is now the default network. Pin it with a cell-specific request.
   1958         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
   1959         mCm.requestNetwork(cellRequest, noopCallback);
   1960 
   1961         // Now connect wifi, and expect it to become the default network.
   1962         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1963         mWiFiNetworkAgent.connect(true);
   1964         callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   1965         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   1966         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1967         // The default request is lingering on cell, but nothing happens to cell, and we send no
   1968         // callbacks for it, because it's kept up by cellRequest.
   1969         callback.assertNoCallback();
   1970         // Now unregister cellRequest and expect cell to start lingering.
   1971         mCm.unregisterNetworkCallback(noopCallback);
   1972         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1973 
   1974         // Let linger run its course.
   1975         callback.assertNoCallback();
   1976         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
   1977         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
   1978 
   1979         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
   1980         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
   1981         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
   1982         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   1983         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   1984         mEthernetNetworkAgent.connect(true);
   1985         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
   1986         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
   1987         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
   1988         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
   1989         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
   1990         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   1991 
   1992         // Let linger run its course.
   1993         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
   1994 
   1995         // Clean up.
   1996         mEthernetNetworkAgent.disconnect();
   1997         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   1998         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   1999         trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2000 
   2001         mCm.unregisterNetworkCallback(callback);
   2002         mCm.unregisterNetworkCallback(defaultCallback);
   2003         mCm.unregisterNetworkCallback(trackDefaultCallback);
   2004     }
   2005 
   2006     @Test
   2007     public void testNetworkGoesIntoBackgroundAfterLinger() {
   2008         setMobileDataAlwaysOn(true);
   2009         NetworkRequest request = new NetworkRequest.Builder()
   2010                 .clearCapabilities()
   2011                 .build();
   2012         TestNetworkCallback callback = new TestNetworkCallback();
   2013         mCm.registerNetworkCallback(request, callback);
   2014 
   2015         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   2016         mCm.registerDefaultNetworkCallback(defaultCallback);
   2017 
   2018         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2019         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2020 
   2021         mCellNetworkAgent.connect(true);
   2022         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2023         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2024 
   2025         // Wifi comes up and cell lingers.
   2026         mWiFiNetworkAgent.connect(true);
   2027         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2028         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2029         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2030         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2031 
   2032         // File a request for cellular, then release it.
   2033         NetworkRequest cellRequest = new NetworkRequest.Builder()
   2034                 .addTransportType(TRANSPORT_CELLULAR).build();
   2035         NetworkCallback noopCallback = new NetworkCallback();
   2036         mCm.requestNetwork(cellRequest, noopCallback);
   2037         mCm.unregisterNetworkCallback(noopCallback);
   2038         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2039 
   2040         // Let linger run its course.
   2041         callback.assertNoCallback();
   2042         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
   2043         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
   2044                 lingerTimeoutMs);
   2045 
   2046         // Clean up.
   2047         mCm.unregisterNetworkCallback(defaultCallback);
   2048         mCm.unregisterNetworkCallback(callback);
   2049     }
   2050 
   2051     @Test
   2052     public void testExplicitlySelected() {
   2053         NetworkRequest request = new NetworkRequest.Builder()
   2054                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
   2055                 .build();
   2056         TestNetworkCallback callback = new TestNetworkCallback();
   2057         mCm.registerNetworkCallback(request, callback);
   2058 
   2059         // Bring up validated cell.
   2060         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2061         mCellNetworkAgent.connect(true);
   2062         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2063 
   2064         // Bring up unvalidated wifi with explicitlySelected=true.
   2065         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2066         mWiFiNetworkAgent.explicitlySelected(false);
   2067         mWiFiNetworkAgent.connect(false);
   2068         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2069 
   2070         // Cell Remains the default.
   2071         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2072 
   2073         // Lower wifi's score to below than cell, and check that it doesn't disconnect because
   2074         // it's explicitly selected.
   2075         mWiFiNetworkAgent.adjustScore(-40);
   2076         mWiFiNetworkAgent.adjustScore(40);
   2077         callback.assertNoCallback();
   2078 
   2079         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
   2080         // wifi even though it's unvalidated.
   2081         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
   2082         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2083         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2084 
   2085         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
   2086         mWiFiNetworkAgent.disconnect();
   2087         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2088         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2089         mWiFiNetworkAgent.explicitlySelected(false);
   2090         mWiFiNetworkAgent.connect(false);
   2091         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2092 
   2093         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
   2094         // network to disconnect.
   2095         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
   2096         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2097 
   2098         // Reconnect, again with explicitlySelected=true, but this time validate.
   2099         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2100         mWiFiNetworkAgent.explicitlySelected(false);
   2101         mWiFiNetworkAgent.connect(true);
   2102         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2103         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2104         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2105         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2106 
   2107         // BUG: the network will no longer linger, even though it's validated and outscored.
   2108         // TODO: fix this.
   2109         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   2110         mEthernetNetworkAgent.connect(true);
   2111         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
   2112         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2113         callback.assertNoCallback();
   2114 
   2115         // Clean up.
   2116         mWiFiNetworkAgent.disconnect();
   2117         mCellNetworkAgent.disconnect();
   2118         mEthernetNetworkAgent.disconnect();
   2119 
   2120         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2121         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2122         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   2123     }
   2124 
   2125     private void tryNetworkFactoryRequests(int capability) throws Exception {
   2126         // Verify NOT_RESTRICTED is set appropriately
   2127         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
   2128                 .build().networkCapabilities;
   2129         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
   2130                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
   2131                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
   2132                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
   2133             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
   2134         } else {
   2135             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
   2136         }
   2137 
   2138         NetworkCapabilities filter = new NetworkCapabilities();
   2139         filter.addCapability(capability);
   2140         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
   2141         handlerThread.start();
   2142         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   2143                 mServiceContext, "testFactory", filter);
   2144         testFactory.setScoreFilter(40);
   2145         ConditionVariable cv = testFactory.getNetworkStartedCV();
   2146         testFactory.expectAddRequests(1);
   2147         testFactory.register();
   2148         testFactory.waitForNetworkRequests(1);
   2149         int expectedRequestCount = 1;
   2150         NetworkCallback networkCallback = null;
   2151         // For non-INTERNET capabilities we cannot rely on the default request being present, so
   2152         // add one.
   2153         if (capability != NET_CAPABILITY_INTERNET) {
   2154             assertFalse(testFactory.getMyStartRequested());
   2155             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
   2156             networkCallback = new NetworkCallback();
   2157             testFactory.expectAddRequests(1);
   2158             mCm.requestNetwork(request, networkCallback);
   2159             expectedRequestCount++;
   2160             testFactory.waitForNetworkRequests(expectedRequestCount);
   2161         }
   2162         waitFor(cv);
   2163         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   2164         assertTrue(testFactory.getMyStartRequested());
   2165 
   2166         // Now bring in a higher scored network.
   2167         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2168         // Rather than create a validated network which complicates things by registering it's
   2169         // own NetworkRequest during startup, just bump up the score to cancel out the
   2170         // unvalidated penalty.
   2171         testAgent.adjustScore(40);
   2172         cv = testFactory.getNetworkStoppedCV();
   2173 
   2174         // When testAgent connects, ConnectivityService will re-send us all current requests with
   2175         // the new score. There are expectedRequestCount such requests, and we must wait for all of
   2176         // them.
   2177         testFactory.expectAddRequests(expectedRequestCount);
   2178         testAgent.connect(false);
   2179         testAgent.addCapability(capability);
   2180         waitFor(cv);
   2181         testFactory.waitForNetworkRequests(expectedRequestCount);
   2182         assertFalse(testFactory.getMyStartRequested());
   2183 
   2184         // Bring in a bunch of requests.
   2185         testFactory.expectAddRequests(10);
   2186         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   2187         ConnectivityManager.NetworkCallback[] networkCallbacks =
   2188                 new ConnectivityManager.NetworkCallback[10];
   2189         for (int i = 0; i< networkCallbacks.length; i++) {
   2190             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
   2191             NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2192             builder.addCapability(capability);
   2193             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
   2194         }
   2195         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
   2196         assertFalse(testFactory.getMyStartRequested());
   2197 
   2198         // Remove the requests.
   2199         testFactory.expectRemoveRequests(10);
   2200         for (int i = 0; i < networkCallbacks.length; i++) {
   2201             mCm.unregisterNetworkCallback(networkCallbacks[i]);
   2202         }
   2203         testFactory.waitForNetworkRequests(expectedRequestCount);
   2204         assertFalse(testFactory.getMyStartRequested());
   2205 
   2206         // Drop the higher scored network.
   2207         cv = testFactory.getNetworkStartedCV();
   2208         testAgent.disconnect();
   2209         waitFor(cv);
   2210         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   2211         assertTrue(testFactory.getMyStartRequested());
   2212 
   2213         testFactory.unregister();
   2214         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
   2215         handlerThread.quit();
   2216     }
   2217 
   2218     @Test
   2219     public void testNetworkFactoryRequests() throws Exception {
   2220         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
   2221         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
   2222         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
   2223         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
   2224         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
   2225         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
   2226         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
   2227         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
   2228         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
   2229         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
   2230         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
   2231         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
   2232         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
   2233         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
   2234         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
   2235         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
   2236     }
   2237 
   2238     @Test
   2239     public void testNoMutableNetworkRequests() throws Exception {
   2240         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
   2241         NetworkRequest request1 = new NetworkRequest.Builder()
   2242                 .addCapability(NET_CAPABILITY_VALIDATED)
   2243                 .build();
   2244         NetworkRequest request2 = new NetworkRequest.Builder()
   2245                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
   2246                 .build();
   2247 
   2248         Class<IllegalArgumentException> expected = IllegalArgumentException.class;
   2249         assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
   2250         assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
   2251         assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
   2252         assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
   2253     }
   2254 
   2255     @Test
   2256     public void testMMSonWiFi() throws Exception {
   2257         // Test bringing up cellular without MMS NetworkRequest gets reaped
   2258         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2259         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   2260         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
   2261         mCellNetworkAgent.connectWithoutInternet();
   2262         waitFor(cv);
   2263         waitForIdle();
   2264         assertEmpty(mCm.getAllNetworks());
   2265         verifyNoNetwork();
   2266 
   2267         // Test bringing up validated WiFi.
   2268         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2269         cv = waitForConnectivityBroadcasts(1);
   2270         mWiFiNetworkAgent.connect(true);
   2271         waitFor(cv);
   2272         verifyActiveNetwork(TRANSPORT_WIFI);
   2273 
   2274         // Register MMS NetworkRequest
   2275         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2276         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
   2277         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   2278         mCm.requestNetwork(builder.build(), networkCallback);
   2279 
   2280         // Test bringing up unvalidated cellular with MMS
   2281         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2282         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   2283         mCellNetworkAgent.connectWithoutInternet();
   2284         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
   2285         verifyActiveNetwork(TRANSPORT_WIFI);
   2286 
   2287         // Test releasing NetworkRequest disconnects cellular with MMS
   2288         cv = mCellNetworkAgent.getDisconnectedCV();
   2289         mCm.unregisterNetworkCallback(networkCallback);
   2290         waitFor(cv);
   2291         verifyActiveNetwork(TRANSPORT_WIFI);
   2292     }
   2293 
   2294     @Test
   2295     public void testMMSonCell() throws Exception {
   2296         // Test bringing up cellular without MMS
   2297         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2298         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   2299         mCellNetworkAgent.connect(false);
   2300         waitFor(cv);
   2301         verifyActiveNetwork(TRANSPORT_CELLULAR);
   2302 
   2303         // Register MMS NetworkRequest
   2304         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2305         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
   2306         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   2307         mCm.requestNetwork(builder.build(), networkCallback);
   2308 
   2309         // Test bringing up MMS cellular network
   2310         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2311         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   2312         mmsNetworkAgent.connectWithoutInternet();
   2313         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
   2314         verifyActiveNetwork(TRANSPORT_CELLULAR);
   2315 
   2316         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
   2317         cv = mmsNetworkAgent.getDisconnectedCV();
   2318         mCm.unregisterNetworkCallback(networkCallback);
   2319         waitFor(cv);
   2320         verifyActiveNetwork(TRANSPORT_CELLULAR);
   2321     }
   2322 
   2323     @Test
   2324     public void testCaptivePortal() {
   2325         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2326         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2327                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2328         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2329 
   2330         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2331         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2332                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2333         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2334 
   2335         // Bring up a network with a captive portal.
   2336         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   2337         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2338         String firstRedirectUrl = "http://example.com/firstPath";
   2339         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
   2340         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2341         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
   2342 
   2343         // Take down network.
   2344         // Expect onLost callback.
   2345         mWiFiNetworkAgent.disconnect();
   2346         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2347 
   2348         // Bring up a network with a captive portal.
   2349         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   2350         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2351         String secondRedirectUrl = "http://example.com/secondPath";
   2352         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
   2353         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2354         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
   2355 
   2356         // Make captive portal disappear then revalidate.
   2357         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
   2358         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
   2359         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   2360         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2361 
   2362         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
   2363         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2364 
   2365         // Break network connectivity.
   2366         // Expect NET_CAPABILITY_VALIDATED onLost callback.
   2367         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
   2368         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
   2369         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2370     }
   2371 
   2372     @Test
   2373     public void testCaptivePortalApp() {
   2374         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2375         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2376                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2377         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2378 
   2379         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2380         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2381                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2382         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2383 
   2384         // Bring up wifi.
   2385         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2386         mWiFiNetworkAgent.connect(true);
   2387         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2388         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
   2389 
   2390         // Check that calling startCaptivePortalApp does nothing.
   2391         final int fastTimeoutMs = 100;
   2392         mCm.startCaptivePortalApp(wifiNetwork);
   2393         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
   2394 
   2395         // Turn into a captive portal.
   2396         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
   2397         mCm.reportNetworkConnectivity(wifiNetwork, false);
   2398         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2399         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2400 
   2401         // Check that startCaptivePortalApp sends the expected intent.
   2402         mCm.startCaptivePortalApp(wifiNetwork);
   2403         Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
   2404         assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
   2405         assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
   2406 
   2407         // Have the app report that the captive portal is dismissed, and check that we revalidate.
   2408         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
   2409         CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
   2410         c.reportCaptivePortalDismissed();
   2411         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   2412         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2413 
   2414         mCm.unregisterNetworkCallback(validatedCallback);
   2415         mCm.unregisterNetworkCallback(captivePortalCallback);
   2416     }
   2417 
   2418     @Test
   2419     public void testAvoidOrIgnoreCaptivePortals() {
   2420         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   2421         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   2422                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   2423         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   2424 
   2425         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   2426         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   2427                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   2428         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   2429 
   2430         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
   2431         // Bring up a network with a captive portal.
   2432         // Expect it to fail to connect and not result in any callbacks.
   2433         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2434         String firstRedirectUrl = "http://example.com/firstPath";
   2435 
   2436         ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
   2437         ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
   2438         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
   2439         waitFor(disconnectCv);
   2440         waitFor(avoidCv);
   2441 
   2442         assertNoCallbacks(captivePortalCallback, validatedCallback);
   2443 
   2444         // Now test ignore mode.
   2445         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
   2446 
   2447         // Bring up a network with a captive portal.
   2448         // Since we're ignoring captive portals, the network will validate.
   2449         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2450         String secondRedirectUrl = "http://example.com/secondPath";
   2451         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
   2452 
   2453         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
   2454         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   2455         // But there should be no CaptivePortal callback.
   2456         captivePortalCallback.assertNoCallback();
   2457     }
   2458 
   2459     private NetworkRequest.Builder newWifiRequestBuilder() {
   2460         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
   2461     }
   2462 
   2463     @Test
   2464     public void testNetworkSpecifier() {
   2465         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
   2466         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
   2467         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
   2468         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
   2469             (NetworkSpecifier) null).build();
   2470         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
   2471         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
   2472                 new StringNetworkSpecifier("bar")).build();
   2473 
   2474         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
   2475         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
   2476         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
   2477         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
   2478         TestNetworkCallback cFoo = new TestNetworkCallback();
   2479         TestNetworkCallback cBar = new TestNetworkCallback();
   2480         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
   2481                 cEmpty1, cEmpty2, cEmpty3 };
   2482 
   2483         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
   2484         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
   2485         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
   2486         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
   2487         mCm.registerNetworkCallback(rFoo, cFoo);
   2488         mCm.registerNetworkCallback(rBar, cBar);
   2489 
   2490         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2491         mWiFiNetworkAgent.connect(false);
   2492         cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2493         cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2494         cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2495         cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2496         assertNoCallbacks(cFoo, cBar);
   2497 
   2498         mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
   2499         cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2500         for (TestNetworkCallback c: emptyCallbacks) {
   2501             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
   2502         }
   2503         cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
   2504         cFoo.assertNoCallback();
   2505 
   2506         mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
   2507         cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2508         cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2509         for (TestNetworkCallback c: emptyCallbacks) {
   2510             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
   2511         }
   2512         cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
   2513         cBar.assertNoCallback();
   2514 
   2515         mWiFiNetworkAgent.setNetworkSpecifier(null);
   2516         cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2517         for (TestNetworkCallback c: emptyCallbacks) {
   2518             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
   2519         }
   2520 
   2521         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
   2522     }
   2523 
   2524     @Test
   2525     public void testInvalidNetworkSpecifier() {
   2526         try {
   2527             NetworkRequest.Builder builder = new NetworkRequest.Builder();
   2528             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
   2529             fail("NetworkRequest builder with MatchAllNetworkSpecifier");
   2530         } catch (IllegalArgumentException expected) {
   2531             // expected
   2532         }
   2533 
   2534         try {
   2535             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
   2536             networkCapabilities.addTransportType(TRANSPORT_WIFI)
   2537                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
   2538             mService.requestNetwork(networkCapabilities, null, 0, null,
   2539                     ConnectivityManager.TYPE_WIFI);
   2540             fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
   2541         } catch (IllegalArgumentException expected) {
   2542             // expected
   2543         }
   2544 
   2545         class NonParcelableSpecifier extends NetworkSpecifier {
   2546             public boolean satisfiedBy(NetworkSpecifier other) { return false; }
   2547         };
   2548         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
   2549             @Override public int describeContents() { return 0; }
   2550             @Override public void writeToParcel(Parcel p, int flags) {}
   2551         }
   2552         NetworkRequest.Builder builder;
   2553 
   2554         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
   2555         try {
   2556             builder.setNetworkSpecifier(new NonParcelableSpecifier());
   2557             Parcel parcelW = Parcel.obtain();
   2558             builder.build().writeToParcel(parcelW, 0);
   2559             fail("Parceling a non-parcelable specifier did not throw an exception");
   2560         } catch (Exception e) {
   2561             // expected
   2562         }
   2563 
   2564         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
   2565         builder.setNetworkSpecifier(new ParcelableSpecifier());
   2566         NetworkRequest nr = builder.build();
   2567         assertNotNull(nr);
   2568 
   2569         try {
   2570             Parcel parcelW = Parcel.obtain();
   2571             nr.writeToParcel(parcelW, 0);
   2572             byte[] bytes = parcelW.marshall();
   2573             parcelW.recycle();
   2574 
   2575             Parcel parcelR = Parcel.obtain();
   2576             parcelR.unmarshall(bytes, 0, bytes.length);
   2577             parcelR.setDataPosition(0);
   2578             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
   2579             fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
   2580         } catch (Exception e) {
   2581             // expected
   2582         }
   2583     }
   2584 
   2585     @Test
   2586     public void testNetworkSpecifierUidSpoofSecurityException() {
   2587         class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
   2588             @Override
   2589             public boolean satisfiedBy(NetworkSpecifier other) {
   2590                 return true;
   2591             }
   2592 
   2593             @Override
   2594             public void assertValidFromUid(int requestorUid) {
   2595                 throw new SecurityException("failure");
   2596             }
   2597 
   2598             @Override
   2599             public int describeContents() { return 0; }
   2600             @Override
   2601             public void writeToParcel(Parcel dest, int flags) {}
   2602         }
   2603 
   2604         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2605         mWiFiNetworkAgent.connect(false);
   2606 
   2607         UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
   2608         NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
   2609                 networkSpecifier).build();
   2610         TestNetworkCallback networkCallback = new TestNetworkCallback();
   2611         try {
   2612             mCm.requestNetwork(networkRequest, networkCallback);
   2613             fail("Network request with spoofed UID did not throw a SecurityException");
   2614         } catch (SecurityException e) {
   2615             // expected
   2616         }
   2617     }
   2618 
   2619     @Test
   2620     public void testRegisterDefaultNetworkCallback() throws Exception {
   2621         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
   2622         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
   2623         defaultNetworkCallback.assertNoCallback();
   2624 
   2625         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
   2626         // whenever Wi-Fi is up. Without this, the mobile network agent is
   2627         // reaped before any other activity can take place.
   2628         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   2629         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2630                 .addTransportType(TRANSPORT_CELLULAR).build();
   2631         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   2632         cellNetworkCallback.assertNoCallback();
   2633 
   2634         // Bring up cell and expect CALLBACK_AVAILABLE.
   2635         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2636         mCellNetworkAgent.connect(true);
   2637         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2638         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2639         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2640 
   2641         // Bring up wifi and expect CALLBACK_AVAILABLE.
   2642         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2643         mWiFiNetworkAgent.connect(true);
   2644         cellNetworkCallback.assertNoCallback();
   2645         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   2646         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2647 
   2648         // Bring down cell. Expect no default network callback, since it wasn't the default.
   2649         mCellNetworkAgent.disconnect();
   2650         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2651         defaultNetworkCallback.assertNoCallback();
   2652         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2653 
   2654         // Bring up cell. Expect no default network callback, since it won't be the default.
   2655         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2656         mCellNetworkAgent.connect(true);
   2657         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2658         defaultNetworkCallback.assertNoCallback();
   2659         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2660 
   2661         // Bring down wifi. Expect the default network callback to notified of LOST wifi
   2662         // followed by AVAILABLE cell.
   2663         mWiFiNetworkAgent.disconnect();
   2664         cellNetworkCallback.assertNoCallback();
   2665         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2666         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2667         mCellNetworkAgent.disconnect();
   2668         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2669         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2670         waitForIdle();
   2671         assertEquals(null, mCm.getActiveNetwork());
   2672 
   2673         final int uid = Process.myUid();
   2674         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   2675         final ArraySet<UidRange> ranges = new ArraySet<>();
   2676         ranges.add(new UidRange(uid, uid));
   2677         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   2678         mMockVpn.setUids(ranges);
   2679         vpnNetworkAgent.connect(true);
   2680         mMockVpn.connect();
   2681         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   2682         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   2683 
   2684         vpnNetworkAgent.disconnect();
   2685         defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   2686         waitForIdle();
   2687         assertEquals(null, mCm.getActiveNetwork());
   2688     }
   2689 
   2690     @Test
   2691     public void testAdditionalStateCallbacks() throws Exception {
   2692         // File a network request for mobile.
   2693         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   2694         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2695                 .addTransportType(TRANSPORT_CELLULAR).build();
   2696         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   2697 
   2698         // Bring up the mobile network.
   2699         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2700         mCellNetworkAgent.connect(true);
   2701 
   2702         // We should get onAvailable(), onCapabilitiesChanged(), and
   2703         // onLinkPropertiesChanged() in rapid succession. Additionally, we
   2704         // should get onCapabilitiesChanged() when the mobile network validates.
   2705         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2706         cellNetworkCallback.assertNoCallback();
   2707 
   2708         // Update LinkProperties.
   2709         final LinkProperties lp = new LinkProperties();
   2710         lp.setInterfaceName("foonet_data0");
   2711         mCellNetworkAgent.sendLinkProperties(lp);
   2712         // We should get onLinkPropertiesChanged().
   2713         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   2714         cellNetworkCallback.assertNoCallback();
   2715 
   2716         // Suspend the network.
   2717         mCellNetworkAgent.suspend();
   2718         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
   2719                 mCellNetworkAgent);
   2720         cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
   2721         cellNetworkCallback.assertNoCallback();
   2722 
   2723         // Register a garden variety default network request.
   2724         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
   2725         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
   2726         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
   2727         // as well as onNetworkSuspended() in rapid succession.
   2728         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
   2729         dfltNetworkCallback.assertNoCallback();
   2730         mCm.unregisterNetworkCallback(dfltNetworkCallback);
   2731 
   2732         mCellNetworkAgent.resume();
   2733         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
   2734                 mCellNetworkAgent);
   2735         cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
   2736         cellNetworkCallback.assertNoCallback();
   2737 
   2738         dfltNetworkCallback = new TestNetworkCallback();
   2739         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
   2740         // This time onNetworkSuspended should not be called.
   2741         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2742         dfltNetworkCallback.assertNoCallback();
   2743 
   2744         mCm.unregisterNetworkCallback(dfltNetworkCallback);
   2745         mCm.unregisterNetworkCallback(cellNetworkCallback);
   2746     }
   2747 
   2748     private void setCaptivePortalMode(int mode) {
   2749         ContentResolver cr = mServiceContext.getContentResolver();
   2750         Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
   2751     }
   2752 
   2753     private void setMobileDataAlwaysOn(boolean enable) {
   2754         ContentResolver cr = mServiceContext.getContentResolver();
   2755         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
   2756         mService.updateMobileDataAlwaysOn();
   2757         waitForIdle();
   2758     }
   2759 
   2760     private void setPrivateDnsSettings(String mode, String specifier) {
   2761         final ContentResolver cr = mServiceContext.getContentResolver();
   2762         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
   2763         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
   2764         mService.updatePrivateDnsSettings();
   2765         waitForIdle();
   2766     }
   2767 
   2768     private boolean isForegroundNetwork(MockNetworkAgent network) {
   2769         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
   2770         assertNotNull(nc);
   2771         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
   2772     }
   2773 
   2774     @Test
   2775     public void testBackgroundNetworks() throws Exception {
   2776         // Create a background request. We can't do this ourselves because ConnectivityService
   2777         // doesn't have an API for it. So just turn on mobile data always on.
   2778         setMobileDataAlwaysOn(true);
   2779         final NetworkRequest request = new NetworkRequest.Builder().build();
   2780         final NetworkRequest fgRequest = new NetworkRequest.Builder()
   2781                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
   2782         final TestNetworkCallback callback = new TestNetworkCallback();
   2783         final TestNetworkCallback fgCallback = new TestNetworkCallback();
   2784         mCm.registerNetworkCallback(request, callback);
   2785         mCm.registerNetworkCallback(fgRequest, fgCallback);
   2786 
   2787         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2788         mCellNetworkAgent.connect(true);
   2789         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2790         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2791         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   2792 
   2793         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2794         mWiFiNetworkAgent.connect(true);
   2795 
   2796         // When wifi connects, cell lingers.
   2797         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2798         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2799         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2800         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   2801         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   2802         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   2803         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   2804         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   2805 
   2806         // When lingering is complete, cell is still there but is now in the background.
   2807         waitForIdle();
   2808         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
   2809         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
   2810         // Expect a network capabilities update sans FOREGROUND.
   2811         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   2812         assertFalse(isForegroundNetwork(mCellNetworkAgent));
   2813         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   2814 
   2815         // File a cell request and check that cell comes into the foreground.
   2816         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2817                 .addTransportType(TRANSPORT_CELLULAR).build();
   2818         final TestNetworkCallback cellCallback = new TestNetworkCallback();
   2819         mCm.requestNetwork(cellRequest, cellCallback);
   2820         // NOTE: This request causes the network's capabilities to change. This
   2821         // is currently delivered before the onAvailable() callbacks.
   2822         // TODO: Fix this.
   2823         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   2824         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2825         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2826         // Expect a network capabilities update with FOREGROUND, because the most recent
   2827         // request causes its state to change.
   2828         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   2829         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   2830         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   2831 
   2832         // Release the request. The network immediately goes into the background, since it was not
   2833         // lingering.
   2834         mCm.unregisterNetworkCallback(cellCallback);
   2835         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2836         // Expect a network capabilities update sans FOREGROUND.
   2837         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
   2838         assertFalse(isForegroundNetwork(mCellNetworkAgent));
   2839         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   2840 
   2841         // Disconnect wifi and check that cell is foreground again.
   2842         mWiFiNetworkAgent.disconnect();
   2843         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2844         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2845         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   2846         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   2847 
   2848         mCm.unregisterNetworkCallback(callback);
   2849         mCm.unregisterNetworkCallback(fgCallback);
   2850     }
   2851 
   2852     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
   2853     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
   2854         // TODO: turn this unit test into a real benchmarking test.
   2855         // Benchmarks connecting and switching performance in the presence of a large number of
   2856         // NetworkRequests.
   2857         // 1. File NUM_REQUESTS requests.
   2858         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
   2859         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
   2860         //    and NUM_REQUESTS onAvailable callbacks to fire.
   2861         // See how long it took.
   2862         final int NUM_REQUESTS = 90;
   2863         final int REGISTER_TIME_LIMIT_MS = 200;
   2864         final int CONNECT_TIME_LIMIT_MS = 60;
   2865         final int SWITCH_TIME_LIMIT_MS = 60;
   2866         final int UNREGISTER_TIME_LIMIT_MS = 20;
   2867 
   2868         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
   2869         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
   2870         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
   2871         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
   2872 
   2873         for (int i = 0; i < NUM_REQUESTS; i++) {
   2874             callbacks[i] = new NetworkCallback() {
   2875                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
   2876                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
   2877             };
   2878         }
   2879 
   2880         assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
   2881             for (NetworkCallback cb : callbacks) {
   2882                 mCm.registerNetworkCallback(request, cb);
   2883             }
   2884         });
   2885 
   2886         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2887         // Don't request that the network validate, because otherwise connect() will block until
   2888         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
   2889         // and we won't actually measure anything.
   2890         mCellNetworkAgent.connect(false);
   2891 
   2892         long onAvailableDispatchingDuration = durationOf(() -> {
   2893             awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
   2894         });
   2895         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
   2896                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
   2897                 onAvailableDispatchingDuration));
   2898         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
   2899                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
   2900                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
   2901 
   2902         // Give wifi a high enough score that we'll linger cell when wifi comes up.
   2903         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2904         mWiFiNetworkAgent.adjustScore(40);
   2905         mWiFiNetworkAgent.connect(false);
   2906 
   2907         long onLostDispatchingDuration = durationOf(() -> {
   2908             awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
   2909         });
   2910         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
   2911                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
   2912         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
   2913                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
   2914                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
   2915 
   2916         assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
   2917             for (NetworkCallback cb : callbacks) {
   2918                 mCm.unregisterNetworkCallback(cb);
   2919             }
   2920         });
   2921     }
   2922 
   2923     private long durationOf(Runnable fn) {
   2924         long startTime = SystemClock.elapsedRealtime();
   2925         fn.run();
   2926         return SystemClock.elapsedRealtime() - startTime;
   2927     }
   2928 
   2929     private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
   2930         long timeTaken = durationOf(fn);
   2931         String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
   2932         Log.d(TAG, msg);
   2933         assertTrue(msg, timeTaken <= timeLimit);
   2934     }
   2935 
   2936     private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
   2937         try {
   2938             return l.await(timeoutMs, TimeUnit.MILLISECONDS);
   2939         } catch (InterruptedException e) {}
   2940         return false;
   2941     }
   2942 
   2943     @Test
   2944     public void testMobileDataAlwaysOn() throws Exception {
   2945         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   2946         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2947                 .addTransportType(TRANSPORT_CELLULAR).build();
   2948         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   2949 
   2950         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
   2951         handlerThread.start();
   2952         NetworkCapabilities filter = new NetworkCapabilities()
   2953                 .addTransportType(TRANSPORT_CELLULAR)
   2954                 .addCapability(NET_CAPABILITY_INTERNET);
   2955         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   2956                 mServiceContext, "testFactory", filter);
   2957         testFactory.setScoreFilter(40);
   2958 
   2959         // Register the factory and expect it to start looking for a network.
   2960         testFactory.expectAddRequests(1);
   2961         testFactory.register();
   2962         testFactory.waitForNetworkRequests(1);
   2963         assertTrue(testFactory.getMyStartRequested());
   2964 
   2965         // Bring up wifi. The factory stops looking for a network.
   2966         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2967         testFactory.expectAddRequests(2);  // Because the default request changes score twice.
   2968         mWiFiNetworkAgent.connect(true);
   2969         testFactory.waitForNetworkRequests(1);
   2970         assertFalse(testFactory.getMyStartRequested());
   2971 
   2972         ContentResolver cr = mServiceContext.getContentResolver();
   2973 
   2974         // Turn on mobile data always on. The factory starts looking again.
   2975         testFactory.expectAddRequests(1);
   2976         setMobileDataAlwaysOn(true);
   2977         testFactory.waitForNetworkRequests(2);
   2978         assertTrue(testFactory.getMyStartRequested());
   2979 
   2980         // Bring up cell data and check that the factory stops looking.
   2981         assertLength(1, mCm.getAllNetworks());
   2982         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2983         testFactory.expectAddRequests(2);  // Because the cell request changes score twice.
   2984         mCellNetworkAgent.connect(true);
   2985         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   2986         testFactory.waitForNetworkRequests(2);
   2987         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
   2988 
   2989         // Check that cell data stays up.
   2990         waitForIdle();
   2991         verifyActiveNetwork(TRANSPORT_WIFI);
   2992         assertLength(2, mCm.getAllNetworks());
   2993 
   2994         // Turn off mobile data always on and expect the request to disappear...
   2995         testFactory.expectRemoveRequests(1);
   2996         setMobileDataAlwaysOn(false);
   2997         testFactory.waitForNetworkRequests(1);
   2998 
   2999         // ...  and cell data to be torn down.
   3000         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3001         assertLength(1, mCm.getAllNetworks());
   3002 
   3003         testFactory.unregister();
   3004         mCm.unregisterNetworkCallback(cellNetworkCallback);
   3005         handlerThread.quit();
   3006     }
   3007 
   3008     @Test
   3009     public void testAvoidBadWifiSetting() throws Exception {
   3010         final ContentResolver cr = mServiceContext.getContentResolver();
   3011         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
   3012         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
   3013 
   3014         tracker.configRestrictsAvoidBadWifi = false;
   3015         String[] values = new String[] {null, "0", "1"};
   3016         for (int i = 0; i < values.length; i++) {
   3017             Settings.Global.putInt(cr, settingName, 1);
   3018             tracker.reevaluate();
   3019             waitForIdle();
   3020             String msg = String.format("config=false, setting=%s", values[i]);
   3021             assertTrue(mService.avoidBadWifi());
   3022             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
   3023         }
   3024 
   3025         tracker.configRestrictsAvoidBadWifi = true;
   3026 
   3027         Settings.Global.putInt(cr, settingName, 0);
   3028         tracker.reevaluate();
   3029         waitForIdle();
   3030         assertFalse(mService.avoidBadWifi());
   3031         assertFalse(tracker.shouldNotifyWifiUnvalidated());
   3032 
   3033         Settings.Global.putInt(cr, settingName, 1);
   3034         tracker.reevaluate();
   3035         waitForIdle();
   3036         assertTrue(mService.avoidBadWifi());
   3037         assertFalse(tracker.shouldNotifyWifiUnvalidated());
   3038 
   3039         Settings.Global.putString(cr, settingName, null);
   3040         tracker.reevaluate();
   3041         waitForIdle();
   3042         assertFalse(mService.avoidBadWifi());
   3043         assertTrue(tracker.shouldNotifyWifiUnvalidated());
   3044     }
   3045 
   3046     @Test
   3047     public void testAvoidBadWifi() throws Exception {
   3048         final ContentResolver cr = mServiceContext.getContentResolver();
   3049         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
   3050 
   3051         // Pretend we're on a carrier that restricts switching away from bad wifi.
   3052         tracker.configRestrictsAvoidBadWifi = true;
   3053 
   3054         // File a request for cell to ensure it doesn't go down.
   3055         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   3056         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3057                 .addTransportType(TRANSPORT_CELLULAR).build();
   3058         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   3059 
   3060         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   3061         mCm.registerDefaultNetworkCallback(defaultCallback);
   3062 
   3063         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
   3064                 .addTransportType(TRANSPORT_WIFI)
   3065                 .addCapability(NET_CAPABILITY_VALIDATED)
   3066                 .build();
   3067         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
   3068         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
   3069 
   3070         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
   3071         tracker.reevaluate();
   3072 
   3073         // Bring up validated cell.
   3074         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3075         mCellNetworkAgent.connect(true);
   3076         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3077         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
   3078         Network cellNetwork = mCellNetworkAgent.getNetwork();
   3079 
   3080         // Bring up validated wifi.
   3081         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3082         mWiFiNetworkAgent.connect(true);
   3083         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3084         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3085         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
   3086 
   3087         // Fail validation on wifi.
   3088         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
   3089         mCm.reportNetworkConnectivity(wifiNetwork, false);
   3090         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   3091         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3092 
   3093         // Because avoid bad wifi is off, we don't switch to cellular.
   3094         defaultCallback.assertNoCallback();
   3095         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   3096                 NET_CAPABILITY_VALIDATED));
   3097         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   3098                 NET_CAPABILITY_VALIDATED));
   3099         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   3100 
   3101         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
   3102         // that we switch back to cell.
   3103         tracker.configRestrictsAvoidBadWifi = false;
   3104         tracker.reevaluate();
   3105         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3106         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3107 
   3108         // Switch back to a restrictive carrier.
   3109         tracker.configRestrictsAvoidBadWifi = true;
   3110         tracker.reevaluate();
   3111         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3112         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   3113 
   3114         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
   3115         mCm.setAvoidUnvalidated(wifiNetwork);
   3116         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3117         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   3118                 NET_CAPABILITY_VALIDATED));
   3119         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   3120                 NET_CAPABILITY_VALIDATED));
   3121         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3122 
   3123         // Disconnect and reconnect wifi to clear the one-time switch above.
   3124         mWiFiNetworkAgent.disconnect();
   3125         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3126         mWiFiNetworkAgent.connect(true);
   3127         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3128         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
   3129         wifiNetwork = mWiFiNetworkAgent.getNetwork();
   3130 
   3131         // Fail validation on wifi and expect the dialog to appear.
   3132         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
   3133         mCm.reportNetworkConnectivity(wifiNetwork, false);
   3134         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
   3135         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3136 
   3137         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
   3138         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
   3139         tracker.reevaluate();
   3140 
   3141         // We now switch to cell.
   3142         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3143         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   3144                 NET_CAPABILITY_VALIDATED));
   3145         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   3146                 NET_CAPABILITY_VALIDATED));
   3147         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3148 
   3149         // Simulate the user turning the cellular fallback setting off and then on.
   3150         // We switch to wifi and then to cell.
   3151         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
   3152         tracker.reevaluate();
   3153         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3154         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   3155         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
   3156         tracker.reevaluate();
   3157         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
   3158         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   3159 
   3160         // If cell goes down, we switch to wifi.
   3161         mCellNetworkAgent.disconnect();
   3162         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   3163         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   3164         validatedWifiCallback.assertNoCallback();
   3165 
   3166         mCm.unregisterNetworkCallback(cellNetworkCallback);
   3167         mCm.unregisterNetworkCallback(validatedWifiCallback);
   3168         mCm.unregisterNetworkCallback(defaultCallback);
   3169     }
   3170 
   3171     @Test
   3172     public void testMeteredMultipathPreferenceSetting() throws Exception {
   3173         final ContentResolver cr = mServiceContext.getContentResolver();
   3174         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
   3175         final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
   3176 
   3177         for (int config : Arrays.asList(0, 3, 2)) {
   3178             for (String setting: Arrays.asList(null, "0", "2", "1")) {
   3179                 tracker.configMeteredMultipathPreference = config;
   3180                 Settings.Global.putString(cr, settingName, setting);
   3181                 tracker.reevaluate();
   3182                 waitForIdle();
   3183 
   3184                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
   3185                 String msg = String.format("config=%d, setting=%s", config, setting);
   3186                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
   3187             }
   3188         }
   3189     }
   3190 
   3191     /**
   3192      * Validate that a satisfied network request does not trigger onUnavailable() once the
   3193      * time-out period expires.
   3194      */
   3195     @Test
   3196     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
   3197         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3198                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3199         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3200         final int timeoutMs = 150;
   3201         mCm.requestNetwork(nr, networkCallback, timeoutMs);
   3202 
   3203         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3204         mWiFiNetworkAgent.connect(false);
   3205         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs);
   3206 
   3207         // pass timeout and validate that UNAVAILABLE is not called
   3208         networkCallback.assertNoCallback();
   3209     }
   3210 
   3211     /**
   3212      * Validate that a satisfied network request followed by a disconnected (lost) network does
   3213      * not trigger onUnavailable() once the time-out period expires.
   3214      */
   3215     @Test
   3216     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
   3217         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3218                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3219         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3220         final int requestTimeoutMs = 50;
   3221         mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
   3222 
   3223         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3224         mWiFiNetworkAgent.connect(false);
   3225         final int assertTimeoutMs = 100;
   3226         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs);
   3227         mWiFiNetworkAgent.disconnect();
   3228         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   3229 
   3230         // Validate that UNAVAILABLE is not called
   3231         networkCallback.assertNoCallback();
   3232     }
   3233 
   3234     /**
   3235      * Validate that when a time-out is specified for a network request the onUnavailable()
   3236      * callback is called when time-out expires. Then validate that if network request is
   3237      * (somehow) satisfied - the callback isn't called later.
   3238      */
   3239     @Test
   3240     public void testTimedoutNetworkRequest() {
   3241         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3242                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3243         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3244         final int timeoutMs = 10;
   3245         mCm.requestNetwork(nr, networkCallback, timeoutMs);
   3246 
   3247         // pass timeout and validate that UNAVAILABLE is called
   3248         networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
   3249 
   3250         // create a network satisfying request - validate that request not triggered
   3251         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3252         mWiFiNetworkAgent.connect(false);
   3253         networkCallback.assertNoCallback();
   3254     }
   3255 
   3256     /**
   3257      * Validate that when a network request is unregistered (cancelled), no posterior event can
   3258      * trigger the callback.
   3259      */
   3260     @Test
   3261     public void testNoCallbackAfterUnregisteredNetworkRequest() {
   3262         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
   3263                 NetworkCapabilities.TRANSPORT_WIFI).build();
   3264         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3265         final int timeoutMs = 10;
   3266 
   3267         mCm.requestNetwork(nr, networkCallback, timeoutMs);
   3268         mCm.unregisterNetworkCallback(networkCallback);
   3269         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
   3270         // that this callback will not be called.
   3271         networkCallback.assertNoCallback();
   3272 
   3273         // create a network satisfying request - validate that request not triggered
   3274         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3275         mWiFiNetworkAgent.connect(false);
   3276         networkCallback.assertNoCallback();
   3277     }
   3278 
   3279     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
   3280 
   3281         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
   3282 
   3283         private class CallbackValue {
   3284             public CallbackType callbackType;
   3285             public int error;
   3286 
   3287             public CallbackValue(CallbackType type) {
   3288                 this.callbackType = type;
   3289                 this.error = PacketKeepalive.SUCCESS;
   3290                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
   3291             }
   3292 
   3293             public CallbackValue(CallbackType type, int error) {
   3294                 this.callbackType = type;
   3295                 this.error = error;
   3296                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
   3297             }
   3298 
   3299             @Override
   3300             public boolean equals(Object o) {
   3301                 return o instanceof CallbackValue &&
   3302                         this.callbackType == ((CallbackValue) o).callbackType &&
   3303                         this.error == ((CallbackValue) o).error;
   3304             }
   3305 
   3306             @Override
   3307             public String toString() {
   3308                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
   3309             }
   3310         }
   3311 
   3312         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
   3313 
   3314         @Override
   3315         public void onStarted() {
   3316             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
   3317         }
   3318 
   3319         @Override
   3320         public void onStopped() {
   3321             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
   3322         }
   3323 
   3324         @Override
   3325         public void onError(int error) {
   3326             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
   3327         }
   3328 
   3329         private void expectCallback(CallbackValue callbackValue) {
   3330             try {
   3331                 assertEquals(
   3332                         callbackValue,
   3333                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
   3334             } catch (InterruptedException e) {
   3335                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
   3336             }
   3337         }
   3338 
   3339         public void expectStarted() {
   3340             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
   3341         }
   3342 
   3343         public void expectStopped() {
   3344             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
   3345         }
   3346 
   3347         public void expectError(int error) {
   3348             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
   3349         }
   3350     }
   3351 
   3352     private Network connectKeepaliveNetwork(LinkProperties lp) {
   3353         // Ensure the network is disconnected before we do anything.
   3354         if (mWiFiNetworkAgent != null) {
   3355             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
   3356         }
   3357 
   3358         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3359         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   3360         mWiFiNetworkAgent.connect(true);
   3361         waitFor(cv);
   3362         verifyActiveNetwork(TRANSPORT_WIFI);
   3363         mWiFiNetworkAgent.sendLinkProperties(lp);
   3364         waitForIdle();
   3365         return mWiFiNetworkAgent.getNetwork();
   3366     }
   3367 
   3368     @Test
   3369     public void testPacketKeepalives() throws Exception {
   3370         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
   3371         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
   3372         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
   3373         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
   3374         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
   3375 
   3376         final int validKaInterval = 15;
   3377         final int invalidKaInterval = 9;
   3378 
   3379         LinkProperties lp = new LinkProperties();
   3380         lp.setInterfaceName("wlan12");
   3381         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
   3382         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
   3383         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
   3384         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
   3385 
   3386         Network notMyNet = new Network(61234);
   3387         Network myNet = connectKeepaliveNetwork(lp);
   3388 
   3389         TestKeepaliveCallback callback = new TestKeepaliveCallback();
   3390         PacketKeepalive ka;
   3391 
   3392         // Attempt to start keepalives with invalid parameters and check for errors.
   3393         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
   3394         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
   3395 
   3396         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
   3397         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
   3398 
   3399         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
   3400         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   3401 
   3402         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
   3403         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   3404 
   3405         // NAT-T is only supported for IPv4.
   3406         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
   3407         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   3408 
   3409         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
   3410         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
   3411 
   3412         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
   3413         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
   3414 
   3415         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3416         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
   3417 
   3418         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3419         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
   3420 
   3421         // Check that a started keepalive can be stopped.
   3422         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   3423         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3424         callback.expectStarted();
   3425         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
   3426         ka.stop();
   3427         callback.expectStopped();
   3428 
   3429         // Check that deleting the IP address stops the keepalive.
   3430         LinkProperties bogusLp = new LinkProperties(lp);
   3431         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3432         callback.expectStarted();
   3433         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
   3434         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
   3435         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
   3436         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   3437         mWiFiNetworkAgent.sendLinkProperties(lp);
   3438 
   3439         // Check that a started keepalive is stopped correctly when the network disconnects.
   3440         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3441         callback.expectStarted();
   3442         mWiFiNetworkAgent.disconnect();
   3443         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   3444         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
   3445 
   3446         // ... and that stopping it after that has no adverse effects.
   3447         waitForIdle();
   3448         final Network myNetAlias = myNet;
   3449         assertNull(mCm.getNetworkCapabilities(myNetAlias));
   3450         ka.stop();
   3451 
   3452         // Reconnect.
   3453         myNet = connectKeepaliveNetwork(lp);
   3454         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   3455 
   3456         // Check things work as expected when the keepalive is stopped and the network disconnects.
   3457         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3458         callback.expectStarted();
   3459         ka.stop();
   3460         mWiFiNetworkAgent.disconnect();
   3461         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
   3462         waitForIdle();
   3463         callback.expectStopped();
   3464 
   3465         // Reconnect.
   3466         myNet = connectKeepaliveNetwork(lp);
   3467         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   3468 
   3469         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
   3470         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   3471         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
   3472         callback.expectStarted();
   3473 
   3474         // The second one gets slot 2.
   3475         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
   3476         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
   3477         PacketKeepalive ka2 = mCm.startNattKeepalive(
   3478                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
   3479         callback2.expectStarted();
   3480 
   3481         // Now stop the first one and create a third. This also gets slot 1.
   3482         ka.stop();
   3483         callback.expectStopped();
   3484 
   3485         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   3486         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
   3487         PacketKeepalive ka3 = mCm.startNattKeepalive(
   3488                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
   3489         callback3.expectStarted();
   3490 
   3491         ka2.stop();
   3492         callback2.expectStopped();
   3493 
   3494         ka3.stop();
   3495         callback3.expectStopped();
   3496     }
   3497 
   3498     @Test
   3499     public void testGetCaptivePortalServerUrl() throws Exception {
   3500         String url = mCm.getCaptivePortalServerUrl();
   3501         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
   3502     }
   3503 
   3504     private static class TestNetworkPinner extends NetworkPinner {
   3505         public static boolean awaitPin(int timeoutMs) {
   3506             synchronized(sLock) {
   3507                 if (sNetwork == null) {
   3508                     try {
   3509                         sLock.wait(timeoutMs);
   3510                     } catch (InterruptedException e) {}
   3511                 }
   3512                 return sNetwork != null;
   3513             }
   3514         }
   3515 
   3516         public static boolean awaitUnpin(int timeoutMs) {
   3517             synchronized(sLock) {
   3518                 if (sNetwork != null) {
   3519                     try {
   3520                         sLock.wait(timeoutMs);
   3521                     } catch (InterruptedException e) {}
   3522                 }
   3523                 return sNetwork == null;
   3524             }
   3525         }
   3526     }
   3527 
   3528     private void assertPinnedToWifiWithCellDefault() {
   3529         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
   3530         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   3531     }
   3532 
   3533     private void assertPinnedToWifiWithWifiDefault() {
   3534         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
   3535         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   3536     }
   3537 
   3538     private void assertNotPinnedToWifi() {
   3539         assertNull(mCm.getBoundNetworkForProcess());
   3540         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   3541     }
   3542 
   3543     @Test
   3544     public void testNetworkPinner() {
   3545         NetworkRequest wifiRequest = new NetworkRequest.Builder()
   3546                 .addTransportType(TRANSPORT_WIFI)
   3547                 .build();
   3548         assertNull(mCm.getBoundNetworkForProcess());
   3549 
   3550         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   3551         assertNull(mCm.getBoundNetworkForProcess());
   3552 
   3553         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3554         mCellNetworkAgent.connect(true);
   3555         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3556         mWiFiNetworkAgent.connect(false);
   3557 
   3558         // When wi-fi connects, expect to be pinned.
   3559         assertTrue(TestNetworkPinner.awaitPin(100));
   3560         assertPinnedToWifiWithCellDefault();
   3561 
   3562         // Disconnect and expect the pin to drop.
   3563         mWiFiNetworkAgent.disconnect();
   3564         assertTrue(TestNetworkPinner.awaitUnpin(100));
   3565         assertNotPinnedToWifi();
   3566 
   3567         // Reconnecting does not cause the pin to come back.
   3568         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3569         mWiFiNetworkAgent.connect(false);
   3570         assertFalse(TestNetworkPinner.awaitPin(100));
   3571         assertNotPinnedToWifi();
   3572 
   3573         // Pinning while connected causes the pin to take effect immediately.
   3574         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   3575         assertTrue(TestNetworkPinner.awaitPin(100));
   3576         assertPinnedToWifiWithCellDefault();
   3577 
   3578         // Explicitly unpin and expect to use the default network again.
   3579         TestNetworkPinner.unpin();
   3580         assertNotPinnedToWifi();
   3581 
   3582         // Disconnect cell and wifi.
   3583         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
   3584         mCellNetworkAgent.disconnect();
   3585         mWiFiNetworkAgent.disconnect();
   3586         waitFor(cv);
   3587 
   3588         // Pinning takes effect even if the pinned network is the default when the pin is set...
   3589         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   3590         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3591         mWiFiNetworkAgent.connect(false);
   3592         assertTrue(TestNetworkPinner.awaitPin(100));
   3593         assertPinnedToWifiWithWifiDefault();
   3594 
   3595         // ... and is maintained even when that network is no longer the default.
   3596         cv = waitForConnectivityBroadcasts(1);
   3597         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3598         mCellNetworkAgent.connect(true);
   3599         waitFor(cv);
   3600         assertPinnedToWifiWithCellDefault();
   3601     }
   3602 
   3603     @Test
   3604     public void testNetworkCallbackMaximum() {
   3605         // We can only have 99 callbacks, because MultipathPolicyTracker is
   3606         // already one of them.
   3607         final int MAX_REQUESTS = 99;
   3608         final int CALLBACKS = 89;
   3609         final int INTENTS = 10;
   3610         assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
   3611 
   3612         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
   3613         ArrayList<Object> registered = new ArrayList<>();
   3614 
   3615         int j = 0;
   3616         while (j++ < CALLBACKS / 2) {
   3617             NetworkCallback cb = new NetworkCallback();
   3618             mCm.requestNetwork(networkRequest, cb);
   3619             registered.add(cb);
   3620         }
   3621         while (j++ < CALLBACKS) {
   3622             NetworkCallback cb = new NetworkCallback();
   3623             mCm.registerNetworkCallback(networkRequest, cb);
   3624             registered.add(cb);
   3625         }
   3626         j = 0;
   3627         while (j++ < INTENTS / 2) {
   3628             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
   3629             mCm.requestNetwork(networkRequest, pi);
   3630             registered.add(pi);
   3631         }
   3632         while (j++ < INTENTS) {
   3633             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
   3634             mCm.registerNetworkCallback(networkRequest, pi);
   3635             registered.add(pi);
   3636         }
   3637 
   3638         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
   3639         try {
   3640             mCm.requestNetwork(networkRequest, new NetworkCallback());
   3641             fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
   3642         } catch (TooManyRequestsException expected) {}
   3643         try {
   3644             mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
   3645             fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
   3646         } catch (TooManyRequestsException expected) {}
   3647         try {
   3648             mCm.requestNetwork(networkRequest,
   3649                 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
   3650             fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
   3651         } catch (TooManyRequestsException expected) {}
   3652         try {
   3653             mCm.registerNetworkCallback(networkRequest,
   3654                 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
   3655             fail("Registering " + MAX_REQUESTS
   3656                     + " PendingIntent callbacks did not throw exception");
   3657         } catch (TooManyRequestsException expected) {}
   3658 
   3659         for (Object o : registered) {
   3660             if (o instanceof NetworkCallback) {
   3661                 mCm.unregisterNetworkCallback((NetworkCallback)o);
   3662             }
   3663             if (o instanceof PendingIntent) {
   3664                 mCm.unregisterNetworkCallback((PendingIntent)o);
   3665             }
   3666         }
   3667         waitForIdle();
   3668 
   3669         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
   3670         for (int i = 0; i < MAX_REQUESTS; i++) {
   3671             NetworkCallback networkCallback = new NetworkCallback();
   3672             mCm.requestNetwork(networkRequest, networkCallback);
   3673             mCm.unregisterNetworkCallback(networkCallback);
   3674         }
   3675         waitForIdle();
   3676 
   3677         for (int i = 0; i < MAX_REQUESTS; i++) {
   3678             NetworkCallback networkCallback = new NetworkCallback();
   3679             mCm.registerNetworkCallback(networkRequest, networkCallback);
   3680             mCm.unregisterNetworkCallback(networkCallback);
   3681         }
   3682         waitForIdle();
   3683 
   3684         for (int i = 0; i < MAX_REQUESTS; i++) {
   3685             PendingIntent pendingIntent =
   3686                     PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
   3687             mCm.requestNetwork(networkRequest, pendingIntent);
   3688             mCm.unregisterNetworkCallback(pendingIntent);
   3689         }
   3690         waitForIdle();
   3691 
   3692         for (int i = 0; i < MAX_REQUESTS; i++) {
   3693             PendingIntent pendingIntent =
   3694                     PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
   3695             mCm.registerNetworkCallback(networkRequest, pendingIntent);
   3696             mCm.unregisterNetworkCallback(pendingIntent);
   3697         }
   3698     }
   3699 
   3700     @Test
   3701     public void testNetworkInfoOfTypeNone() {
   3702         ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
   3703 
   3704         verifyNoNetwork();
   3705         MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
   3706         assertNull(mCm.getActiveNetworkInfo());
   3707 
   3708         Network[] allNetworks = mCm.getAllNetworks();
   3709         assertLength(1, allNetworks);
   3710         Network network = allNetworks[0];
   3711         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
   3712         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
   3713 
   3714         final NetworkRequest request =
   3715                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
   3716         final TestNetworkCallback callback = new TestNetworkCallback();
   3717         mCm.registerNetworkCallback(request, callback);
   3718 
   3719         // Bring up wifi aware network.
   3720         wifiAware.connect(false, false);
   3721         callback.expectAvailableCallbacksUnvalidated(wifiAware);
   3722 
   3723         assertNull(mCm.getActiveNetworkInfo());
   3724         assertNull(mCm.getActiveNetwork());
   3725         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
   3726         // of this test. Fix it and uncomment the assert below.
   3727         //assertEmpty(mCm.getAllNetworkInfo());
   3728 
   3729         // Disconnect wifi aware network.
   3730         wifiAware.disconnect();
   3731         callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
   3732         mCm.unregisterNetworkCallback(callback);
   3733 
   3734         verifyNoNetwork();
   3735         if (broadcastCV.block(10)) {
   3736             fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
   3737         }
   3738     }
   3739 
   3740     @Test
   3741     public void testDeprecatedAndUnsupportedOperations() throws Exception {
   3742         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
   3743         assertNull(mCm.getNetworkInfo(TYPE_NONE));
   3744         assertNull(mCm.getNetworkForType(TYPE_NONE));
   3745         assertNull(mCm.getLinkProperties(TYPE_NONE));
   3746         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
   3747 
   3748         assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
   3749                 IllegalArgumentException.class);
   3750 
   3751         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
   3752         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
   3753         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
   3754         // TODO: let test context have configuration application target sdk version
   3755         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
   3756         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
   3757         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
   3758         assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
   3759     }
   3760 
   3761     @Test
   3762     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
   3763         final NetworkRequest networkRequest = new NetworkRequest.Builder()
   3764                 .addTransportType(TRANSPORT_WIFI).build();
   3765         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   3766         mCm.registerNetworkCallback(networkRequest, networkCallback);
   3767 
   3768         LinkProperties lp = new LinkProperties();
   3769         lp.setInterfaceName(WIFI_IFNAME);
   3770         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
   3771         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
   3772                 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
   3773         lp.addLinkAddress(myIpv4Address);
   3774         lp.addRoute(myIpv4DefaultRoute);
   3775 
   3776         // Verify direct routes are added when network agent is first registered in
   3777         // ConnectivityService.
   3778         MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
   3779         networkAgent.connect(true);
   3780         networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
   3781         networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
   3782         CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   3783                 networkAgent);
   3784         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
   3785         networkCallback.assertNoCallback();
   3786         checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
   3787                 Arrays.asList(myIpv4DefaultRoute));
   3788         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
   3789                 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
   3790 
   3791         // Verify direct routes are added during subsequent link properties updates.
   3792         LinkProperties newLp = new LinkProperties(lp);
   3793         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
   3794         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
   3795         newLp.addLinkAddress(myIpv6Address1);
   3796         newLp.addLinkAddress(myIpv6Address2);
   3797         networkAgent.sendLinkProperties(newLp);
   3798         cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
   3799         networkCallback.assertNoCallback();
   3800         checkDirectlyConnectedRoutes(cbi.arg,
   3801                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
   3802                 Arrays.asList(myIpv4DefaultRoute));
   3803         mCm.unregisterNetworkCallback(networkCallback);
   3804     }
   3805 
   3806     @Test
   3807     public void testStatsIfacesChanged() throws Exception {
   3808         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3809         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   3810 
   3811         Network[] onlyCell = new Network[]{mCellNetworkAgent.getNetwork()};
   3812         Network[] onlyWifi = new Network[]{mWiFiNetworkAgent.getNetwork()};
   3813 
   3814         // Simple connection should have updated ifaces
   3815         mCellNetworkAgent.connect(false);
   3816         waitForIdle();
   3817         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
   3818         reset(mStatsService);
   3819 
   3820         // Default network switch should update ifaces.
   3821         mWiFiNetworkAgent.connect(false);
   3822         waitForIdle();
   3823         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyWifi);
   3824         reset(mStatsService);
   3825 
   3826         // Disconnect should update ifaces.
   3827         mWiFiNetworkAgent.disconnect();
   3828         waitForIdle();
   3829         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
   3830         reset(mStatsService);
   3831 
   3832         // Metered change should update ifaces
   3833         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   3834         waitForIdle();
   3835         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
   3836         reset(mStatsService);
   3837 
   3838         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   3839         waitForIdle();
   3840         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
   3841         reset(mStatsService);
   3842 
   3843         // Captive portal change shouldn't update ifaces
   3844         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
   3845         waitForIdle();
   3846         verify(mStatsService, never()).forceUpdateIfaces(onlyCell);
   3847         reset(mStatsService);
   3848 
   3849         // Roaming change should update ifaces
   3850         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
   3851         waitForIdle();
   3852         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
   3853         reset(mStatsService);
   3854     }
   3855 
   3856     @Test
   3857     public void testBasicDnsConfigurationPushed() throws Exception {
   3858         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   3859         ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
   3860 
   3861         // Clear any interactions that occur as a result of CS starting up.
   3862         reset(mNetworkManagementService);
   3863 
   3864         final String[] EMPTY_STRING_ARRAY = new String[0];
   3865         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3866         waitForIdle();
   3867         verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
   3868                 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
   3869         verifyNoMoreInteractions(mNetworkManagementService);
   3870 
   3871         final LinkProperties cellLp = new LinkProperties();
   3872         cellLp.setInterfaceName(MOBILE_IFNAME);
   3873         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
   3874         // "is-reachable" testing in order to not program netd with unreachable
   3875         // nameservers that it might try repeated to validate.
   3876         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
   3877         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
   3878                 MOBILE_IFNAME));
   3879         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
   3880         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
   3881                 MOBILE_IFNAME));
   3882         mCellNetworkAgent.sendLinkProperties(cellLp);
   3883         mCellNetworkAgent.connect(false);
   3884         waitForIdle();
   3885         // CS tells netd about the empty DNS config for this network.
   3886         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
   3887                 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
   3888         reset(mNetworkManagementService);
   3889 
   3890         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
   3891         mCellNetworkAgent.sendLinkProperties(cellLp);
   3892         waitForIdle();
   3893         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
   3894                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
   3895                 eq(""), tlsServers.capture());
   3896         assertEquals(1, mStringArrayCaptor.getValue().length);
   3897         assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
   3898         // Opportunistic mode.
   3899         assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
   3900         reset(mNetworkManagementService);
   3901 
   3902         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
   3903         mCellNetworkAgent.sendLinkProperties(cellLp);
   3904         waitForIdle();
   3905         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
   3906                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
   3907                 eq(""), tlsServers.capture());
   3908         assertEquals(2, mStringArrayCaptor.getValue().length);
   3909         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
   3910                 new String[]{"2001:db8::1", "192.0.2.1"}));
   3911         // Opportunistic mode.
   3912         assertEquals(2, tlsServers.getValue().length);
   3913         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
   3914                 new String[]{"2001:db8::1", "192.0.2.1"}));
   3915         reset(mNetworkManagementService);
   3916 
   3917         final String TLS_SPECIFIER = "tls.example.com";
   3918         final String TLS_SERVER6 = "2001:db8:53::53";
   3919         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
   3920         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
   3921         final Handler h = mCellNetworkAgent.getWrappedNetworkMonitor().connectivityHandler;
   3922         h.sendMessage(h.obtainMessage(
   3923                 NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0,
   3924                 mCellNetworkAgent.getNetwork().netId,
   3925                 new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
   3926         waitForIdle();
   3927         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
   3928                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
   3929                 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
   3930         assertEquals(2, mStringArrayCaptor.getValue().length);
   3931         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
   3932                 new String[]{"2001:db8::1", "192.0.2.1"}));
   3933         reset(mNetworkManagementService);
   3934     }
   3935 
   3936     @Test
   3937     public void testPrivateDnsSettingsChange() throws Exception {
   3938         final String[] EMPTY_STRING_ARRAY = new String[0];
   3939         ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
   3940 
   3941         // Clear any interactions that occur as a result of CS starting up.
   3942         reset(mNetworkManagementService);
   3943 
   3944         // The default on Android is opportunistic mode ("Automatic").
   3945         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   3946 
   3947         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   3948         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   3949                 .addTransportType(TRANSPORT_CELLULAR).build();
   3950         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   3951 
   3952         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   3953         waitForIdle();
   3954         // CS tells netd about the empty DNS config for this network.
   3955         verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
   3956                 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
   3957         verifyNoMoreInteractions(mNetworkManagementService);
   3958 
   3959         final LinkProperties cellLp = new LinkProperties();
   3960         cellLp.setInterfaceName(MOBILE_IFNAME);
   3961         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
   3962         // "is-reachable" testing in order to not program netd with unreachable
   3963         // nameservers that it might try repeated to validate.
   3964         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
   3965         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
   3966                 MOBILE_IFNAME));
   3967         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
   3968         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
   3969                 MOBILE_IFNAME));
   3970         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
   3971         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
   3972 
   3973         mCellNetworkAgent.sendLinkProperties(cellLp);
   3974         mCellNetworkAgent.connect(false);
   3975         waitForIdle();
   3976         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
   3977                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
   3978                 eq(""), tlsServers.capture());
   3979         assertEquals(2, mStringArrayCaptor.getValue().length);
   3980         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
   3981                 new String[]{"2001:db8::1", "192.0.2.1"}));
   3982         // Opportunistic mode.
   3983         assertEquals(2, tlsServers.getValue().length);
   3984         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
   3985                 new String[]{"2001:db8::1", "192.0.2.1"}));
   3986         reset(mNetworkManagementService);
   3987         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   3988         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
   3989                 mCellNetworkAgent);
   3990         CallbackInfo cbi = cellNetworkCallback.expectCallback(
   3991                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   3992         cellNetworkCallback.assertNoCallback();
   3993         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   3994         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   3995 
   3996         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
   3997         verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
   3998                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
   3999                 eq(""), eq(EMPTY_STRING_ARRAY));
   4000         assertEquals(2, mStringArrayCaptor.getValue().length);
   4001         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
   4002                 new String[]{"2001:db8::1", "192.0.2.1"}));
   4003         reset(mNetworkManagementService);
   4004         cellNetworkCallback.assertNoCallback();
   4005 
   4006         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   4007         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
   4008                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
   4009                 eq(""), tlsServers.capture());
   4010         assertEquals(2, mStringArrayCaptor.getValue().length);
   4011         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
   4012                 new String[]{"2001:db8::1", "192.0.2.1"}));
   4013         assertEquals(2, tlsServers.getValue().length);
   4014         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
   4015                 new String[]{"2001:db8::1", "192.0.2.1"}));
   4016         reset(mNetworkManagementService);
   4017         cellNetworkCallback.assertNoCallback();
   4018 
   4019         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
   4020         // Can't test dns configuration for strict mode without properly mocking
   4021         // out the DNS lookups, but can test that LinkProperties is updated.
   4022         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   4023                 mCellNetworkAgent);
   4024         cellNetworkCallback.assertNoCallback();
   4025         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
   4026         assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
   4027     }
   4028 
   4029     @Test
   4030     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
   4031         // The default on Android is opportunistic mode ("Automatic").
   4032         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
   4033 
   4034         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   4035         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   4036                 .addTransportType(TRANSPORT_CELLULAR).build();
   4037         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   4038 
   4039         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   4040         waitForIdle();
   4041         LinkProperties lp = new LinkProperties();
   4042         mCellNetworkAgent.sendLinkProperties(lp);
   4043         mCellNetworkAgent.connect(false);
   4044         waitForIdle();
   4045         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   4046         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
   4047                 mCellNetworkAgent);
   4048         CallbackInfo cbi = cellNetworkCallback.expectCallback(
   4049                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   4050         cellNetworkCallback.assertNoCallback();
   4051         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   4052         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   4053         Set<InetAddress> dnsServers = new HashSet<>();
   4054         checkDnsServers(cbi.arg, dnsServers);
   4055 
   4056         // Send a validation event for a server that is not part of the current
   4057         // resolver config. The validation event should be ignored.
   4058         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   4059                 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
   4060         cellNetworkCallback.assertNoCallback();
   4061 
   4062         // Add a dns server to the LinkProperties.
   4063         LinkProperties lp2 = new LinkProperties(lp);
   4064         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
   4065         mCellNetworkAgent.sendLinkProperties(lp2);
   4066         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   4067                 mCellNetworkAgent);
   4068         cellNetworkCallback.assertNoCallback();
   4069         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   4070         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   4071         dnsServers.add(InetAddress.getByName("145.100.185.16"));
   4072         checkDnsServers(cbi.arg, dnsServers);
   4073 
   4074         // Send a validation event containing a hostname that is not part of
   4075         // the current resolver config. The validation event should be ignored.
   4076         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   4077                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
   4078         cellNetworkCallback.assertNoCallback();
   4079 
   4080         // Send a validation event where validation failed.
   4081         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   4082                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
   4083         cellNetworkCallback.assertNoCallback();
   4084 
   4085         // Send a validation event where validation succeeded for a server in
   4086         // the current resolver config. A LinkProperties callback with updated
   4087         // private dns fields should be sent.
   4088         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
   4089                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
   4090         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   4091                 mCellNetworkAgent);
   4092         cellNetworkCallback.assertNoCallback();
   4093         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
   4094         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   4095         checkDnsServers(cbi.arg, dnsServers);
   4096 
   4097         // The private dns fields in LinkProperties should be preserved when
   4098         // the network agent sends unrelated changes.
   4099         LinkProperties lp3 = new LinkProperties(lp2);
   4100         lp3.setMtu(1300);
   4101         mCellNetworkAgent.sendLinkProperties(lp3);
   4102         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   4103                 mCellNetworkAgent);
   4104         cellNetworkCallback.assertNoCallback();
   4105         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
   4106         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   4107         checkDnsServers(cbi.arg, dnsServers);
   4108         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
   4109 
   4110         // Removing the only validated server should affect the private dns
   4111         // fields in LinkProperties.
   4112         LinkProperties lp4 = new LinkProperties(lp3);
   4113         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
   4114         mCellNetworkAgent.sendLinkProperties(lp4);
   4115         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
   4116                 mCellNetworkAgent);
   4117         cellNetworkCallback.assertNoCallback();
   4118         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
   4119         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
   4120         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
   4121         checkDnsServers(cbi.arg, dnsServers);
   4122         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
   4123     }
   4124 
   4125     private void checkDirectlyConnectedRoutes(Object callbackObj,
   4126             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
   4127         assertTrue(callbackObj instanceof LinkProperties);
   4128         LinkProperties lp = (LinkProperties) callbackObj;
   4129 
   4130         Set<RouteInfo> expectedRoutes = new ArraySet<>();
   4131         expectedRoutes.addAll(otherRoutes);
   4132         for (LinkAddress address : linkAddresses) {
   4133             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
   4134             // Duplicates in linkAddresses are considered failures
   4135             assertTrue(expectedRoutes.add(localRoute));
   4136         }
   4137         List<RouteInfo> observedRoutes = lp.getRoutes();
   4138         assertEquals(expectedRoutes.size(), observedRoutes.size());
   4139         assertTrue(observedRoutes.containsAll(expectedRoutes));
   4140     }
   4141 
   4142     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
   4143         assertTrue(callbackObj instanceof LinkProperties);
   4144         LinkProperties lp = (LinkProperties) callbackObj;
   4145         assertEquals(dnsServers.size(), lp.getDnsServers().size());
   4146         assertTrue(lp.getDnsServers().containsAll(dnsServers));
   4147     }
   4148 
   4149     private static <T> void assertEmpty(T[] ts) {
   4150         int length = ts.length;
   4151         assertEquals("expected empty array, but length was " + length, 0, length);
   4152     }
   4153 
   4154     private static <T> void assertLength(int expected, T[] got) {
   4155         int length = got.length;
   4156         assertEquals(String.format("expected array of length %s, but length was %s for %s",
   4157                 expected, length, Arrays.toString(got)), expected, length);
   4158     }
   4159 
   4160     private static <T> void assertException(Runnable block, Class<T> expected) {
   4161         try {
   4162             block.run();
   4163             fail("Expected exception of type " + expected);
   4164         } catch (Exception got) {
   4165             if (!got.getClass().equals(expected)) {
   4166                 fail("Expected exception of type " + expected + " but got " + got);
   4167             }
   4168             return;
   4169         }
   4170     }
   4171 
   4172     @Test
   4173     public void testVpnNetworkActive() {
   4174         final int uid = Process.myUid();
   4175 
   4176         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
   4177         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
   4178         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
   4179         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
   4180         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
   4181         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
   4182         final NetworkRequest genericRequest = new NetworkRequest.Builder()
   4183                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
   4184         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
   4185                 .addTransportType(TRANSPORT_WIFI).build();
   4186         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
   4187                 .removeCapability(NET_CAPABILITY_NOT_VPN)
   4188                 .addTransportType(TRANSPORT_VPN).build();
   4189         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
   4190         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
   4191         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
   4192         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
   4193         mCm.registerDefaultNetworkCallback(defaultCallback);
   4194         defaultCallback.assertNoCallback();
   4195 
   4196         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4197         mWiFiNetworkAgent.connect(false);
   4198 
   4199         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   4200         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   4201         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   4202         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
   4203         vpnNetworkCallback.assertNoCallback();
   4204         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   4205 
   4206         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   4207         final ArraySet<UidRange> ranges = new ArraySet<>();
   4208         ranges.add(new UidRange(uid, uid));
   4209         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   4210         mMockVpn.setUids(ranges);
   4211         vpnNetworkAgent.connect(false);
   4212         mMockVpn.connect();
   4213 
   4214         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   4215         genericNotVpnNetworkCallback.assertNoCallback();
   4216         wifiNetworkCallback.assertNoCallback();
   4217         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   4218         defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
   4219         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   4220 
   4221         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   4222         genericNotVpnNetworkCallback.assertNoCallback();
   4223         vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
   4224         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   4225         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   4226 
   4227         ranges.clear();
   4228         vpnNetworkAgent.setUids(ranges);
   4229 
   4230         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   4231         genericNotVpnNetworkCallback.assertNoCallback();
   4232         wifiNetworkCallback.assertNoCallback();
   4233         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   4234 
   4235         // TODO : The default network callback should actually get a LOST call here (also see the
   4236         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
   4237         // ranges at all when determining whether a network should be rematched. In practice, VPNs
   4238         // can't currently update their UIDs without disconnecting, so this does not matter too
   4239         // much, but that is the reason the test here has to check for an update to the
   4240         // capabilities instead of the expected LOST then AVAILABLE.
   4241         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   4242 
   4243         ranges.add(new UidRange(uid, uid));
   4244         mMockVpn.setUids(ranges);
   4245 
   4246         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
   4247         genericNotVpnNetworkCallback.assertNoCallback();
   4248         wifiNetworkCallback.assertNoCallback();
   4249         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
   4250         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
   4251         // happen outside of the test, ConnectivityService does not rematch callbacks.
   4252         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
   4253 
   4254         mWiFiNetworkAgent.disconnect();
   4255 
   4256         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   4257         genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   4258         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   4259         vpnNetworkCallback.assertNoCallback();
   4260         defaultCallback.assertNoCallback();
   4261 
   4262         vpnNetworkAgent.disconnect();
   4263 
   4264         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   4265         genericNotVpnNetworkCallback.assertNoCallback();
   4266         wifiNetworkCallback.assertNoCallback();
   4267         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   4268         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   4269         assertEquals(null, mCm.getActiveNetwork());
   4270 
   4271         mCm.unregisterNetworkCallback(genericNetworkCallback);
   4272         mCm.unregisterNetworkCallback(wifiNetworkCallback);
   4273         mCm.unregisterNetworkCallback(vpnNetworkCallback);
   4274         mCm.unregisterNetworkCallback(defaultCallback);
   4275     }
   4276 
   4277     @Test
   4278     public void testVpnWithAndWithoutInternet() {
   4279         final int uid = Process.myUid();
   4280 
   4281         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
   4282         mCm.registerDefaultNetworkCallback(defaultCallback);
   4283         defaultCallback.assertNoCallback();
   4284 
   4285         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4286         mWiFiNetworkAgent.connect(true);
   4287 
   4288         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
   4289         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   4290 
   4291         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   4292         final ArraySet<UidRange> ranges = new ArraySet<>();
   4293         ranges.add(new UidRange(uid, uid));
   4294         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   4295         mMockVpn.setUids(ranges);
   4296         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
   4297         mMockVpn.connect();
   4298 
   4299         defaultCallback.assertNoCallback();
   4300         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   4301 
   4302         vpnNetworkAgent.disconnect();
   4303         defaultCallback.assertNoCallback();
   4304 
   4305         vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   4306         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   4307         mMockVpn.setUids(ranges);
   4308         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
   4309         mMockVpn.connect();
   4310         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   4311         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
   4312 
   4313         vpnNetworkAgent.disconnect();
   4314         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
   4315         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
   4316 
   4317         vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   4318         ranges.clear();
   4319         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   4320         mMockVpn.setUids(ranges);
   4321         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
   4322         mMockVpn.connect();
   4323         defaultCallback.assertNoCallback();
   4324 
   4325         mCm.unregisterNetworkCallback(defaultCallback);
   4326     }
   4327 
   4328     @Test
   4329     public void testVpnSetUnderlyingNetworks() {
   4330         final int uid = Process.myUid();
   4331 
   4332         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
   4333         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
   4334                 .removeCapability(NET_CAPABILITY_NOT_VPN)
   4335                 .addTransportType(TRANSPORT_VPN)
   4336                 .build();
   4337         NetworkCapabilities nc;
   4338         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
   4339         vpnNetworkCallback.assertNoCallback();
   4340 
   4341         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
   4342         final ArraySet<UidRange> ranges = new ArraySet<>();
   4343         ranges.add(new UidRange(uid, uid));
   4344         mMockVpn.setNetworkAgent(vpnNetworkAgent);
   4345         mMockVpn.connect();
   4346         mMockVpn.setUids(ranges);
   4347         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
   4348 
   4349         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
   4350         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
   4351         assertTrue(nc.hasTransport(TRANSPORT_VPN));
   4352         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
   4353         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
   4354         // For safety reasons a VPN without underlying networks is considered metered.
   4355         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
   4356 
   4357         // Connect cell and use it as an underlying network.
   4358         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   4359         mCellNetworkAgent.connect(true);
   4360 
   4361         mService.setUnderlyingNetworksForVpn(
   4362                 new Network[] { mCellNetworkAgent.getNetwork() });
   4363 
   4364         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4365                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   4366                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4367                 vpnNetworkAgent);
   4368 
   4369         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   4370         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   4371         mWiFiNetworkAgent.connect(true);
   4372 
   4373         mService.setUnderlyingNetworksForVpn(
   4374                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
   4375 
   4376         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4377                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   4378                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4379                 vpnNetworkAgent);
   4380 
   4381         // Don't disconnect, but note the VPN is not using wifi any more.
   4382         mService.setUnderlyingNetworksForVpn(
   4383                 new Network[] { mCellNetworkAgent.getNetwork() });
   4384 
   4385         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4386                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   4387                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4388                 vpnNetworkAgent);
   4389 
   4390         // Use Wifi but not cell. Note the VPN is now unmetered.
   4391         mService.setUnderlyingNetworksForVpn(
   4392                 new Network[] { mWiFiNetworkAgent.getNetwork() });
   4393 
   4394         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4395                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   4396                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4397                 vpnNetworkAgent);
   4398 
   4399         // Use both again.
   4400         mService.setUnderlyingNetworksForVpn(
   4401                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
   4402 
   4403         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4404                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   4405                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4406                 vpnNetworkAgent);
   4407 
   4408         // Disconnect cell. Receive update without even removing the dead network from the
   4409         // underlying networks  it's dead anyway. Not metered any more.
   4410         mCellNetworkAgent.disconnect();
   4411         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4412                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
   4413                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4414                 vpnNetworkAgent);
   4415 
   4416         // Disconnect wifi too. No underlying networks means this is now metered.
   4417         mWiFiNetworkAgent.disconnect();
   4418         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
   4419                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
   4420                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
   4421                 vpnNetworkAgent);
   4422 
   4423         mMockVpn.disconnect();
   4424     }
   4425 }
   4426