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.TYPE_ETHERNET;
     21 import static android.net.ConnectivityManager.TYPE_MOBILE;
     22 import static android.net.ConnectivityManager.TYPE_WIFI;
     23 import static android.net.ConnectivityManager.getNetworkTypeName;
     24 import static android.net.NetworkCapabilities.*;
     25 
     26 import static org.mockito.Mockito.mock;
     27 
     28 import android.app.NotificationManager;
     29 import android.app.PendingIntent;
     30 import android.content.BroadcastReceiver;
     31 import android.content.ContentResolver;
     32 import android.content.Context;
     33 import android.content.ContextWrapper;
     34 import android.content.Intent;
     35 import android.content.IntentFilter;
     36 import android.net.ConnectivityManager;
     37 import android.net.ConnectivityManager.NetworkCallback;
     38 import android.net.ConnectivityManager.PacketKeepalive;
     39 import android.net.ConnectivityManager.PacketKeepaliveCallback;
     40 import android.net.INetworkPolicyManager;
     41 import android.net.INetworkStatsService;
     42 import android.net.IpPrefix;
     43 import android.net.LinkAddress;
     44 import android.net.LinkProperties;
     45 import android.net.Network;
     46 import android.net.NetworkAgent;
     47 import android.net.NetworkCapabilities;
     48 import android.net.NetworkConfig;
     49 import android.net.NetworkFactory;
     50 import android.net.NetworkInfo;
     51 import android.net.NetworkInfo.DetailedState;
     52 import android.net.NetworkMisc;
     53 import android.net.NetworkRequest;
     54 import android.net.RouteInfo;
     55 import android.net.metrics.IpConnectivityLog;
     56 import android.net.util.AvoidBadWifiTracker;
     57 import android.os.ConditionVariable;
     58 import android.os.Handler;
     59 import android.os.HandlerThread;
     60 import android.os.IBinder;
     61 import android.os.INetworkManagementService;
     62 import android.os.Looper;
     63 import android.os.Message;
     64 import android.os.MessageQueue;
     65 import android.os.Messenger;
     66 import android.os.MessageQueue.IdleHandler;
     67 import android.os.Process;
     68 import android.os.SystemClock;
     69 import android.provider.Settings;
     70 import android.test.AndroidTestCase;
     71 import android.test.mock.MockContentResolver;
     72 import android.test.suitebuilder.annotation.LargeTest;
     73 import android.test.suitebuilder.annotation.SmallTest;
     74 import android.util.Log;
     75 import android.util.LogPrinter;
     76 
     77 import com.android.internal.util.FakeSettingsProvider;
     78 import com.android.internal.util.WakeupMessage;
     79 import com.android.server.connectivity.NetworkAgentInfo;
     80 import com.android.server.connectivity.NetworkMonitor;
     81 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
     82 import com.android.server.net.NetworkPinner;
     83 
     84 import java.net.InetAddress;
     85 import java.util.ArrayList;
     86 import java.util.Arrays;
     87 import java.util.Objects;
     88 import java.util.concurrent.CountDownLatch;
     89 import java.util.concurrent.LinkedBlockingQueue;
     90 import java.util.concurrent.TimeUnit;
     91 import java.util.concurrent.atomic.AtomicBoolean;
     92 
     93 /**
     94  * Tests for {@link ConnectivityService}.
     95  *
     96  * Build, install and run with:
     97  *  runtest frameworks-services -c com.android.server.ConnectivityServiceTest
     98  */
     99 public class ConnectivityServiceTest extends AndroidTestCase {
    100     private static final String TAG = "ConnectivityServiceTest";
    101 
    102     private static final int TIMEOUT_MS = 500;
    103     private static final int TEST_LINGER_DELAY_MS = 120;
    104 
    105     private BroadcastInterceptingContext mServiceContext;
    106     private WrappedConnectivityService mService;
    107     private WrappedConnectivityManager mCm;
    108     private MockNetworkAgent mWiFiNetworkAgent;
    109     private MockNetworkAgent mCellNetworkAgent;
    110     private MockNetworkAgent mEthernetNetworkAgent;
    111 
    112     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
    113     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
    114     // reflect the state of our test ConnectivityService.
    115     private class WrappedConnectivityManager extends ConnectivityManager {
    116         private Network mFakeBoundNetwork;
    117 
    118         public synchronized boolean bindProcessToNetwork(Network network) {
    119             mFakeBoundNetwork = network;
    120             return true;
    121         }
    122 
    123         public synchronized Network getBoundNetworkForProcess() {
    124             return mFakeBoundNetwork;
    125         }
    126 
    127         public WrappedConnectivityManager(Context context, ConnectivityService service) {
    128             super(context, service);
    129         }
    130     }
    131 
    132     private class MockContext extends BroadcastInterceptingContext {
    133         private final MockContentResolver mContentResolver;
    134 
    135         MockContext(Context base) {
    136             super(base);
    137             mContentResolver = new MockContentResolver();
    138             mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
    139         }
    140 
    141         @Override
    142         public Object getSystemService(String name) {
    143             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
    144             if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
    145             return super.getSystemService(name);
    146         }
    147 
    148         @Override
    149         public ContentResolver getContentResolver() {
    150             return mContentResolver;
    151         }
    152     }
    153 
    154     /**
    155      * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
    156      * will return immediately if the handler is already idle.
    157      */
    158     private class IdleableHandlerThread extends HandlerThread {
    159         private IdleHandler mIdleHandler;
    160 
    161         public IdleableHandlerThread(String name) {
    162             super(name);
    163         }
    164 
    165         public void waitForIdle(int timeoutMs) {
    166             final ConditionVariable cv = new ConditionVariable();
    167             final MessageQueue queue = getLooper().getQueue();
    168 
    169             synchronized (queue) {
    170                 if (queue.isIdle()) {
    171                     return;
    172                 }
    173 
    174                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
    175                 mIdleHandler = new IdleHandler() {
    176                     public boolean queueIdle() {
    177                         synchronized (queue) {
    178                             cv.open();
    179                             mIdleHandler = null;
    180                             return false;  // Remove the handler.
    181                         }
    182                     }
    183                 };
    184                 queue.addIdleHandler(mIdleHandler);
    185             }
    186 
    187             if (!cv.block(timeoutMs)) {
    188                 fail("HandlerThread " + getName() +
    189                         " did not become idle after " + timeoutMs + " ms");
    190                 queue.removeIdleHandler(mIdleHandler);
    191             }
    192         }
    193     }
    194 
    195     // Tests that IdleableHandlerThread works as expected.
    196     public void testIdleableHandlerThread() {
    197         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
    198 
    199         // Tests that waitForIdle returns immediately if the service is already idle.
    200         for (int i = 0; i < attempts; i++) {
    201             mService.waitForIdle();
    202         }
    203 
    204         // Bring up a network that we can use to send messages to ConnectivityService.
    205         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    206         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    207         mWiFiNetworkAgent.connect(false);
    208         waitFor(cv);
    209         Network n = mWiFiNetworkAgent.getNetwork();
    210         assertNotNull(n);
    211 
    212         // Tests that calling waitForIdle waits for messages to be processed.
    213         for (int i = 0; i < attempts; i++) {
    214             mWiFiNetworkAgent.setSignalStrength(i);
    215             mService.waitForIdle();
    216             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
    217         }
    218 
    219         // Ensure that not calling waitForIdle causes a race condition.
    220         for (int i = 0; i < attempts; i++) {
    221             mWiFiNetworkAgent.setSignalStrength(i);
    222             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
    223                 // We hit a race condition, as expected. Pass the test.
    224                 return;
    225             }
    226         }
    227 
    228         // No race? There is a bug in this test.
    229         fail("expected race condition at least once in " + attempts + " attempts");
    230     }
    231 
    232     private class MockNetworkAgent {
    233         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
    234         private final NetworkInfo mNetworkInfo;
    235         private final NetworkCapabilities mNetworkCapabilities;
    236         private final IdleableHandlerThread mHandlerThread;
    237         private final ConditionVariable mDisconnected = new ConditionVariable();
    238         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
    239         private int mScore;
    240         private NetworkAgent mNetworkAgent;
    241         private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
    242         private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
    243         private Integer mExpectedKeepaliveSlot = null;
    244         // Contains the redirectUrl from networkStatus(). Before reading, wait for
    245         // mNetworkStatusReceived.
    246         private String mRedirectUrl;
    247 
    248         MockNetworkAgent(int transport) {
    249             final int type = transportToLegacyType(transport);
    250             final String typeName = ConnectivityManager.getNetworkTypeName(type);
    251             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
    252             mNetworkCapabilities = new NetworkCapabilities();
    253             mNetworkCapabilities.addTransportType(transport);
    254             switch (transport) {
    255                 case TRANSPORT_ETHERNET:
    256                     mScore = 70;
    257                     break;
    258                 case TRANSPORT_WIFI:
    259                     mScore = 60;
    260                     break;
    261                 case TRANSPORT_CELLULAR:
    262                     mScore = 50;
    263                     break;
    264                 default:
    265                     throw new UnsupportedOperationException("unimplemented network type");
    266             }
    267             mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
    268             mHandlerThread.start();
    269             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
    270                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
    271                     new LinkProperties(), mScore, new NetworkMisc()) {
    272                 @Override
    273                 public void unwanted() { mDisconnected.open(); }
    274 
    275                 @Override
    276                 public void startPacketKeepalive(Message msg) {
    277                     int slot = msg.arg1;
    278                     if (mExpectedKeepaliveSlot != null) {
    279                         assertEquals((int) mExpectedKeepaliveSlot, slot);
    280                     }
    281                     onPacketKeepaliveEvent(slot, mStartKeepaliveError);
    282                 }
    283 
    284                 @Override
    285                 public void stopPacketKeepalive(Message msg) {
    286                     onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
    287                 }
    288 
    289                 @Override
    290                 public void networkStatus(int status, String redirectUrl) {
    291                     mRedirectUrl = redirectUrl;
    292                     mNetworkStatusReceived.open();
    293                 }
    294             };
    295             // Waits for the NetworkAgent to be registered, which includes the creation of the
    296             // NetworkMonitor.
    297             mService.waitForIdle();
    298             mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
    299         }
    300 
    301         public void waitForIdle(int timeoutMs) {
    302             mHandlerThread.waitForIdle(timeoutMs);
    303         }
    304 
    305         public void waitForIdle() {
    306             waitForIdle(TIMEOUT_MS);
    307         }
    308 
    309         public void adjustScore(int change) {
    310             mScore += change;
    311             mNetworkAgent.sendNetworkScore(mScore);
    312         }
    313 
    314         public void addCapability(int capability) {
    315             mNetworkCapabilities.addCapability(capability);
    316             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    317         }
    318 
    319         public void removeCapability(int capability) {
    320             mNetworkCapabilities.removeCapability(capability);
    321             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    322         }
    323 
    324         public void setSignalStrength(int signalStrength) {
    325             mNetworkCapabilities.setSignalStrength(signalStrength);
    326             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    327         }
    328 
    329         public void connectWithoutInternet() {
    330             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
    331             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    332         }
    333 
    334         /**
    335          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
    336          * @param validated Indicate if network should pretend to be validated.
    337          */
    338         public void connect(boolean validated) {
    339             assertEquals("MockNetworkAgents can only be connected once",
    340                     mNetworkInfo.getDetailedState(), DetailedState.IDLE);
    341             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
    342 
    343             NetworkCallback callback = null;
    344             final ConditionVariable validatedCv = new ConditionVariable();
    345             if (validated) {
    346                 mWrappedNetworkMonitor.gen204ProbeResult = 204;
    347                 NetworkRequest request = new NetworkRequest.Builder()
    348                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
    349                         .build();
    350                 callback = new NetworkCallback() {
    351                     public void onCapabilitiesChanged(Network network,
    352                             NetworkCapabilities networkCapabilities) {
    353                         if (network.equals(getNetwork()) &&
    354                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
    355                             validatedCv.open();
    356                         }
    357                     }
    358                 };
    359                 mCm.registerNetworkCallback(request, callback);
    360             }
    361             addCapability(NET_CAPABILITY_INTERNET);
    362 
    363             connectWithoutInternet();
    364 
    365             if (validated) {
    366                 // Wait for network to validate.
    367                 waitFor(validatedCv);
    368                 mWrappedNetworkMonitor.gen204ProbeResult = 500;
    369             }
    370 
    371             if (callback != null) mCm.unregisterNetworkCallback(callback);
    372         }
    373 
    374         public void connectWithCaptivePortal(String redirectUrl) {
    375             mWrappedNetworkMonitor.gen204ProbeResult = 200;
    376             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
    377             connect(false);
    378             waitFor(new Criteria() { public boolean get() {
    379                 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
    380                 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
    381             mWrappedNetworkMonitor.gen204ProbeResult = 500;
    382             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null;
    383         }
    384 
    385         public void disconnect() {
    386             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
    387             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    388         }
    389 
    390         public Network getNetwork() {
    391             return new Network(mNetworkAgent.netId);
    392         }
    393 
    394         public ConditionVariable getDisconnectedCV() {
    395             return mDisconnected;
    396         }
    397 
    398         public WrappedNetworkMonitor getWrappedNetworkMonitor() {
    399             return mWrappedNetworkMonitor;
    400         }
    401 
    402         public void sendLinkProperties(LinkProperties lp) {
    403             mNetworkAgent.sendLinkProperties(lp);
    404         }
    405 
    406         public void setStartKeepaliveError(int error) {
    407             mStartKeepaliveError = error;
    408         }
    409 
    410         public void setStopKeepaliveError(int error) {
    411             mStopKeepaliveError = error;
    412         }
    413 
    414         public void setExpectedKeepaliveSlot(Integer slot) {
    415             mExpectedKeepaliveSlot = slot;
    416         }
    417 
    418         public String waitForRedirectUrl() {
    419             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
    420             return mRedirectUrl;
    421         }
    422     }
    423 
    424     /**
    425      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
    426      * operations have been processed. Before ConnectivityService can add or remove any requests,
    427      * the factory must be told to expect those operations by calling expectAddRequests or
    428      * expectRemoveRequests.
    429      */
    430     private static class MockNetworkFactory extends NetworkFactory {
    431         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
    432         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
    433         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
    434 
    435         // Used to expect that requests be removed or added on a separate thread, without sleeping.
    436         // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
    437         // cause some other thread to add or remove requests, then call waitForRequests(). We can
    438         // either expect requests to be added or removed, but not both, because CountDownLatch can
    439         // only count in one direction.
    440         private CountDownLatch mExpectations;
    441 
    442         // Whether we are currently expecting requests to be added or removed. Valid only if
    443         // mExpectations is non-null.
    444         private boolean mExpectingAdditions;
    445 
    446         public MockNetworkFactory(Looper looper, Context context, String logTag,
    447                 NetworkCapabilities filter) {
    448             super(looper, context, logTag, filter);
    449         }
    450 
    451         public int getMyRequestCount() {
    452             return getRequestCount();
    453         }
    454 
    455         protected void startNetwork() {
    456             mNetworkStarted.set(true);
    457             mNetworkStartedCV.open();
    458         }
    459 
    460         protected void stopNetwork() {
    461             mNetworkStarted.set(false);
    462             mNetworkStoppedCV.open();
    463         }
    464 
    465         public boolean getMyStartRequested() {
    466             return mNetworkStarted.get();
    467         }
    468 
    469         public ConditionVariable getNetworkStartedCV() {
    470             mNetworkStartedCV.close();
    471             return mNetworkStartedCV;
    472         }
    473 
    474         public ConditionVariable getNetworkStoppedCV() {
    475             mNetworkStoppedCV.close();
    476             return mNetworkStoppedCV;
    477         }
    478 
    479         @Override
    480         protected void handleAddRequest(NetworkRequest request, int score) {
    481             // If we're expecting anything, we must be expecting additions.
    482             if (mExpectations != null && !mExpectingAdditions) {
    483                 fail("Can't add requests while expecting requests to be removed");
    484             }
    485 
    486             // Add the request.
    487             super.handleAddRequest(request, score);
    488 
    489             // Reduce the number of request additions we're waiting for.
    490             if (mExpectingAdditions) {
    491                 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
    492                 mExpectations.countDown();
    493             }
    494         }
    495 
    496         @Override
    497         protected void handleRemoveRequest(NetworkRequest request) {
    498             // If we're expecting anything, we must be expecting removals.
    499             if (mExpectations != null && mExpectingAdditions) {
    500                 fail("Can't remove requests while expecting requests to be added");
    501             }
    502 
    503             // Remove the request.
    504             super.handleRemoveRequest(request);
    505 
    506             // Reduce the number of request removals we're waiting for.
    507             if (!mExpectingAdditions) {
    508                 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
    509                 mExpectations.countDown();
    510             }
    511         }
    512 
    513         private void assertNoExpectations() {
    514             if (mExpectations != null) {
    515                 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
    516             }
    517         }
    518 
    519         // Expects that count requests will be added.
    520         public void expectAddRequests(final int count) {
    521             assertNoExpectations();
    522             mExpectingAdditions = true;
    523             mExpectations = new CountDownLatch(count);
    524         }
    525 
    526         // Expects that count requests will be removed.
    527         public void expectRemoveRequests(final int count) {
    528             assertNoExpectations();
    529             mExpectingAdditions = false;
    530             mExpectations = new CountDownLatch(count);
    531         }
    532 
    533         // Waits for the expected request additions or removals to happen within a timeout.
    534         public void waitForRequests() throws InterruptedException {
    535             assertNotNull("Nothing to wait for", mExpectations);
    536             mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    537             final long count = mExpectations.getCount();
    538             final String msg = count + " requests still not " +
    539                     (mExpectingAdditions ? "added" : "removed") +
    540                     " after " + TIMEOUT_MS + " ms";
    541             assertEquals(msg, 0, count);
    542             mExpectations = null;
    543         }
    544 
    545         public void waitForNetworkRequests(final int count) throws InterruptedException {
    546             waitForRequests();
    547             assertEquals(count, getMyRequestCount());
    548         }
    549     }
    550 
    551     private class FakeWakeupMessage extends WakeupMessage {
    552         private static final int UNREASONABLY_LONG_WAIT = 1000;
    553 
    554         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
    555             super(context, handler, cmdName, cmd);
    556         }
    557 
    558         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
    559                 int arg1, int arg2, Object obj) {
    560             super(context, handler, cmdName, cmd, arg1, arg2, obj);
    561         }
    562 
    563         @Override
    564         public void schedule(long when) {
    565             long delayMs = when - SystemClock.elapsedRealtime();
    566             if (delayMs < 0) delayMs = 0;
    567             if (delayMs > UNREASONABLY_LONG_WAIT) {
    568                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
    569                         "ms into the future: " + delayMs);
    570             }
    571             Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
    572             mHandler.sendMessageDelayed(msg, delayMs);
    573         }
    574 
    575         @Override
    576         public void cancel() {
    577             mHandler.removeMessages(mCmd, mObj);
    578         }
    579 
    580         @Override
    581         public void onAlarm() {
    582             throw new AssertionError("Should never happen. Update this fake.");
    583         }
    584     }
    585 
    586     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
    587     private class WrappedNetworkMonitor extends NetworkMonitor {
    588         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
    589         public int gen204ProbeResult = 500;
    590         public String gen204ProbeRedirectUrl = null;
    591 
    592         public WrappedNetworkMonitor(Context context, Handler handler,
    593                 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
    594                 IpConnectivityLog log) {
    595             super(context, handler, networkAgentInfo, defaultRequest, log);
    596         }
    597 
    598         @Override
    599         protected CaptivePortalProbeResult isCaptivePortal() {
    600             return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
    601         }
    602     }
    603 
    604     private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
    605         public boolean configRestrictsAvoidBadWifi;
    606 
    607         public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
    608             super(c, h, r);
    609         }
    610 
    611         @Override
    612         public boolean configRestrictsAvoidBadWifi() {
    613             return configRestrictsAvoidBadWifi;
    614         }
    615     }
    616 
    617     private class WrappedConnectivityService extends ConnectivityService {
    618         public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
    619         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
    620 
    621         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
    622                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
    623                 IpConnectivityLog log) {
    624             super(context, netManager, statsService, policyManager, log);
    625             mLingerDelayMs = TEST_LINGER_DELAY_MS;
    626         }
    627 
    628         @Override
    629         protected HandlerThread createHandlerThread() {
    630             return new IdleableHandlerThread("WrappedConnectivityService");
    631         }
    632 
    633         @Override
    634         protected int getDefaultTcpRwnd() {
    635             // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
    636             return 0;
    637         }
    638 
    639         @Override
    640         protected int reserveNetId() {
    641             while (true) {
    642                 final int netId = super.reserveNetId();
    643 
    644                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
    645                 // can have odd side-effects, like network validations succeeding.
    646                 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
    647                 boolean overlaps = false;
    648                 for (Network network : networks) {
    649                     if (netId == network.netId) {
    650                         overlaps = true;
    651                         break;
    652                     }
    653                 }
    654                 if (overlaps) continue;
    655 
    656                 return netId;
    657             }
    658         }
    659 
    660         @Override
    661         public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
    662                 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
    663             final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
    664                     context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
    665             mLastCreatedNetworkMonitor = monitor;
    666             return monitor;
    667         }
    668 
    669         @Override
    670         public AvoidBadWifiTracker createAvoidBadWifiTracker(
    671                 Context c, Handler h, Runnable r) {
    672             final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
    673             return tracker;
    674         }
    675 
    676         public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
    677             return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
    678         }
    679 
    680         @Override
    681         public WakeupMessage makeWakeupMessage(
    682                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
    683             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
    684         }
    685 
    686         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
    687             return mLastCreatedNetworkMonitor;
    688         }
    689 
    690         public void waitForIdle(int timeoutMs) {
    691             ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
    692         }
    693 
    694         public void waitForIdle() {
    695             waitForIdle(TIMEOUT_MS);
    696         }
    697     }
    698 
    699     private interface Criteria {
    700         public boolean get();
    701     }
    702 
    703     /**
    704      * Wait up to 500ms for {@code criteria.get()} to become true, polling.
    705      * Fails if 500ms goes by before {@code criteria.get()} to become true.
    706      */
    707     static private void waitFor(Criteria criteria) {
    708         int delays = 0;
    709         while (!criteria.get()) {
    710             try {
    711                 Thread.sleep(50);
    712             } catch (InterruptedException e) {
    713             }
    714             if (++delays == 10) fail();
    715         }
    716     }
    717 
    718     /**
    719      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
    720      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
    721      */
    722     static private void waitFor(ConditionVariable conditionVariable) {
    723         assertTrue(conditionVariable.block(TIMEOUT_MS));
    724     }
    725 
    726     @Override
    727     public void setUp() throws Exception {
    728         super.setUp();
    729 
    730         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
    731         // http://b/25897652 .
    732         if (Looper.myLooper() == null) {
    733             Looper.prepare();
    734         }
    735 
    736         mServiceContext = new MockContext(getContext());
    737         mService = new WrappedConnectivityService(mServiceContext,
    738                 mock(INetworkManagementService.class),
    739                 mock(INetworkStatsService.class),
    740                 mock(INetworkPolicyManager.class),
    741                 mock(IpConnectivityLog.class));
    742 
    743         mService.systemReady();
    744         mCm = new WrappedConnectivityManager(getContext(), mService);
    745         mCm.bindProcessToNetwork(null);
    746     }
    747 
    748     public void tearDown() throws Exception {
    749         setMobileDataAlwaysOn(false);
    750         if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
    751         if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
    752         mCellNetworkAgent = mWiFiNetworkAgent = null;
    753         super.tearDown();
    754     }
    755 
    756     private int transportToLegacyType(int transport) {
    757         switch (transport) {
    758             case TRANSPORT_ETHERNET:
    759                 return TYPE_ETHERNET;
    760             case TRANSPORT_WIFI:
    761                 return TYPE_WIFI;
    762             case TRANSPORT_CELLULAR:
    763                 return TYPE_MOBILE;
    764             default:
    765                 throw new IllegalStateException("Unknown transport " + transport);
    766         }
    767     }
    768 
    769     private void verifyActiveNetwork(int transport) {
    770         // Test getActiveNetworkInfo()
    771         assertNotNull(mCm.getActiveNetworkInfo());
    772         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
    773         // Test getActiveNetwork()
    774         assertNotNull(mCm.getActiveNetwork());
    775         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
    776         switch (transport) {
    777             case TRANSPORT_WIFI:
    778                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
    779                 break;
    780             case TRANSPORT_CELLULAR:
    781                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
    782                 break;
    783             default:
    784                 throw new IllegalStateException("Unknown transport" + transport);
    785         }
    786         // Test getNetworkInfo(Network)
    787         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
    788         assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
    789         // Test getNetworkCapabilities(Network)
    790         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
    791         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
    792     }
    793 
    794     private void verifyNoNetwork() {
    795         // Test getActiveNetworkInfo()
    796         assertNull(mCm.getActiveNetworkInfo());
    797         // Test getActiveNetwork()
    798         assertNull(mCm.getActiveNetwork());
    799         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
    800         // Test getAllNetworks()
    801         assertEquals(0, mCm.getAllNetworks().length);
    802     }
    803 
    804     /**
    805      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
    806      * broadcasts are received.
    807      */
    808     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
    809         final ConditionVariable cv = new ConditionVariable();
    810         mServiceContext.registerReceiver(new BroadcastReceiver() {
    811                     private int remaining = count;
    812                     public void onReceive(Context context, Intent intent) {
    813                         if (--remaining == 0) {
    814                             cv.open();
    815                             mServiceContext.unregisterReceiver(this);
    816                         }
    817                     }
    818                 }, new IntentFilter(CONNECTIVITY_ACTION));
    819         return cv;
    820     }
    821 
    822     @LargeTest
    823     public void testLingering() throws Exception {
    824         verifyNoNetwork();
    825         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
    826         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    827         assertNull(mCm.getActiveNetworkInfo());
    828         assertNull(mCm.getActiveNetwork());
    829         // Test bringing up validated cellular.
    830         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    831         mCellNetworkAgent.connect(true);
    832         waitFor(cv);
    833         verifyActiveNetwork(TRANSPORT_CELLULAR);
    834         assertEquals(2, mCm.getAllNetworks().length);
    835         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
    836                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
    837         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
    838                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
    839         // Test bringing up validated WiFi.
    840         cv = waitForConnectivityBroadcasts(2);
    841         mWiFiNetworkAgent.connect(true);
    842         waitFor(cv);
    843         verifyActiveNetwork(TRANSPORT_WIFI);
    844         assertEquals(2, mCm.getAllNetworks().length);
    845         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
    846                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
    847         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
    848                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
    849         // Test cellular linger timeout.
    850         waitFor(new Criteria() {
    851                 public boolean get() { return mCm.getAllNetworks().length == 1; } });
    852         verifyActiveNetwork(TRANSPORT_WIFI);
    853         assertEquals(1, mCm.getAllNetworks().length);
    854         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
    855         // Test WiFi disconnect.
    856         cv = waitForConnectivityBroadcasts(1);
    857         mWiFiNetworkAgent.disconnect();
    858         waitFor(cv);
    859         verifyNoNetwork();
    860     }
    861 
    862     @LargeTest
    863     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
    864         // Test bringing up unvalidated WiFi
    865         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    866         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    867         mWiFiNetworkAgent.connect(false);
    868         waitFor(cv);
    869         verifyActiveNetwork(TRANSPORT_WIFI);
    870         // Test bringing up unvalidated cellular
    871         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
    872         mCellNetworkAgent.connect(false);
    873         mService.waitForIdle();
    874         verifyActiveNetwork(TRANSPORT_WIFI);
    875         // Test cellular disconnect.
    876         mCellNetworkAgent.disconnect();
    877         mService.waitForIdle();
    878         verifyActiveNetwork(TRANSPORT_WIFI);
    879         // Test bringing up validated cellular
    880         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
    881         cv = waitForConnectivityBroadcasts(2);
    882         mCellNetworkAgent.connect(true);
    883         waitFor(cv);
    884         verifyActiveNetwork(TRANSPORT_CELLULAR);
    885         // Test cellular disconnect.
    886         cv = waitForConnectivityBroadcasts(2);
    887         mCellNetworkAgent.disconnect();
    888         waitFor(cv);
    889         verifyActiveNetwork(TRANSPORT_WIFI);
    890         // Test WiFi disconnect.
    891         cv = waitForConnectivityBroadcasts(1);
    892         mWiFiNetworkAgent.disconnect();
    893         waitFor(cv);
    894         verifyNoNetwork();
    895     }
    896 
    897     @LargeTest
    898     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
    899         // Test bringing up unvalidated cellular.
    900         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
    901         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    902         mCellNetworkAgent.connect(false);
    903         waitFor(cv);
    904         verifyActiveNetwork(TRANSPORT_CELLULAR);
    905         // Test bringing up unvalidated WiFi.
    906         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    907         cv = waitForConnectivityBroadcasts(2);
    908         mWiFiNetworkAgent.connect(false);
    909         waitFor(cv);
    910         verifyActiveNetwork(TRANSPORT_WIFI);
    911         // Test WiFi disconnect.
    912         cv = waitForConnectivityBroadcasts(2);
    913         mWiFiNetworkAgent.disconnect();
    914         waitFor(cv);
    915         verifyActiveNetwork(TRANSPORT_CELLULAR);
    916         // Test cellular disconnect.
    917         cv = waitForConnectivityBroadcasts(1);
    918         mCellNetworkAgent.disconnect();
    919         waitFor(cv);
    920         verifyNoNetwork();
    921     }
    922 
    923     @LargeTest
    924     public void testUnlingeringDoesNotValidate() throws Exception {
    925         // Test bringing up unvalidated WiFi.
    926         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    927         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    928         mWiFiNetworkAgent.connect(false);
    929         waitFor(cv);
    930         verifyActiveNetwork(TRANSPORT_WIFI);
    931         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
    932                 NET_CAPABILITY_VALIDATED));
    933         // Test bringing up validated cellular.
    934         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
    935         cv = waitForConnectivityBroadcasts(2);
    936         mCellNetworkAgent.connect(true);
    937         waitFor(cv);
    938         verifyActiveNetwork(TRANSPORT_CELLULAR);
    939         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
    940                 NET_CAPABILITY_VALIDATED));
    941         // Test cellular disconnect.
    942         cv = waitForConnectivityBroadcasts(2);
    943         mCellNetworkAgent.disconnect();
    944         waitFor(cv);
    945         verifyActiveNetwork(TRANSPORT_WIFI);
    946         // Unlingering a network should not cause it to be marked as validated.
    947         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
    948                 NET_CAPABILITY_VALIDATED));
    949     }
    950 
    951     @LargeTest
    952     public void testCellularOutscoresWeakWifi() throws Exception {
    953         // Test bringing up validated cellular.
    954         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
    955         ConditionVariable cv = waitForConnectivityBroadcasts(1);
    956         mCellNetworkAgent.connect(true);
    957         waitFor(cv);
    958         verifyActiveNetwork(TRANSPORT_CELLULAR);
    959         // Test bringing up validated WiFi.
    960         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    961         cv = waitForConnectivityBroadcasts(2);
    962         mWiFiNetworkAgent.connect(true);
    963         waitFor(cv);
    964         verifyActiveNetwork(TRANSPORT_WIFI);
    965         // Test WiFi getting really weak.
    966         cv = waitForConnectivityBroadcasts(2);
    967         mWiFiNetworkAgent.adjustScore(-11);
    968         waitFor(cv);
    969         verifyActiveNetwork(TRANSPORT_CELLULAR);
    970         // Test WiFi restoring signal strength.
    971         cv = waitForConnectivityBroadcasts(2);
    972         mWiFiNetworkAgent.adjustScore(11);
    973         waitFor(cv);
    974         verifyActiveNetwork(TRANSPORT_WIFI);
    975     }
    976 
    977     @LargeTest
    978     public void testReapingNetwork() throws Exception {
    979         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
    980         // Expect it to be torn down immediately because it satisfies no requests.
    981         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    982         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
    983         mWiFiNetworkAgent.connectWithoutInternet();
    984         waitFor(cv);
    985         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
    986         // Expect it to be torn down immediately because it satisfies no requests.
    987         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    988         cv = mCellNetworkAgent.getDisconnectedCV();
    989         mCellNetworkAgent.connectWithoutInternet();
    990         waitFor(cv);
    991         // Test bringing up validated WiFi.
    992         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
    993         cv = waitForConnectivityBroadcasts(1);
    994         mWiFiNetworkAgent.connect(true);
    995         waitFor(cv);
    996         verifyActiveNetwork(TRANSPORT_WIFI);
    997         // Test bringing up unvalidated cellular.
    998         // Expect it to be torn down because it could never be the highest scoring network
    999         // satisfying the default request even if it validated.
   1000         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1001         cv = mCellNetworkAgent.getDisconnectedCV();
   1002         mCellNetworkAgent.connect(false);
   1003         waitFor(cv);
   1004         verifyActiveNetwork(TRANSPORT_WIFI);
   1005         cv = mWiFiNetworkAgent.getDisconnectedCV();
   1006         mWiFiNetworkAgent.disconnect();
   1007         waitFor(cv);
   1008     }
   1009 
   1010     @LargeTest
   1011     public void testCellularFallback() throws Exception {
   1012         // Test bringing up validated cellular.
   1013         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1014         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1015         mCellNetworkAgent.connect(true);
   1016         waitFor(cv);
   1017         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1018         // Test bringing up validated WiFi.
   1019         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1020         cv = waitForConnectivityBroadcasts(2);
   1021         mWiFiNetworkAgent.connect(true);
   1022         waitFor(cv);
   1023         verifyActiveNetwork(TRANSPORT_WIFI);
   1024         // Reevaluate WiFi (it'll instantly fail DNS).
   1025         cv = waitForConnectivityBroadcasts(2);
   1026         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1027                 NET_CAPABILITY_VALIDATED));
   1028         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
   1029         // Should quickly fall back to Cellular.
   1030         waitFor(cv);
   1031         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1032                 NET_CAPABILITY_VALIDATED));
   1033         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1034         // Reevaluate cellular (it'll instantly fail DNS).
   1035         cv = waitForConnectivityBroadcasts(2);
   1036         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1037                 NET_CAPABILITY_VALIDATED));
   1038         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
   1039         // Should quickly fall back to WiFi.
   1040         waitFor(cv);
   1041         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1042                 NET_CAPABILITY_VALIDATED));
   1043         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
   1044                 NET_CAPABILITY_VALIDATED));
   1045         verifyActiveNetwork(TRANSPORT_WIFI);
   1046     }
   1047 
   1048     @LargeTest
   1049     public void testWiFiFallback() throws Exception {
   1050         // Test bringing up unvalidated WiFi.
   1051         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1052         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1053         mWiFiNetworkAgent.connect(false);
   1054         waitFor(cv);
   1055         verifyActiveNetwork(TRANSPORT_WIFI);
   1056         // Test bringing up validated cellular.
   1057         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1058         cv = waitForConnectivityBroadcasts(2);
   1059         mCellNetworkAgent.connect(true);
   1060         waitFor(cv);
   1061         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1062         // Reevaluate cellular (it'll instantly fail DNS).
   1063         cv = waitForConnectivityBroadcasts(2);
   1064         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1065                 NET_CAPABILITY_VALIDATED));
   1066         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
   1067         // Should quickly fall back to WiFi.
   1068         waitFor(cv);
   1069         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
   1070                 NET_CAPABILITY_VALIDATED));
   1071         verifyActiveNetwork(TRANSPORT_WIFI);
   1072     }
   1073 
   1074     enum CallbackState {
   1075         NONE,
   1076         AVAILABLE,
   1077         NETWORK_CAPABILITIES,
   1078         LINK_PROPERTIES,
   1079         LOSING,
   1080         LOST
   1081     }
   1082 
   1083     /**
   1084      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
   1085      * this class receives, by calling expectCallback() exactly once each time a callback is
   1086      * received. assertNoCallback may be called at any time.
   1087      */
   1088     private class TestNetworkCallback extends NetworkCallback {
   1089         // Chosen to be much less than the linger timeout. This ensures that we can distinguish
   1090         // between a LOST callback that arrives immediately and a LOST callback that arrives after
   1091         // the linger timeout.
   1092         private final static int TIMEOUT_MS = 50;
   1093 
   1094         private class CallbackInfo {
   1095             public final CallbackState state;
   1096             public final Network network;
   1097             public Object arg;
   1098             public CallbackInfo(CallbackState s, Network n, Object o) {
   1099                 state = s; network = n; arg = o;
   1100             }
   1101             public String toString() { return String.format("%s (%s)", state, network); }
   1102             public boolean equals(Object o) {
   1103                 if (!(o instanceof CallbackInfo)) return false;
   1104                 // Ignore timeMs, since it's unpredictable.
   1105                 CallbackInfo other = (CallbackInfo) o;
   1106                 return state == other.state && Objects.equals(network, other.network);
   1107             }
   1108         }
   1109         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
   1110 
   1111         protected void setLastCallback(CallbackState state, Network network, Object o) {
   1112             mCallbacks.offer(new CallbackInfo(state, network, o));
   1113         }
   1114 
   1115         @Override
   1116         public void onAvailable(Network network) {
   1117             setLastCallback(CallbackState.AVAILABLE, network, null);
   1118         }
   1119 
   1120         @Override
   1121         public void onLosing(Network network, int maxMsToLive) {
   1122             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
   1123         }
   1124 
   1125         @Override
   1126         public void onLost(Network network) {
   1127             setLastCallback(CallbackState.LOST, network, null);
   1128         }
   1129 
   1130         void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
   1131             CallbackInfo expected = new CallbackInfo(
   1132                     state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
   1133             CallbackInfo actual;
   1134             try {
   1135                 actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
   1136                 assertEquals("Unexpected callback:", expected, actual);
   1137             } catch (InterruptedException e) {
   1138                 fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
   1139                 actual = null;  // Or the compiler can't tell it's never used uninitialized.
   1140             }
   1141             if (state == CallbackState.LOSING) {
   1142                 String msg = String.format(
   1143                         "Invalid linger time value %d, must be between %d and %d",
   1144                         actual.arg, 0, TEST_LINGER_DELAY_MS);
   1145                 int maxMsToLive = (Integer) actual.arg;
   1146                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
   1147             }
   1148         }
   1149 
   1150         void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
   1151             expectCallback(state, mockAgent, TIMEOUT_MS);
   1152         }
   1153 
   1154         void assertNoCallback() {
   1155             mService.waitForIdle();
   1156             CallbackInfo c = mCallbacks.peek();
   1157             assertNull("Unexpected callback: " + c, c);
   1158         }
   1159     }
   1160 
   1161     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
   1162     // only be declared in a static or top level type".
   1163     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
   1164         for (TestNetworkCallback c : callbacks) {
   1165             c.assertNoCallback();
   1166         }
   1167     }
   1168 
   1169     @LargeTest
   1170     public void testStateChangeNetworkCallbacks() throws Exception {
   1171         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
   1172         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
   1173         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   1174         final NetworkRequest genericRequest = new NetworkRequest.Builder()
   1175                 .clearCapabilities().build();
   1176         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
   1177                 .addTransportType(TRANSPORT_WIFI).build();
   1178         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   1179                 .addTransportType(TRANSPORT_CELLULAR).build();
   1180         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
   1181         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
   1182         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   1183 
   1184         // Test unvalidated networks
   1185         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1186         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1187         mCellNetworkAgent.connect(false);
   1188         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1189         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1190         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1191         waitFor(cv);
   1192         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1193 
   1194         // This should not trigger spurious onAvailable() callbacks, b/21762680.
   1195         mCellNetworkAgent.adjustScore(-1);
   1196         mService.waitForIdle();
   1197         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1198         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1199 
   1200         cv = waitForConnectivityBroadcasts(2);
   1201         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1202         mWiFiNetworkAgent.connect(false);
   1203         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1204         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1205         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1206         waitFor(cv);
   1207         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1208 
   1209         cv = waitForConnectivityBroadcasts(2);
   1210         mWiFiNetworkAgent.disconnect();
   1211         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1212         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1213         cellNetworkCallback.assertNoCallback();
   1214         waitFor(cv);
   1215         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1216 
   1217         cv = waitForConnectivityBroadcasts(1);
   1218         mCellNetworkAgent.disconnect();
   1219         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1220         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1221         waitFor(cv);
   1222         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1223 
   1224         // Test validated networks
   1225         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1226         mCellNetworkAgent.connect(true);
   1227         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1228         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1229         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1230         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1231 
   1232         // This should not trigger spurious onAvailable() callbacks, b/21762680.
   1233         mCellNetworkAgent.adjustScore(-1);
   1234         mService.waitForIdle();
   1235         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1236         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1237 
   1238         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1239         mWiFiNetworkAgent.connect(true);
   1240         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1241         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1242         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1243         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1244         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1245         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1246 
   1247         mWiFiNetworkAgent.disconnect();
   1248         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1249         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1250         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1251 
   1252         mCellNetworkAgent.disconnect();
   1253         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1254         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1255         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
   1256     }
   1257 
   1258     @SmallTest
   1259     public void testMultipleLingering() {
   1260         NetworkRequest request = new NetworkRequest.Builder()
   1261                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
   1262                 .build();
   1263         TestNetworkCallback callback = new TestNetworkCallback();
   1264         mCm.registerNetworkCallback(request, callback);
   1265 
   1266         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   1267         mCm.registerDefaultNetworkCallback(defaultCallback);
   1268 
   1269         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1270         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1271         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
   1272 
   1273         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   1274         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   1275         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
   1276 
   1277         mCellNetworkAgent.connect(true);
   1278         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1279         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1280         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1281 
   1282         mWiFiNetworkAgent.connect(true);
   1283         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
   1284         // We then get LOSING when wifi validates and cell is outscored.
   1285         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1286         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1287         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1288         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1289 
   1290         mEthernetNetworkAgent.connect(true);
   1291         callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
   1292         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
   1293         defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
   1294         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1295 
   1296         mEthernetNetworkAgent.disconnect();
   1297         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   1298         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
   1299         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1300 
   1301         for (int i = 0; i < 4; i++) {
   1302             MockNetworkAgent oldNetwork, newNetwork;
   1303             if (i % 2 == 0) {
   1304                 mWiFiNetworkAgent.adjustScore(-15);
   1305                 oldNetwork = mWiFiNetworkAgent;
   1306                 newNetwork = mCellNetworkAgent;
   1307             } else {
   1308                 mWiFiNetworkAgent.adjustScore(15);
   1309                 oldNetwork = mCellNetworkAgent;
   1310                 newNetwork = mWiFiNetworkAgent;
   1311 
   1312             }
   1313             callback.expectCallback(CallbackState.LOSING, oldNetwork);
   1314             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
   1315             // longer lingering?
   1316             defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
   1317             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
   1318         }
   1319         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1320 
   1321         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
   1322         // if the network is still up.
   1323         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
   1324         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1325 
   1326         // Wifi no longer satisfies our listen, which is for an unmetered network.
   1327         // But because its score is 55, it's still up (and the default network).
   1328         defaultCallback.assertNoCallback();
   1329         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1330 
   1331         // Disconnect our test networks.
   1332         mWiFiNetworkAgent.disconnect();
   1333         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1334         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1335         mCellNetworkAgent.disconnect();
   1336         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1337 
   1338         mCm.unregisterNetworkCallback(callback);
   1339         mService.waitForIdle();
   1340 
   1341         // Check that a network is only lingered or torn down if it would not satisfy a request even
   1342         // if it validated.
   1343         request = new NetworkRequest.Builder().clearCapabilities().build();
   1344         callback = new TestNetworkCallback();
   1345 
   1346         mCm.registerNetworkCallback(request, callback);
   1347 
   1348         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1349         mCellNetworkAgent.connect(false);   // Score: 10
   1350         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1351         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1352         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1353 
   1354         // Bring up wifi with a score of 20.
   1355         // Cell stays up because it would satisfy the default request if it validated.
   1356         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1357         mWiFiNetworkAgent.connect(false);   // Score: 20
   1358         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1359         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1360         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1361 
   1362         mWiFiNetworkAgent.disconnect();
   1363         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1364         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1365         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1366         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1367 
   1368         // Bring up wifi with a score of 70.
   1369         // Cell is lingered because it would not satisfy any request, even if it validated.
   1370         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1371         mWiFiNetworkAgent.adjustScore(50);
   1372         mWiFiNetworkAgent.connect(false);   // Score: 70
   1373         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1374         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1375         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1376         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1377 
   1378         // Tear down wifi.
   1379         mWiFiNetworkAgent.disconnect();
   1380         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1381         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1382         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1383         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1384 
   1385         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
   1386         // it's arguably correct to linger it, since it was the default network before it validated.
   1387         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1388         mWiFiNetworkAgent.connect(true);
   1389         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1390         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1391         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1392         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   1393 
   1394         mWiFiNetworkAgent.disconnect();
   1395         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1396         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1397         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1398         mCellNetworkAgent.disconnect();
   1399         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1400         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1401 
   1402         // If a network is lingering, and we add and remove a request from it, resume lingering.
   1403         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1404         mCellNetworkAgent.connect(true);
   1405         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1406         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1407         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1408         mWiFiNetworkAgent.connect(true);
   1409         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1410         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1411         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1412 
   1413         NetworkRequest cellRequest = new NetworkRequest.Builder()
   1414                 .addTransportType(TRANSPORT_CELLULAR).build();
   1415         NetworkCallback noopCallback = new NetworkCallback();
   1416         mCm.requestNetwork(cellRequest, noopCallback);
   1417         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
   1418         // lingering?
   1419         mCm.unregisterNetworkCallback(noopCallback);
   1420         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1421 
   1422         // Similar to the above: lingering can start even after the lingered request is removed.
   1423         // Disconnect wifi and switch to cell.
   1424         mWiFiNetworkAgent.disconnect();
   1425         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1426         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1427         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1428 
   1429         // Cell is now the default network. Pin it with a cell-specific request.
   1430         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
   1431         mCm.requestNetwork(cellRequest, noopCallback);
   1432 
   1433         // Now connect wifi, and expect it to become the default network.
   1434         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1435         mWiFiNetworkAgent.connect(true);
   1436         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1437         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1438         // The default request is lingering on cell, but nothing happens to cell, and we send no
   1439         // callbacks for it, because it's kept up by cellRequest.
   1440         callback.assertNoCallback();
   1441         // Now unregister cellRequest and expect cell to start lingering.
   1442         mCm.unregisterNetworkCallback(noopCallback);
   1443         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1444 
   1445         // Let linger run its course.
   1446         callback.assertNoCallback();
   1447         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
   1448                 TEST_LINGER_DELAY_MS /* timeoutMs */);
   1449 
   1450         // Clean up.
   1451         mWiFiNetworkAgent.disconnect();
   1452         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1453         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1454 
   1455         mCm.unregisterNetworkCallback(callback);
   1456         mCm.unregisterNetworkCallback(defaultCallback);
   1457     }
   1458 
   1459     private void tryNetworkFactoryRequests(int capability) throws Exception {
   1460         // Verify NOT_RESTRICTED is set appropriately
   1461         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
   1462                 .build().networkCapabilities;
   1463         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
   1464                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
   1465                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
   1466                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
   1467             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
   1468         } else {
   1469             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
   1470         }
   1471 
   1472         NetworkCapabilities filter = new NetworkCapabilities();
   1473         filter.addCapability(capability);
   1474         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
   1475         handlerThread.start();
   1476         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   1477                 mServiceContext, "testFactory", filter);
   1478         testFactory.setScoreFilter(40);
   1479         ConditionVariable cv = testFactory.getNetworkStartedCV();
   1480         testFactory.expectAddRequests(1);
   1481         testFactory.register();
   1482         testFactory.waitForNetworkRequests(1);
   1483         int expectedRequestCount = 1;
   1484         NetworkCallback networkCallback = null;
   1485         // For non-INTERNET capabilities we cannot rely on the default request being present, so
   1486         // add one.
   1487         if (capability != NET_CAPABILITY_INTERNET) {
   1488             assertFalse(testFactory.getMyStartRequested());
   1489             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
   1490             networkCallback = new NetworkCallback();
   1491             testFactory.expectAddRequests(1);
   1492             mCm.requestNetwork(request, networkCallback);
   1493             expectedRequestCount++;
   1494             testFactory.waitForNetworkRequests(expectedRequestCount);
   1495         }
   1496         waitFor(cv);
   1497         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   1498         assertTrue(testFactory.getMyStartRequested());
   1499 
   1500         // Now bring in a higher scored network.
   1501         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1502         // Rather than create a validated network which complicates things by registering it's
   1503         // own NetworkRequest during startup, just bump up the score to cancel out the
   1504         // unvalidated penalty.
   1505         testAgent.adjustScore(40);
   1506         cv = testFactory.getNetworkStoppedCV();
   1507 
   1508         // When testAgent connects, ConnectivityService will re-send us all current requests with
   1509         // the new score. There are expectedRequestCount such requests, and we must wait for all of
   1510         // them.
   1511         testFactory.expectAddRequests(expectedRequestCount);
   1512         testAgent.connect(false);
   1513         testAgent.addCapability(capability);
   1514         waitFor(cv);
   1515         testFactory.waitForNetworkRequests(expectedRequestCount);
   1516         assertFalse(testFactory.getMyStartRequested());
   1517 
   1518         // Bring in a bunch of requests.
   1519         testFactory.expectAddRequests(10);
   1520         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   1521         ConnectivityManager.NetworkCallback[] networkCallbacks =
   1522                 new ConnectivityManager.NetworkCallback[10];
   1523         for (int i = 0; i< networkCallbacks.length; i++) {
   1524             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
   1525             NetworkRequest.Builder builder = new NetworkRequest.Builder();
   1526             builder.addCapability(capability);
   1527             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
   1528         }
   1529         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
   1530         assertFalse(testFactory.getMyStartRequested());
   1531 
   1532         // Remove the requests.
   1533         testFactory.expectRemoveRequests(10);
   1534         for (int i = 0; i < networkCallbacks.length; i++) {
   1535             mCm.unregisterNetworkCallback(networkCallbacks[i]);
   1536         }
   1537         testFactory.waitForNetworkRequests(expectedRequestCount);
   1538         assertFalse(testFactory.getMyStartRequested());
   1539 
   1540         // Drop the higher scored network.
   1541         cv = testFactory.getNetworkStartedCV();
   1542         testAgent.disconnect();
   1543         waitFor(cv);
   1544         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
   1545         assertTrue(testFactory.getMyStartRequested());
   1546 
   1547         testFactory.unregister();
   1548         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
   1549         handlerThread.quit();
   1550     }
   1551 
   1552     @LargeTest
   1553     public void testNetworkFactoryRequests() throws Exception {
   1554         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
   1555         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
   1556         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
   1557         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
   1558         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
   1559         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
   1560         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
   1561         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
   1562         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
   1563         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
   1564         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
   1565         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
   1566         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
   1567         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
   1568         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
   1569         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
   1570     }
   1571 
   1572     @LargeTest
   1573     public void testNoMutableNetworkRequests() throws Exception {
   1574         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
   1575         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   1576         builder.addCapability(NET_CAPABILITY_VALIDATED);
   1577         try {
   1578             mCm.requestNetwork(builder.build(), new NetworkCallback());
   1579             fail();
   1580         } catch (IllegalArgumentException expected) {}
   1581         try {
   1582             mCm.requestNetwork(builder.build(), pendingIntent);
   1583             fail();
   1584         } catch (IllegalArgumentException expected) {}
   1585         builder = new NetworkRequest.Builder();
   1586         builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
   1587         try {
   1588             mCm.requestNetwork(builder.build(), new NetworkCallback());
   1589             fail();
   1590         } catch (IllegalArgumentException expected) {}
   1591         try {
   1592             mCm.requestNetwork(builder.build(), pendingIntent);
   1593             fail();
   1594         } catch (IllegalArgumentException expected) {}
   1595     }
   1596 
   1597     @LargeTest
   1598     public void testMMSonWiFi() throws Exception {
   1599         // Test bringing up cellular without MMS NetworkRequest gets reaped
   1600         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1601         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   1602         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
   1603         mCellNetworkAgent.connectWithoutInternet();
   1604         waitFor(cv);
   1605         waitFor(new Criteria() {
   1606                 public boolean get() { return mCm.getAllNetworks().length == 0; } });
   1607         verifyNoNetwork();
   1608         // Test bringing up validated WiFi.
   1609         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1610         cv = waitForConnectivityBroadcasts(1);
   1611         mWiFiNetworkAgent.connect(true);
   1612         waitFor(cv);
   1613         verifyActiveNetwork(TRANSPORT_WIFI);
   1614         // Register MMS NetworkRequest
   1615         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   1616         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
   1617         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   1618         mCm.requestNetwork(builder.build(), networkCallback);
   1619         // Test bringing up unvalidated cellular with MMS
   1620         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1621         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   1622         mCellNetworkAgent.connectWithoutInternet();
   1623         networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1624         verifyActiveNetwork(TRANSPORT_WIFI);
   1625         // Test releasing NetworkRequest disconnects cellular with MMS
   1626         cv = mCellNetworkAgent.getDisconnectedCV();
   1627         mCm.unregisterNetworkCallback(networkCallback);
   1628         waitFor(cv);
   1629         verifyActiveNetwork(TRANSPORT_WIFI);
   1630     }
   1631 
   1632     @LargeTest
   1633     public void testMMSonCell() throws Exception {
   1634         // Test bringing up cellular without MMS
   1635         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1636         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   1637         mCellNetworkAgent.connect(false);
   1638         waitFor(cv);
   1639         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1640         // Register MMS NetworkRequest
   1641         NetworkRequest.Builder builder = new NetworkRequest.Builder();
   1642         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
   1643         final TestNetworkCallback networkCallback = new TestNetworkCallback();
   1644         mCm.requestNetwork(builder.build(), networkCallback);
   1645         // Test bringing up MMS cellular network
   1646         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1647         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
   1648         mmsNetworkAgent.connectWithoutInternet();
   1649         networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
   1650         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1651         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
   1652         cv = mmsNetworkAgent.getDisconnectedCV();
   1653         mCm.unregisterNetworkCallback(networkCallback);
   1654         waitFor(cv);
   1655         verifyActiveNetwork(TRANSPORT_CELLULAR);
   1656     }
   1657 
   1658     @LargeTest
   1659     public void testCaptivePortal() {
   1660         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
   1661         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
   1662                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
   1663         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
   1664 
   1665         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
   1666         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
   1667                 .addCapability(NET_CAPABILITY_VALIDATED).build();
   1668         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
   1669 
   1670         // Bring up a network with a captive portal.
   1671         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   1672         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1673         String firstRedirectUrl = "http://example.com/firstPath";
   1674         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
   1675         captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1676         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
   1677 
   1678         // Take down network.
   1679         // Expect onLost callback.
   1680         mWiFiNetworkAgent.disconnect();
   1681         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1682 
   1683         // Bring up a network with a captive portal.
   1684         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
   1685         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1686         String secondRedirectUrl = "http://example.com/secondPath";
   1687         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
   1688         captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1689         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
   1690 
   1691         // Make captive portal disappear then revalidate.
   1692         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
   1693         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
   1694         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
   1695         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1696 
   1697         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
   1698         validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1699 
   1700         // Break network connectivity.
   1701         // Expect NET_CAPABILITY_VALIDATED onLost callback.
   1702         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
   1703         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
   1704         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1705     }
   1706 
   1707     @SmallTest
   1708     public void testInvalidNetworkSpecifier() {
   1709         boolean execptionCalled = true;
   1710 
   1711         try {
   1712             NetworkRequest.Builder builder = new NetworkRequest.Builder();
   1713             builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
   1714             execptionCalled = false;
   1715         } catch (IllegalArgumentException e) {
   1716             // do nothing - should get here
   1717         }
   1718 
   1719         assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
   1720                 execptionCalled);
   1721 
   1722         try {
   1723             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
   1724             networkCapabilities.addTransportType(TRANSPORT_WIFI)
   1725                     .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
   1726             mService.requestNetwork(networkCapabilities, null, 0, null,
   1727                     ConnectivityManager.TYPE_WIFI);
   1728             execptionCalled = false;
   1729         } catch (IllegalArgumentException e) {
   1730             // do nothing - should get here
   1731         }
   1732 
   1733         assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
   1734                 execptionCalled);
   1735     }
   1736 
   1737     @LargeTest
   1738     public void testRegisterDefaultNetworkCallback() throws Exception {
   1739         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
   1740         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
   1741         defaultNetworkCallback.assertNoCallback();
   1742 
   1743         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
   1744         // whenever Wi-Fi is up. Without this, the mobile network agent is
   1745         // reaped before any other activity can take place.
   1746         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   1747         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   1748                 .addTransportType(TRANSPORT_CELLULAR).build();
   1749         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   1750         cellNetworkCallback.assertNoCallback();
   1751 
   1752         // Bring up cell and expect CALLBACK_AVAILABLE.
   1753         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1754         mCellNetworkAgent.connect(true);
   1755         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1756         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1757 
   1758         // Bring up wifi and expect CALLBACK_AVAILABLE.
   1759         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1760         mWiFiNetworkAgent.connect(true);
   1761         cellNetworkCallback.assertNoCallback();
   1762         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1763 
   1764         // Bring down cell. Expect no default network callback, since it wasn't the default.
   1765         mCellNetworkAgent.disconnect();
   1766         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1767         defaultNetworkCallback.assertNoCallback();
   1768 
   1769         // Bring up cell. Expect no default network callback, since it won't be the default.
   1770         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1771         mCellNetworkAgent.connect(true);
   1772         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1773         defaultNetworkCallback.assertNoCallback();
   1774 
   1775         // Bring down wifi. Expect the default network callback to notified of LOST wifi
   1776         // followed by AVAILABLE cell.
   1777         mWiFiNetworkAgent.disconnect();
   1778         cellNetworkCallback.assertNoCallback();
   1779         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1780         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1781         mCellNetworkAgent.disconnect();
   1782         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1783         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1784     }
   1785 
   1786     private class TestRequestUpdateCallback extends TestNetworkCallback {
   1787         @Override
   1788         public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
   1789             setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
   1790         }
   1791 
   1792         @Override
   1793         public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
   1794             setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
   1795         }
   1796     }
   1797 
   1798     @LargeTest
   1799     public void testRequestCallbackUpdates() throws Exception {
   1800         // File a network request for mobile.
   1801         final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
   1802         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   1803                 .addTransportType(TRANSPORT_CELLULAR).build();
   1804         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   1805 
   1806         // Bring up the mobile network.
   1807         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1808         mCellNetworkAgent.connect(true);
   1809 
   1810         // We should get onAvailable().
   1811         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1812         // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
   1813         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
   1814         cellNetworkCallback.assertNoCallback();
   1815 
   1816         // Update LinkProperties.
   1817         final LinkProperties lp = new LinkProperties();
   1818         lp.setInterfaceName("foonet_data0");
   1819         mCellNetworkAgent.sendLinkProperties(lp);
   1820         // We should get onLinkPropertiesChanged().
   1821         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   1822         cellNetworkCallback.assertNoCallback();
   1823 
   1824         // Register a garden variety default network request.
   1825         final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
   1826         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
   1827         // Only onAvailable() is called; no other information is delivered.
   1828         dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1829         dfltNetworkCallback.assertNoCallback();
   1830 
   1831         // Request a NetworkCapabilities update; only the requesting callback is notified.
   1832         mCm.requestNetworkCapabilities(dfltNetworkCallback);
   1833         dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
   1834         cellNetworkCallback.assertNoCallback();
   1835         dfltNetworkCallback.assertNoCallback();
   1836 
   1837         // Request a LinkProperties update; only the requesting callback is notified.
   1838         mCm.requestLinkProperties(dfltNetworkCallback);
   1839         dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
   1840         cellNetworkCallback.assertNoCallback();
   1841         dfltNetworkCallback.assertNoCallback();
   1842 
   1843         mCm.unregisterNetworkCallback(dfltNetworkCallback);
   1844         mCm.unregisterNetworkCallback(cellNetworkCallback);
   1845     }
   1846 
   1847     private void setMobileDataAlwaysOn(boolean enable) {
   1848         ContentResolver cr = mServiceContext.getContentResolver();
   1849         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
   1850         mService.updateMobileDataAlwaysOn();
   1851         mService.waitForIdle();
   1852     }
   1853 
   1854     private boolean isForegroundNetwork(MockNetworkAgent network) {
   1855         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
   1856         assertNotNull(nc);
   1857         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
   1858     }
   1859 
   1860     @SmallTest
   1861     public void testBackgroundNetworks() throws Exception {
   1862         // Create a background request. We can't do this ourselves because ConnectivityService
   1863         // doesn't have an API for it. So just turn on mobile data always on.
   1864         setMobileDataAlwaysOn(true);
   1865         final NetworkRequest request = new NetworkRequest.Builder().build();
   1866         final NetworkRequest fgRequest = new NetworkRequest.Builder()
   1867                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
   1868         final TestNetworkCallback callback = new TestNetworkCallback();
   1869         final TestNetworkCallback fgCallback = new TestNetworkCallback();
   1870         mCm.registerNetworkCallback(request, callback);
   1871         mCm.registerNetworkCallback(fgRequest, fgCallback);
   1872 
   1873         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1874         mCellNetworkAgent.connect(true);
   1875         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1876         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1877         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   1878 
   1879         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1880         mWiFiNetworkAgent.connect(true);
   1881 
   1882         // When wifi connects, cell lingers.
   1883         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1884         fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   1885         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1886         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
   1887         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   1888         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   1889 
   1890         // When lingering is complete, cell is still there but is now in the background.
   1891         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
   1892         callback.assertNoCallback();
   1893         assertFalse(isForegroundNetwork(mCellNetworkAgent));
   1894         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   1895 
   1896         // File a cell request and check that cell comes into the foreground.
   1897         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   1898                 .addTransportType(TRANSPORT_CELLULAR).build();
   1899         final TestNetworkCallback cellCallback = new TestNetworkCallback();
   1900         mCm.requestNetwork(cellRequest, cellCallback);
   1901         cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1902         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1903         callback.assertNoCallback();  // Because the network is already up.
   1904         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   1905         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   1906 
   1907         // Release the request. The network immediately goes into the background, since it was not
   1908         // lingering.
   1909         mCm.unregisterNetworkCallback(cellCallback);
   1910         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   1911         callback.assertNoCallback();
   1912         assertFalse(isForegroundNetwork(mCellNetworkAgent));
   1913         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
   1914 
   1915         // Disconnect wifi and check that cell is foreground again.
   1916         mWiFiNetworkAgent.disconnect();
   1917         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1918         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   1919         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   1920         assertTrue(isForegroundNetwork(mCellNetworkAgent));
   1921 
   1922         mCm.unregisterNetworkCallback(callback);
   1923         mCm.unregisterNetworkCallback(fgCallback);
   1924     }
   1925 
   1926     @SmallTest
   1927     public void testRequestBenchmark() throws Exception {
   1928         // Benchmarks connecting and switching performance in the presence of a large number of
   1929         // NetworkRequests.
   1930         // 1. File NUM_REQUESTS requests.
   1931         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
   1932         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
   1933         //    and NUM_REQUESTS onAvailable callbacks to fire.
   1934         // See how long it took.
   1935         final int NUM_REQUESTS = 90;
   1936         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
   1937         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
   1938         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
   1939         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
   1940 
   1941         final int REGISTER_TIME_LIMIT_MS = 100;
   1942         long startTime = System.currentTimeMillis();
   1943         for (int i = 0; i < NUM_REQUESTS; i++) {
   1944             callbacks[i] = new NetworkCallback() {
   1945                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
   1946                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
   1947             };
   1948             mCm.registerNetworkCallback(request, callbacks[i]);
   1949         }
   1950         long timeTaken = System.currentTimeMillis() - startTime;
   1951         String msg = String.format("Register %d callbacks: %dms, acceptable %dms",
   1952                 NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS);
   1953         Log.d(TAG, msg);
   1954         assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS);
   1955 
   1956         final int CONNECT_TIME_LIMIT_MS = 30;
   1957         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   1958         // Don't request that the network validate, because otherwise connect() will block until
   1959         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
   1960         // and we won't actually measure anything.
   1961         mCellNetworkAgent.connect(false);
   1962         startTime = System.currentTimeMillis();
   1963         if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
   1964             fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
   1965                     NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
   1966                     CONNECT_TIME_LIMIT_MS));
   1967         }
   1968         timeTaken = System.currentTimeMillis() - startTime;
   1969         Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
   1970                 NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS));
   1971 
   1972         final int SWITCH_TIME_LIMIT_MS = 30;
   1973         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   1974         // Give wifi a high enough score that we'll linger cell when wifi comes up.
   1975         mWiFiNetworkAgent.adjustScore(40);
   1976         mWiFiNetworkAgent.connect(false);
   1977         startTime = System.currentTimeMillis();
   1978         if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
   1979             fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
   1980                     NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
   1981         }
   1982         timeTaken = System.currentTimeMillis() - startTime;
   1983         Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
   1984                 NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS));
   1985 
   1986         final int UNREGISTER_TIME_LIMIT_MS = 10;
   1987         startTime = System.currentTimeMillis();
   1988         for (int i = 0; i < NUM_REQUESTS; i++) {
   1989             mCm.unregisterNetworkCallback(callbacks[i]);
   1990         }
   1991         timeTaken = System.currentTimeMillis() - startTime;
   1992         msg = String.format("Unregister %d callbacks: %dms, acceptable %dms",
   1993                 NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS);
   1994         Log.d(TAG, msg);
   1995         assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS);
   1996     }
   1997 
   1998     @SmallTest
   1999     public void testMobileDataAlwaysOn() throws Exception {
   2000         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   2001         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2002                 .addTransportType(TRANSPORT_CELLULAR).build();
   2003         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
   2004 
   2005         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
   2006         handlerThread.start();
   2007         NetworkCapabilities filter = new NetworkCapabilities()
   2008                 .addTransportType(TRANSPORT_CELLULAR)
   2009                 .addCapability(NET_CAPABILITY_INTERNET);
   2010         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
   2011                 mServiceContext, "testFactory", filter);
   2012         testFactory.setScoreFilter(40);
   2013 
   2014         // Register the factory and expect it to start looking for a network.
   2015         testFactory.expectAddRequests(1);
   2016         testFactory.register();
   2017         testFactory.waitForNetworkRequests(1);
   2018         assertTrue(testFactory.getMyStartRequested());
   2019 
   2020         // Bring up wifi. The factory stops looking for a network.
   2021         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2022         testFactory.expectAddRequests(2);  // Because the default request changes score twice.
   2023         mWiFiNetworkAgent.connect(true);
   2024         testFactory.waitForNetworkRequests(1);
   2025         assertFalse(testFactory.getMyStartRequested());
   2026 
   2027         ContentResolver cr = mServiceContext.getContentResolver();
   2028 
   2029         // Turn on mobile data always on. The factory starts looking again.
   2030         testFactory.expectAddRequests(1);
   2031         setMobileDataAlwaysOn(true);
   2032         testFactory.waitForNetworkRequests(2);
   2033         assertTrue(testFactory.getMyStartRequested());
   2034 
   2035         // Bring up cell data and check that the factory stops looking.
   2036         assertEquals(1, mCm.getAllNetworks().length);
   2037         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2038         testFactory.expectAddRequests(2);  // Because the cell request changes score twice.
   2039         mCellNetworkAgent.connect(true);
   2040         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2041         testFactory.waitForNetworkRequests(2);
   2042         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
   2043 
   2044         // Check that cell data stays up.
   2045         mService.waitForIdle();
   2046         verifyActiveNetwork(TRANSPORT_WIFI);
   2047         assertEquals(2, mCm.getAllNetworks().length);
   2048 
   2049         // Turn off mobile data always on and expect the request to disappear...
   2050         testFactory.expectRemoveRequests(1);
   2051         setMobileDataAlwaysOn(false);
   2052         testFactory.waitForNetworkRequests(1);
   2053 
   2054         // ...  and cell data to be torn down.
   2055         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2056         assertEquals(1, mCm.getAllNetworks().length);
   2057 
   2058         testFactory.unregister();
   2059         mCm.unregisterNetworkCallback(cellNetworkCallback);
   2060         handlerThread.quit();
   2061     }
   2062 
   2063     @SmallTest
   2064     public void testAvoidBadWifiSetting() throws Exception {
   2065         final ContentResolver cr = mServiceContext.getContentResolver();
   2066         final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
   2067         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
   2068 
   2069         tracker.configRestrictsAvoidBadWifi = false;
   2070         String[] values = new String[] {null, "0", "1"};
   2071         for (int i = 0; i < values.length; i++) {
   2072             Settings.Global.putInt(cr, settingName, 1);
   2073             tracker.reevaluate();
   2074             mService.waitForIdle();
   2075             String msg = String.format("config=false, setting=%s", values[i]);
   2076             assertTrue(msg, mService.avoidBadWifi());
   2077             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
   2078         }
   2079 
   2080         tracker.configRestrictsAvoidBadWifi = true;
   2081 
   2082         Settings.Global.putInt(cr, settingName, 0);
   2083         tracker.reevaluate();
   2084         mService.waitForIdle();
   2085         assertFalse(mService.avoidBadWifi());
   2086         assertFalse(tracker.shouldNotifyWifiUnvalidated());
   2087 
   2088         Settings.Global.putInt(cr, settingName, 1);
   2089         tracker.reevaluate();
   2090         mService.waitForIdle();
   2091         assertTrue(mService.avoidBadWifi());
   2092         assertFalse(tracker.shouldNotifyWifiUnvalidated());
   2093 
   2094         Settings.Global.putString(cr, settingName, null);
   2095         tracker.reevaluate();
   2096         mService.waitForIdle();
   2097         assertFalse(mService.avoidBadWifi());
   2098         assertTrue(tracker.shouldNotifyWifiUnvalidated());
   2099     }
   2100 
   2101     @SmallTest
   2102     public void testAvoidBadWifi() throws Exception {
   2103         final ContentResolver cr = mServiceContext.getContentResolver();
   2104         final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
   2105 
   2106         // Pretend we're on a carrier that restricts switching away from bad wifi.
   2107         tracker.configRestrictsAvoidBadWifi = true;
   2108 
   2109         // File a request for cell to ensure it doesn't go down.
   2110         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
   2111         final NetworkRequest cellRequest = new NetworkRequest.Builder()
   2112                 .addTransportType(TRANSPORT_CELLULAR).build();
   2113         mCm.requestNetwork(cellRequest, cellNetworkCallback);
   2114 
   2115         TestNetworkCallback defaultCallback = new TestNetworkCallback();
   2116         mCm.registerDefaultNetworkCallback(defaultCallback);
   2117 
   2118         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
   2119                 .addTransportType(TRANSPORT_WIFI)
   2120                 .addCapability(NET_CAPABILITY_VALIDATED)
   2121                 .build();
   2122         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
   2123         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
   2124 
   2125         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
   2126         tracker.reevaluate();
   2127 
   2128         // Bring up validated cell.
   2129         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2130         mCellNetworkAgent.connect(true);
   2131         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2132         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2133         Network cellNetwork = mCellNetworkAgent.getNetwork();
   2134 
   2135         // Bring up validated wifi.
   2136         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2137         mWiFiNetworkAgent.connect(true);
   2138         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2139         validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2140         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
   2141 
   2142         // Fail validation on wifi.
   2143         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
   2144         mCm.reportNetworkConnectivity(wifiNetwork, false);
   2145         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2146 
   2147         // Because avoid bad wifi is off, we don't switch to cellular.
   2148         defaultCallback.assertNoCallback();
   2149         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   2150                 NET_CAPABILITY_VALIDATED));
   2151         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   2152                 NET_CAPABILITY_VALIDATED));
   2153         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   2154 
   2155         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
   2156         // that we switch back to cell.
   2157         tracker.configRestrictsAvoidBadWifi = false;
   2158         tracker.reevaluate();
   2159         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2160         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   2161 
   2162         // Switch back to a restrictive carrier.
   2163         tracker.configRestrictsAvoidBadWifi = true;
   2164         tracker.reevaluate();
   2165         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2166         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   2167 
   2168         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
   2169         mCm.setAvoidUnvalidated(wifiNetwork);
   2170         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2171         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   2172                 NET_CAPABILITY_VALIDATED));
   2173         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   2174                 NET_CAPABILITY_VALIDATED));
   2175         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   2176 
   2177         // Disconnect and reconnect wifi to clear the one-time switch above.
   2178         mWiFiNetworkAgent.disconnect();
   2179         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2180         mWiFiNetworkAgent.connect(true);
   2181         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2182         validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2183         wifiNetwork = mWiFiNetworkAgent.getNetwork();
   2184 
   2185         // Fail validation on wifi and expect the dialog to appear.
   2186         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
   2187         mCm.reportNetworkConnectivity(wifiNetwork, false);
   2188         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
   2189 
   2190         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
   2191         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
   2192         tracker.reevaluate();
   2193 
   2194         // We now switch to cell.
   2195         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2196         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
   2197                 NET_CAPABILITY_VALIDATED));
   2198         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
   2199                 NET_CAPABILITY_VALIDATED));
   2200         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   2201 
   2202         // Simulate the user turning the cellular fallback setting off and then on.
   2203         // We switch to wifi and then to cell.
   2204         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
   2205         tracker.reevaluate();
   2206         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2207         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
   2208         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
   2209         tracker.reevaluate();
   2210         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
   2211         assertEquals(mCm.getActiveNetwork(), cellNetwork);
   2212 
   2213         // If cell goes down, we switch to wifi.
   2214         mCellNetworkAgent.disconnect();
   2215         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
   2216         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
   2217         validatedWifiCallback.assertNoCallback();
   2218 
   2219         mCm.unregisterNetworkCallback(cellNetworkCallback);
   2220         mCm.unregisterNetworkCallback(validatedWifiCallback);
   2221         mCm.unregisterNetworkCallback(defaultCallback);
   2222     }
   2223 
   2224     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
   2225 
   2226         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
   2227 
   2228         private class CallbackValue {
   2229             public CallbackType callbackType;
   2230             public int error;
   2231 
   2232             public CallbackValue(CallbackType type) {
   2233                 this.callbackType = type;
   2234                 this.error = PacketKeepalive.SUCCESS;
   2235                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
   2236             }
   2237 
   2238             public CallbackValue(CallbackType type, int error) {
   2239                 this.callbackType = type;
   2240                 this.error = error;
   2241                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
   2242             }
   2243 
   2244             @Override
   2245             public boolean equals(Object o) {
   2246                 return o instanceof CallbackValue &&
   2247                         this.callbackType == ((CallbackValue) o).callbackType &&
   2248                         this.error == ((CallbackValue) o).error;
   2249             }
   2250 
   2251             @Override
   2252             public String toString() {
   2253                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
   2254             }
   2255         }
   2256 
   2257         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
   2258 
   2259         @Override
   2260         public void onStarted() {
   2261             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
   2262         }
   2263 
   2264         @Override
   2265         public void onStopped() {
   2266             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
   2267         }
   2268 
   2269         @Override
   2270         public void onError(int error) {
   2271             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
   2272         }
   2273 
   2274         private void expectCallback(CallbackValue callbackValue) {
   2275             try {
   2276                 assertEquals(
   2277                         callbackValue,
   2278                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
   2279             } catch (InterruptedException e) {
   2280                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
   2281             }
   2282         }
   2283 
   2284         public void expectStarted() {
   2285             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
   2286         }
   2287 
   2288         public void expectStopped() {
   2289             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
   2290         }
   2291 
   2292         public void expectError(int error) {
   2293             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
   2294         }
   2295     }
   2296 
   2297     private Network connectKeepaliveNetwork(LinkProperties lp) {
   2298         // Ensure the network is disconnected before we do anything.
   2299         if (mWiFiNetworkAgent != null) {
   2300             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
   2301         }
   2302 
   2303         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2304         ConditionVariable cv = waitForConnectivityBroadcasts(1);
   2305         mWiFiNetworkAgent.connect(true);
   2306         waitFor(cv);
   2307         verifyActiveNetwork(TRANSPORT_WIFI);
   2308         mWiFiNetworkAgent.sendLinkProperties(lp);
   2309         mService.waitForIdle();
   2310         return mWiFiNetworkAgent.getNetwork();
   2311     }
   2312 
   2313     public void testPacketKeepalives() throws Exception {
   2314         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
   2315         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
   2316         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
   2317         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
   2318         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
   2319 
   2320         LinkProperties lp = new LinkProperties();
   2321         lp.setInterfaceName("wlan12");
   2322         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
   2323         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
   2324         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
   2325         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
   2326 
   2327         Network notMyNet = new Network(61234);
   2328         Network myNet = connectKeepaliveNetwork(lp);
   2329 
   2330         TestKeepaliveCallback callback = new TestKeepaliveCallback();
   2331         PacketKeepalive ka;
   2332 
   2333         // Attempt to start keepalives with invalid parameters and check for errors.
   2334         ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
   2335         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
   2336 
   2337         ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
   2338         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
   2339 
   2340         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
   2341         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   2342 
   2343         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
   2344         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   2345 
   2346         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
   2347         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);  // NAT-T is IPv4-only.
   2348 
   2349         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
   2350         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
   2351 
   2352         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
   2353         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
   2354 
   2355         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2356         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
   2357 
   2358         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2359         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
   2360 
   2361         // Check that a started keepalive can be stopped.
   2362         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   2363         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2364         callback.expectStarted();
   2365         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
   2366         ka.stop();
   2367         callback.expectStopped();
   2368 
   2369         // Check that deleting the IP address stops the keepalive.
   2370         LinkProperties bogusLp = new LinkProperties(lp);
   2371         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2372         callback.expectStarted();
   2373         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
   2374         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
   2375         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
   2376         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
   2377         mWiFiNetworkAgent.sendLinkProperties(lp);
   2378 
   2379         // Check that a started keepalive is stopped correctly when the network disconnects.
   2380         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2381         callback.expectStarted();
   2382         mWiFiNetworkAgent.disconnect();
   2383         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
   2384 
   2385         // ... and that stopping it after that has no adverse effects.
   2386         assertNull(mCm.getNetworkCapabilities(myNet));
   2387         ka.stop();
   2388 
   2389         // Reconnect.
   2390         myNet = connectKeepaliveNetwork(lp);
   2391         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   2392 
   2393         // Check things work as expected when the keepalive is stopped and the network disconnects.
   2394         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2395         callback.expectStarted();
   2396         ka.stop();
   2397         mWiFiNetworkAgent.disconnect();
   2398         mService.waitForIdle();
   2399         callback.expectStopped();
   2400 
   2401         // Reconnect.
   2402         myNet = connectKeepaliveNetwork(lp);
   2403         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
   2404 
   2405         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
   2406         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   2407         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
   2408         callback.expectStarted();
   2409 
   2410         // The second one gets slot 2.
   2411         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
   2412         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
   2413         PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
   2414         callback2.expectStarted();
   2415 
   2416         // Now stop the first one and create a third. This also gets slot 1.
   2417         ka.stop();
   2418         callback.expectStopped();
   2419 
   2420         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
   2421         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
   2422         PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
   2423         callback3.expectStarted();
   2424 
   2425         ka2.stop();
   2426         callback2.expectStopped();
   2427 
   2428         ka3.stop();
   2429         callback3.expectStopped();
   2430     }
   2431 
   2432     @SmallTest
   2433     public void testGetCaptivePortalServerUrl() throws Exception {
   2434         String url = mCm.getCaptivePortalServerUrl();
   2435         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
   2436     }
   2437 
   2438     private static class TestNetworkPinner extends NetworkPinner {
   2439         public static boolean awaitPin(int timeoutMs) {
   2440             synchronized(sLock) {
   2441                 if (sNetwork == null) {
   2442                     try {
   2443                         sLock.wait(timeoutMs);
   2444                     } catch (InterruptedException e) {}
   2445                 }
   2446                 return sNetwork != null;
   2447             }
   2448         }
   2449 
   2450         public static boolean awaitUnpin(int timeoutMs) {
   2451             synchronized(sLock) {
   2452                 if (sNetwork != null) {
   2453                     try {
   2454                         sLock.wait(timeoutMs);
   2455                     } catch (InterruptedException e) {}
   2456                 }
   2457                 return sNetwork == null;
   2458             }
   2459         }
   2460     }
   2461 
   2462     private void assertPinnedToWifiWithCellDefault() {
   2463         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
   2464         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2465     }
   2466 
   2467     private void assertPinnedToWifiWithWifiDefault() {
   2468         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
   2469         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2470     }
   2471 
   2472     private void assertNotPinnedToWifi() {
   2473         assertNull(mCm.getBoundNetworkForProcess());
   2474         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
   2475     }
   2476 
   2477     @SmallTest
   2478     public void testNetworkPinner() {
   2479         NetworkRequest wifiRequest = new NetworkRequest.Builder()
   2480                 .addTransportType(TRANSPORT_WIFI)
   2481                 .build();
   2482         assertNull(mCm.getBoundNetworkForProcess());
   2483 
   2484         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   2485         assertNull(mCm.getBoundNetworkForProcess());
   2486 
   2487         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
   2488         mCellNetworkAgent.connect(true);
   2489         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2490         mWiFiNetworkAgent.connect(false);
   2491 
   2492         // When wi-fi connects, expect to be pinned.
   2493         assertTrue(TestNetworkPinner.awaitPin(100));
   2494         assertPinnedToWifiWithCellDefault();
   2495 
   2496         // Disconnect and expect the pin to drop.
   2497         mWiFiNetworkAgent.disconnect();
   2498         assertTrue(TestNetworkPinner.awaitUnpin(100));
   2499         assertNotPinnedToWifi();
   2500 
   2501         // Reconnecting does not cause the pin to come back.
   2502         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2503         mWiFiNetworkAgent.connect(false);
   2504         assertFalse(TestNetworkPinner.awaitPin(100));
   2505         assertNotPinnedToWifi();
   2506 
   2507         // Pinning while connected causes the pin to take effect immediately.
   2508         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   2509         assertTrue(TestNetworkPinner.awaitPin(100));
   2510         assertPinnedToWifiWithCellDefault();
   2511 
   2512         // Explicitly unpin and expect to use the default network again.
   2513         TestNetworkPinner.unpin();
   2514         assertNotPinnedToWifi();
   2515 
   2516         // Disconnect cell and wifi.
   2517         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
   2518         mCellNetworkAgent.disconnect();
   2519         mWiFiNetworkAgent.disconnect();
   2520         waitFor(cv);
   2521 
   2522         // Pinning takes effect even if the pinned network is the default when the pin is set...
   2523         TestNetworkPinner.pin(mServiceContext, wifiRequest);
   2524         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2525         mWiFiNetworkAgent.connect(false);
   2526         assertTrue(TestNetworkPinner.awaitPin(100));
   2527         assertPinnedToWifiWithWifiDefault();
   2528 
   2529         // ... and is maintained even when that network is no longer the default.
   2530         cv = waitForConnectivityBroadcasts(1);
   2531         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
   2532         mCellNetworkAgent.connect(true);
   2533         waitFor(cv);
   2534         assertPinnedToWifiWithCellDefault();
   2535     }
   2536 
   2537     @SmallTest
   2538     public void testNetworkRequestMaximum() {
   2539         final int MAX_REQUESTS = 100;
   2540         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
   2541         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
   2542         ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
   2543         try {
   2544             for (int i = 0; i < MAX_REQUESTS; i++) {
   2545                 NetworkCallback networkCallback = new NetworkCallback();
   2546                 mCm.requestNetwork(networkRequest, networkCallback);
   2547                 networkCallbacks.add(networkCallback);
   2548             }
   2549             fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
   2550         } catch (IllegalArgumentException expected) {}
   2551         for (NetworkCallback networkCallback : networkCallbacks) {
   2552             mCm.unregisterNetworkCallback(networkCallback);
   2553         }
   2554         networkCallbacks.clear();
   2555 
   2556         try {
   2557             for (int i = 0; i < MAX_REQUESTS; i++) {
   2558                 NetworkCallback networkCallback = new NetworkCallback();
   2559                 mCm.registerNetworkCallback(networkRequest, networkCallback);
   2560                 networkCallbacks.add(networkCallback);
   2561             }
   2562             fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
   2563         } catch (IllegalArgumentException expected) {}
   2564         for (NetworkCallback networkCallback : networkCallbacks) {
   2565             mCm.unregisterNetworkCallback(networkCallback);
   2566         }
   2567         networkCallbacks.clear();
   2568 
   2569         ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
   2570         try {
   2571             for (int i = 0; i < MAX_REQUESTS + 1; i++) {
   2572                 PendingIntent pendingIntent =
   2573                         PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
   2574                 mCm.requestNetwork(networkRequest, pendingIntent);
   2575                 pendingIntents.add(pendingIntent);
   2576             }
   2577             fail("Registering " + MAX_REQUESTS +
   2578                     " PendingIntent NetworkRequests did not throw exception");
   2579         } catch (IllegalArgumentException expected) {}
   2580         for (PendingIntent pendingIntent : pendingIntents) {
   2581             mCm.unregisterNetworkCallback(pendingIntent);
   2582         }
   2583         pendingIntents.clear();
   2584 
   2585         try {
   2586             for (int i = 0; i < MAX_REQUESTS + 1; i++) {
   2587                 PendingIntent pendingIntent =
   2588                         PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
   2589                 mCm.registerNetworkCallback(networkRequest, pendingIntent);
   2590                 pendingIntents.add(pendingIntent);
   2591             }
   2592             fail("Registering " + MAX_REQUESTS +
   2593                     " PendingIntent NetworkCallbacks did not throw exception");
   2594         } catch (IllegalArgumentException expected) {}
   2595         for (PendingIntent pendingIntent : pendingIntents) {
   2596             mCm.unregisterNetworkCallback(pendingIntent);
   2597         }
   2598         pendingIntents.clear();
   2599         mService.waitForIdle(5000);
   2600 
   2601         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
   2602         for (int i = 0; i < MAX_REQUESTS; i++) {
   2603             NetworkCallback networkCallback = new NetworkCallback();
   2604             mCm.requestNetwork(networkRequest, networkCallback);
   2605             mCm.unregisterNetworkCallback(networkCallback);
   2606         }
   2607         mService.waitForIdle();
   2608         for (int i = 0; i < MAX_REQUESTS; i++) {
   2609             NetworkCallback networkCallback = new NetworkCallback();
   2610             mCm.registerNetworkCallback(networkRequest, networkCallback);
   2611             mCm.unregisterNetworkCallback(networkCallback);
   2612         }
   2613         mService.waitForIdle();
   2614         for (int i = 0; i < MAX_REQUESTS; i++) {
   2615             PendingIntent pendingIntent =
   2616                     PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
   2617             mCm.requestNetwork(networkRequest, pendingIntent);
   2618             mCm.unregisterNetworkCallback(pendingIntent);
   2619         }
   2620         mService.waitForIdle();
   2621         for (int i = 0; i < MAX_REQUESTS; i++) {
   2622             PendingIntent pendingIntent =
   2623                     PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
   2624             mCm.registerNetworkCallback(networkRequest, pendingIntent);
   2625             mCm.unregisterNetworkCallback(pendingIntent);
   2626         }
   2627     }
   2628 }
   2629