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