OSDN Git Service

resolve merge conflicts of 56a2b529373b to nyc-dev
[android-x86/frameworks-base.git] / services / tests / servicestests / src / com / android / server / ConnectivityServiceTest.java
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_MOBILE;
21 import static android.net.ConnectivityManager.TYPE_WIFI;
22 import static android.net.ConnectivityManager.getNetworkTypeName;
23 import static android.net.NetworkCapabilities.*;
24
25 import static org.mockito.Mockito.mock;
26
27 import android.app.PendingIntent;
28 import android.content.BroadcastReceiver;
29 import android.content.Context;
30 import android.content.ContextWrapper;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.net.ConnectivityManager;
34 import android.net.ConnectivityManager.NetworkCallback;
35 import android.net.ConnectivityManager.PacketKeepalive;
36 import android.net.ConnectivityManager.PacketKeepaliveCallback;
37 import android.net.INetworkPolicyManager;
38 import android.net.INetworkStatsService;
39 import android.net.IpPrefix;
40 import android.net.LinkAddress;
41 import android.net.LinkProperties;
42 import android.net.Network;
43 import android.net.NetworkAgent;
44 import android.net.NetworkCapabilities;
45 import android.net.NetworkConfig;
46 import android.net.NetworkFactory;
47 import android.net.NetworkInfo;
48 import android.net.NetworkInfo.DetailedState;
49 import android.net.NetworkMisc;
50 import android.net.NetworkRequest;
51 import android.net.RouteInfo;
52 import android.os.ConditionVariable;
53 import android.os.Handler;
54 import android.os.HandlerThread;
55 import android.os.IBinder;
56 import android.os.INetworkManagementService;
57 import android.os.Looper;
58 import android.os.Message;
59 import android.os.MessageQueue;
60 import android.os.Messenger;
61 import android.os.MessageQueue.IdleHandler;
62 import android.os.Process;
63 import android.os.SystemClock;
64 import android.test.AndroidTestCase;
65 import android.test.suitebuilder.annotation.LargeTest;
66 import android.test.suitebuilder.annotation.SmallTest;
67 import android.util.Log;
68 import android.util.LogPrinter;
69
70 import com.android.internal.util.WakeupMessage;
71 import com.android.server.connectivity.NetworkAgentInfo;
72 import com.android.server.connectivity.NetworkMonitor;
73 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
74 import com.android.server.net.NetworkPinner;
75
76 import java.net.InetAddress;
77 import java.util.ArrayList;
78 import java.util.concurrent.CountDownLatch;
79 import java.util.concurrent.LinkedBlockingQueue;
80 import java.util.concurrent.TimeUnit;
81 import java.util.concurrent.atomic.AtomicBoolean;
82
83 /**
84  * Tests for {@link ConnectivityService}.
85  *
86  * Build, install and run with:
87  *  runtest frameworks-services -c com.android.server.ConnectivityServiceTest
88  */
89 public class ConnectivityServiceTest extends AndroidTestCase {
90     private static final String TAG = "ConnectivityServiceTest";
91
92     private static final int TIMEOUT_MS = 500;
93
94     private BroadcastInterceptingContext mServiceContext;
95     private WrappedConnectivityService mService;
96     private WrappedConnectivityManager mCm;
97     private MockNetworkAgent mWiFiNetworkAgent;
98     private MockNetworkAgent mCellNetworkAgent;
99
100     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
101     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
102     // reflect the state of our test ConnectivityService.
103     private class WrappedConnectivityManager extends ConnectivityManager {
104         private Network mFakeBoundNetwork;
105
106         public synchronized boolean bindProcessToNetwork(Network network) {
107             mFakeBoundNetwork = network;
108             return true;
109         }
110
111         public synchronized Network getBoundNetworkForProcess() {
112             return mFakeBoundNetwork;
113         }
114
115         public WrappedConnectivityManager(Context context, ConnectivityService service) {
116             super(context, service);
117         }
118     }
119
120     private class MockContext extends BroadcastInterceptingContext {
121         MockContext(Context base) {
122             super(base);
123         }
124
125         @Override
126         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
127             // PendingIntents sent by the AlarmManager are not intercepted by
128             // BroadcastInterceptingContext so we must really register the receiver.
129             // This shouldn't effect the real NetworkMonitors as the action contains a random token.
130             if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
131                 return getBaseContext().registerReceiver(receiver, filter);
132             } else {
133                 return super.registerReceiver(receiver, filter);
134             }
135         }
136
137         @Override
138         public Object getSystemService (String name) {
139             if (name == Context.CONNECTIVITY_SERVICE) return mCm;
140             return super.getSystemService(name);
141         }
142     }
143
144     /**
145      * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
146      * will return immediately if the handler is already idle.
147      */
148     private class IdleableHandlerThread extends HandlerThread {
149         private IdleHandler mIdleHandler;
150
151         public IdleableHandlerThread(String name) {
152             super(name);
153         }
154
155         public void waitForIdle(int timeoutMs) {
156             final ConditionVariable cv = new ConditionVariable();
157             final MessageQueue queue = getLooper().getQueue();
158
159             synchronized (queue) {
160                 if (queue.isIdle()) {
161                     return;
162                 }
163
164                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
165                 mIdleHandler = new IdleHandler() {
166                     public boolean queueIdle() {
167                         synchronized (queue) {
168                             cv.open();
169                             mIdleHandler = null;
170                             return false;  // Remove the handler.
171                         }
172                     }
173                 };
174                 queue.addIdleHandler(mIdleHandler);
175             }
176
177             if (!cv.block(timeoutMs)) {
178                 fail("HandlerThread " + getName() +
179                         " did not become idle after " + timeoutMs + " ms");
180                 queue.removeIdleHandler(mIdleHandler);
181             }
182         }
183     }
184
185     // Tests that IdleableHandlerThread works as expected.
186     public void testIdleableHandlerThread() {
187         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
188
189         // Tests that waitForIdle returns immediately if the service is already idle.
190         for (int i = 0; i < attempts; i++) {
191             mService.waitForIdle();
192         }
193
194         // Bring up a network that we can use to send messages to ConnectivityService.
195         ConditionVariable cv = waitForConnectivityBroadcasts(1);
196         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
197         mWiFiNetworkAgent.connect(false);
198         waitFor(cv);
199         Network n = mWiFiNetworkAgent.getNetwork();
200         assertNotNull(n);
201
202         // Tests that calling waitForIdle waits for messages to be processed.
203         for (int i = 0; i < attempts; i++) {
204             mWiFiNetworkAgent.setSignalStrength(i);
205             mService.waitForIdle();
206             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
207         }
208
209         // Ensure that not calling waitForIdle causes a race condition.
210         for (int i = 0; i < attempts; i++) {
211             mWiFiNetworkAgent.setSignalStrength(i);
212             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
213                 // We hit a race condition, as expected. Pass the test.
214                 return;
215             }
216         }
217
218         // No race? There is a bug in this test.
219         fail("expected race condition at least once in " + attempts + " attempts");
220     }
221
222     private class MockNetworkAgent {
223         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
224         private final NetworkInfo mNetworkInfo;
225         private final NetworkCapabilities mNetworkCapabilities;
226         private final IdleableHandlerThread mHandlerThread;
227         private final ConditionVariable mDisconnected = new ConditionVariable();
228         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
229         private int mScore;
230         private NetworkAgent mNetworkAgent;
231         private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
232         private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
233         private Integer mExpectedKeepaliveSlot = null;
234         // Contains the redirectUrl from networkStatus(). Before reading, wait for
235         // mNetworkStatusReceived.
236         private String mRedirectUrl;
237
238         MockNetworkAgent(int transport) {
239             final int type = transportToLegacyType(transport);
240             final String typeName = ConnectivityManager.getNetworkTypeName(type);
241             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
242             mNetworkCapabilities = new NetworkCapabilities();
243             mNetworkCapabilities.addTransportType(transport);
244             switch (transport) {
245                 case TRANSPORT_WIFI:
246                     mScore = 60;
247                     break;
248                 case TRANSPORT_CELLULAR:
249                     mScore = 50;
250                     break;
251                 default:
252                     throw new UnsupportedOperationException("unimplemented network type");
253             }
254             mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
255             mHandlerThread.start();
256             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
257                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
258                     new LinkProperties(), mScore, new NetworkMisc()) {
259                 @Override
260                 public void unwanted() { mDisconnected.open(); }
261
262                 @Override
263                 public void startPacketKeepalive(Message msg) {
264                     int slot = msg.arg1;
265                     if (mExpectedKeepaliveSlot != null) {
266                         assertEquals((int) mExpectedKeepaliveSlot, slot);
267                     }
268                     onPacketKeepaliveEvent(slot, mStartKeepaliveError);
269                 }
270
271                 @Override
272                 public void stopPacketKeepalive(Message msg) {
273                     onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
274                 }
275
276                 @Override
277                 public void networkStatus(int status, String redirectUrl) {
278                     mRedirectUrl = redirectUrl;
279                     mNetworkStatusReceived.open();
280                 }
281             };
282             // Waits for the NetworkAgent to be registered, which includes the creation of the
283             // NetworkMonitor.
284             mService.waitForIdle();
285             mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
286         }
287
288         public void waitForIdle(int timeoutMs) {
289             mHandlerThread.waitForIdle(timeoutMs);
290         }
291
292         public void waitForIdle() {
293             waitForIdle(TIMEOUT_MS);
294         }
295
296         public void adjustScore(int change) {
297             mScore += change;
298             mNetworkAgent.sendNetworkScore(mScore);
299         }
300
301         public void addCapability(int capability) {
302             mNetworkCapabilities.addCapability(capability);
303             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
304         }
305
306         public void setSignalStrength(int signalStrength) {
307             mNetworkCapabilities.setSignalStrength(signalStrength);
308             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
309         }
310
311         public void connectWithoutInternet() {
312             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
313             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
314         }
315
316         /**
317          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
318          * @param validated Indicate if network should pretend to be validated.
319          */
320         public void connect(boolean validated) {
321             assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE);
322             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
323
324             NetworkCallback callback = null;
325             final ConditionVariable validatedCv = new ConditionVariable();
326             if (validated) {
327                 mWrappedNetworkMonitor.gen204ProbeResult = 204;
328                 NetworkRequest request = new NetworkRequest.Builder()
329                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
330                         .build();
331                 callback = new NetworkCallback() {
332                     public void onCapabilitiesChanged(Network network,
333                             NetworkCapabilities networkCapabilities) {
334                         if (network.equals(getNetwork()) &&
335                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
336                             validatedCv.open();
337                         }
338                     }
339                 };
340                 mCm.registerNetworkCallback(request, callback);
341             }
342             addCapability(NET_CAPABILITY_INTERNET);
343
344             connectWithoutInternet();
345
346             if (validated) {
347                 // Wait for network to validate.
348                 waitFor(validatedCv);
349                 mWrappedNetworkMonitor.gen204ProbeResult = 500;
350             }
351
352             if (callback != null) mCm.unregisterNetworkCallback(callback);
353         }
354
355         public void connectWithCaptivePortal(String redirectUrl) {
356             mWrappedNetworkMonitor.gen204ProbeResult = 200;
357             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
358             connect(false);
359             waitFor(new Criteria() { public boolean get() {
360                 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
361                 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
362             mWrappedNetworkMonitor.gen204ProbeResult = 500;
363             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null;
364         }
365
366         public void disconnect() {
367             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
368             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
369         }
370
371         public Network getNetwork() {
372             return new Network(mNetworkAgent.netId);
373         }
374
375         public ConditionVariable getDisconnectedCV() {
376             return mDisconnected;
377         }
378
379         public WrappedNetworkMonitor getWrappedNetworkMonitor() {
380             return mWrappedNetworkMonitor;
381         }
382
383         public void sendLinkProperties(LinkProperties lp) {
384             mNetworkAgent.sendLinkProperties(lp);
385         }
386
387         public void setStartKeepaliveError(int error) {
388             mStartKeepaliveError = error;
389         }
390
391         public void setStopKeepaliveError(int error) {
392             mStopKeepaliveError = error;
393         }
394
395         public void setExpectedKeepaliveSlot(Integer slot) {
396             mExpectedKeepaliveSlot = slot;
397         }
398
399         public String waitForRedirectUrl() {
400             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
401             return mRedirectUrl;
402         }
403     }
404
405     /**
406      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
407      * operations have been processed. Before ConnectivityService can add or remove any requests,
408      * the factory must be told to expect those operations by calling expectAddRequests or
409      * expectRemoveRequests.
410      */
411     private static class MockNetworkFactory extends NetworkFactory {
412         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
413         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
414         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
415
416         // Used to expect that requests be removed or added on a separate thread, without sleeping.
417         // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
418         // cause some other thread to add or remove requests, then call waitForRequests(). We can
419         // either expect requests to be added or removed, but not both, because CountDownLatch can
420         // only count in one direction.
421         private CountDownLatch mExpectations;
422
423         // Whether we are currently expecting requests to be added or removed. Valid only if
424         // mExpectations is non-null.
425         private boolean mExpectingAdditions;
426
427         public MockNetworkFactory(Looper looper, Context context, String logTag,
428                 NetworkCapabilities filter) {
429             super(looper, context, logTag, filter);
430         }
431
432         public int getMyRequestCount() {
433             return getRequestCount();
434         }
435
436         protected void startNetwork() {
437             mNetworkStarted.set(true);
438             mNetworkStartedCV.open();
439         }
440
441         protected void stopNetwork() {
442             mNetworkStarted.set(false);
443             mNetworkStoppedCV.open();
444         }
445
446         public boolean getMyStartRequested() {
447             return mNetworkStarted.get();
448         }
449
450         public ConditionVariable getNetworkStartedCV() {
451             mNetworkStartedCV.close();
452             return mNetworkStartedCV;
453         }
454
455         public ConditionVariable getNetworkStoppedCV() {
456             mNetworkStoppedCV.close();
457             return mNetworkStoppedCV;
458         }
459
460         @Override
461         protected void handleAddRequest(NetworkRequest request, int score) {
462             // If we're expecting anything, we must be expecting additions.
463             if (mExpectations != null && !mExpectingAdditions) {
464                 fail("Can't add requests while expecting requests to be removed");
465             }
466
467             // Add the request.
468             super.handleAddRequest(request, score);
469
470             // Reduce the number of request additions we're waiting for.
471             if (mExpectingAdditions) {
472                 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
473                 mExpectations.countDown();
474             }
475         }
476
477         @Override
478         protected void handleRemoveRequest(NetworkRequest request) {
479             // If we're expecting anything, we must be expecting removals.
480             if (mExpectations != null && mExpectingAdditions) {
481                 fail("Can't remove requests while expecting requests to be added");
482             }
483
484             // Remove the request.
485             super.handleRemoveRequest(request);
486
487             // Reduce the number of request removals we're waiting for.
488             if (!mExpectingAdditions) {
489                 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
490                 mExpectations.countDown();
491             }
492         }
493
494         private void assertNoExpectations() {
495             if (mExpectations != null) {
496                 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
497             }
498         }
499
500         // Expects that count requests will be added.
501         public void expectAddRequests(final int count) {
502             assertNoExpectations();
503             mExpectingAdditions = true;
504             mExpectations = new CountDownLatch(count);
505         }
506
507         // Expects that count requests will be removed.
508         public void expectRemoveRequests(final int count) {
509             assertNoExpectations();
510             mExpectingAdditions = false;
511             mExpectations = new CountDownLatch(count);
512         }
513
514         // Waits for the expected request additions or removals to happen within a timeout.
515         public void waitForRequests() throws InterruptedException {
516             assertNotNull("Nothing to wait for", mExpectations);
517             mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
518             final long count = mExpectations.getCount();
519             final String msg = count + " requests still not " +
520                     (mExpectingAdditions ? "added" : "removed") +
521                     " after " + TIMEOUT_MS + " ms";
522             assertEquals(msg, 0, count);
523             mExpectations = null;
524         }
525
526         public void waitForNetworkRequests(final int count) throws InterruptedException {
527             waitForRequests();
528             assertEquals(count, getMyRequestCount());
529         }
530     }
531
532     private class FakeWakeupMessage extends WakeupMessage {
533         private static final int UNREASONABLY_LONG_WAIT = 1000;
534
535         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
536             super(context, handler, cmdName, cmd);
537         }
538
539         @Override
540         public void schedule(long when) {
541             long delayMs = when - SystemClock.elapsedRealtime();
542             if (delayMs < 0) delayMs = 0;
543             if (delayMs > UNREASONABLY_LONG_WAIT) {
544                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
545                         "ms into the future: " + delayMs);
546             }
547             mHandler.sendEmptyMessageDelayed(mCmd, delayMs);
548         }
549
550         @Override
551         public void cancel() {
552             mHandler.removeMessages(mCmd);
553         }
554
555         @Override
556         public void onAlarm() {
557             throw new AssertionError("Should never happen. Update this fake.");
558         }
559     }
560
561     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
562     private class WrappedNetworkMonitor extends NetworkMonitor {
563         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
564         public int gen204ProbeResult = 500;
565         public String gen204ProbeRedirectUrl = null;
566
567         public WrappedNetworkMonitor(Context context, Handler handler,
568             NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
569             super(context, handler, networkAgentInfo, defaultRequest);
570         }
571
572         @Override
573         protected CaptivePortalProbeResult isCaptivePortal() {
574             return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl);
575         }
576
577         @Override
578         protected WakeupMessage makeWakeupMessage(
579                 Context context, Handler handler, String cmdName, int cmd) {
580             return new FakeWakeupMessage(context, handler, cmdName, cmd);
581         }
582     }
583
584     private class WrappedConnectivityService extends ConnectivityService {
585         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
586
587         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
588                 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
589             super(context, netManager, statsService, policyManager);
590         }
591
592         @Override
593         protected HandlerThread createHandlerThread() {
594             return new IdleableHandlerThread("WrappedConnectivityService");
595         }
596
597         @Override
598         protected int getDefaultTcpRwnd() {
599             // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
600             return 0;
601         }
602
603         @Override
604         protected int reserveNetId() {
605             while (true) {
606                 final int netId = super.reserveNetId();
607
608                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
609                 // can have odd side-effects, like network validations succeeding.
610                 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
611                 boolean overlaps = false;
612                 for (Network network : networks) {
613                     if (netId == network.netId) {
614                         overlaps = true;
615                         break;
616                     }
617                 }
618                 if (overlaps) continue;
619
620                 return netId;
621             }
622         }
623
624         @Override
625         public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
626                 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
627             final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai,
628                     defaultRequest);
629             mLastCreatedNetworkMonitor = monitor;
630             return monitor;
631         }
632
633         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
634             return mLastCreatedNetworkMonitor;
635         }
636
637         public void waitForIdle(int timeoutMs) {
638             ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
639         }
640
641         public void waitForIdle() {
642             waitForIdle(TIMEOUT_MS);
643         }
644
645     }
646
647     private interface Criteria {
648         public boolean get();
649     }
650
651     /**
652      * Wait up to 500ms for {@code criteria.get()} to become true, polling.
653      * Fails if 500ms goes by before {@code criteria.get()} to become true.
654      */
655     static private void waitFor(Criteria criteria) {
656         int delays = 0;
657         while (!criteria.get()) {
658             try {
659                 Thread.sleep(50);
660             } catch (InterruptedException e) {
661             }
662             if (++delays == 10) fail();
663         }
664     }
665
666     /**
667      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
668      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
669      */
670     static private void waitFor(ConditionVariable conditionVariable) {
671         assertTrue(conditionVariable.block(TIMEOUT_MS));
672     }
673
674     @Override
675     public void setUp() throws Exception {
676         super.setUp();
677
678         NetworkMonitor.SetDefaultLingerTime(120);
679
680         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
681         // http://b/25897652 .
682         if (Looper.myLooper() == null) {
683             Looper.prepare();
684         }
685
686         mServiceContext = new MockContext(getContext());
687         mService = new WrappedConnectivityService(mServiceContext,
688                 mock(INetworkManagementService.class),
689                 mock(INetworkStatsService.class),
690                 mock(INetworkPolicyManager.class));
691
692         mService.systemReady();
693         mCm = new WrappedConnectivityManager(getContext(), mService);
694         mCm.bindProcessToNetwork(null);
695     }
696
697     private int transportToLegacyType(int transport) {
698         switch (transport) {
699             case TRANSPORT_WIFI:
700                 return TYPE_WIFI;
701             case TRANSPORT_CELLULAR:
702                 return TYPE_MOBILE;
703             default:
704                 throw new IllegalStateException("Unknown transport" + transport);
705         }
706     }
707
708     private void verifyActiveNetwork(int transport) {
709         // Test getActiveNetworkInfo()
710         assertNotNull(mCm.getActiveNetworkInfo());
711         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
712         // Test getActiveNetwork()
713         assertNotNull(mCm.getActiveNetwork());
714         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
715         switch (transport) {
716             case TRANSPORT_WIFI:
717                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
718                 break;
719             case TRANSPORT_CELLULAR:
720                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
721                 break;
722             default:
723                 throw new IllegalStateException("Unknown transport" + transport);
724         }
725         // Test getNetworkInfo(Network)
726         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
727         assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
728         // Test getNetworkCapabilities(Network)
729         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
730         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
731     }
732
733     private void verifyNoNetwork() {
734         // Test getActiveNetworkInfo()
735         assertNull(mCm.getActiveNetworkInfo());
736         // Test getActiveNetwork()
737         assertNull(mCm.getActiveNetwork());
738         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
739         // Test getAllNetworks()
740         assertEquals(0, mCm.getAllNetworks().length);
741     }
742
743     /**
744      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
745      * broadcasts are received.
746      */
747     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
748         final ConditionVariable cv = new ConditionVariable();
749         mServiceContext.registerReceiver(new BroadcastReceiver() {
750                     private int remaining = count;
751                     public void onReceive(Context context, Intent intent) {
752                         if (--remaining == 0) {
753                             cv.open();
754                             mServiceContext.unregisterReceiver(this);
755                         }
756                     }
757                 }, new IntentFilter(CONNECTIVITY_ACTION));
758         return cv;
759     }
760
761     @LargeTest
762     public void testLingering() throws Exception {
763         verifyNoNetwork();
764         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
765         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
766         assertNull(mCm.getActiveNetworkInfo());
767         assertNull(mCm.getActiveNetwork());
768         // Test bringing up validated cellular.
769         ConditionVariable cv = waitForConnectivityBroadcasts(1);
770         mCellNetworkAgent.connect(true);
771         waitFor(cv);
772         verifyActiveNetwork(TRANSPORT_CELLULAR);
773         assertEquals(2, mCm.getAllNetworks().length);
774         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
775                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
776         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
777                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
778         // Test bringing up validated WiFi.
779         cv = waitForConnectivityBroadcasts(2);
780         mWiFiNetworkAgent.connect(true);
781         waitFor(cv);
782         verifyActiveNetwork(TRANSPORT_WIFI);
783         assertEquals(2, mCm.getAllNetworks().length);
784         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
785                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
786         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
787                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
788         // Test cellular linger timeout.
789         waitFor(new Criteria() {
790                 public boolean get() { return mCm.getAllNetworks().length == 1; } });
791         verifyActiveNetwork(TRANSPORT_WIFI);
792         assertEquals(1, mCm.getAllNetworks().length);
793         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
794         // Test WiFi disconnect.
795         cv = waitForConnectivityBroadcasts(1);
796         mWiFiNetworkAgent.disconnect();
797         waitFor(cv);
798         verifyNoNetwork();
799     }
800
801     @LargeTest
802     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
803         // Test bringing up unvalidated WiFi
804         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
805         ConditionVariable cv = waitForConnectivityBroadcasts(1);
806         mWiFiNetworkAgent.connect(false);
807         waitFor(cv);
808         verifyActiveNetwork(TRANSPORT_WIFI);
809         // Test bringing up unvalidated cellular
810         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
811         mCellNetworkAgent.connect(false);
812         mService.waitForIdle();
813         verifyActiveNetwork(TRANSPORT_WIFI);
814         // Test cellular disconnect.
815         mCellNetworkAgent.disconnect();
816         mService.waitForIdle();
817         verifyActiveNetwork(TRANSPORT_WIFI);
818         // Test bringing up validated cellular
819         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
820         cv = waitForConnectivityBroadcasts(2);
821         mCellNetworkAgent.connect(true);
822         waitFor(cv);
823         verifyActiveNetwork(TRANSPORT_CELLULAR);
824         // Test cellular disconnect.
825         cv = waitForConnectivityBroadcasts(2);
826         mCellNetworkAgent.disconnect();
827         waitFor(cv);
828         verifyActiveNetwork(TRANSPORT_WIFI);
829         // Test WiFi disconnect.
830         cv = waitForConnectivityBroadcasts(1);
831         mWiFiNetworkAgent.disconnect();
832         waitFor(cv);
833         verifyNoNetwork();
834     }
835
836     @LargeTest
837     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
838         // Test bringing up unvalidated cellular.
839         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
840         ConditionVariable cv = waitForConnectivityBroadcasts(1);
841         mCellNetworkAgent.connect(false);
842         waitFor(cv);
843         verifyActiveNetwork(TRANSPORT_CELLULAR);
844         // Test bringing up unvalidated WiFi.
845         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
846         cv = waitForConnectivityBroadcasts(2);
847         mWiFiNetworkAgent.connect(false);
848         waitFor(cv);
849         verifyActiveNetwork(TRANSPORT_WIFI);
850         // Test WiFi disconnect.
851         cv = waitForConnectivityBroadcasts(2);
852         mWiFiNetworkAgent.disconnect();
853         waitFor(cv);
854         verifyActiveNetwork(TRANSPORT_CELLULAR);
855         // Test cellular disconnect.
856         cv = waitForConnectivityBroadcasts(1);
857         mCellNetworkAgent.disconnect();
858         waitFor(cv);
859         verifyNoNetwork();
860     }
861
862     @LargeTest
863     public void testUnlingeringDoesNotValidate() throws Exception {
864         // Test bringing up unvalidated WiFi.
865         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
866         ConditionVariable cv = waitForConnectivityBroadcasts(1);
867         mWiFiNetworkAgent.connect(false);
868         waitFor(cv);
869         verifyActiveNetwork(TRANSPORT_WIFI);
870         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
871                 NET_CAPABILITY_VALIDATED));
872         // Test bringing up validated cellular.
873         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
874         cv = waitForConnectivityBroadcasts(2);
875         mCellNetworkAgent.connect(true);
876         waitFor(cv);
877         verifyActiveNetwork(TRANSPORT_CELLULAR);
878         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
879                 NET_CAPABILITY_VALIDATED));
880         // Test cellular disconnect.
881         cv = waitForConnectivityBroadcasts(2);
882         mCellNetworkAgent.disconnect();
883         waitFor(cv);
884         verifyActiveNetwork(TRANSPORT_WIFI);
885         // Unlingering a network should not cause it to be marked as validated.
886         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
887                 NET_CAPABILITY_VALIDATED));
888     }
889
890     @LargeTest
891     public void testCellularOutscoresWeakWifi() throws Exception {
892         // Test bringing up validated cellular.
893         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
894         ConditionVariable cv = waitForConnectivityBroadcasts(1);
895         mCellNetworkAgent.connect(true);
896         waitFor(cv);
897         verifyActiveNetwork(TRANSPORT_CELLULAR);
898         // Test bringing up validated WiFi.
899         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
900         cv = waitForConnectivityBroadcasts(2);
901         mWiFiNetworkAgent.connect(true);
902         waitFor(cv);
903         verifyActiveNetwork(TRANSPORT_WIFI);
904         // Test WiFi getting really weak.
905         cv = waitForConnectivityBroadcasts(2);
906         mWiFiNetworkAgent.adjustScore(-11);
907         waitFor(cv);
908         verifyActiveNetwork(TRANSPORT_CELLULAR);
909         // Test WiFi restoring signal strength.
910         cv = waitForConnectivityBroadcasts(2);
911         mWiFiNetworkAgent.adjustScore(11);
912         waitFor(cv);
913         verifyActiveNetwork(TRANSPORT_WIFI);
914         mCellNetworkAgent.disconnect();
915         mWiFiNetworkAgent.disconnect();
916     }
917
918     @LargeTest
919     public void testReapingNetwork() throws Exception {
920         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
921         // Expect it to be torn down immediately because it satisfies no requests.
922         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
923         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
924         mWiFiNetworkAgent.connectWithoutInternet();
925         waitFor(cv);
926         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
927         // Expect it to be torn down immediately because it satisfies no requests.
928         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
929         cv = mCellNetworkAgent.getDisconnectedCV();
930         mCellNetworkAgent.connectWithoutInternet();
931         waitFor(cv);
932         // Test bringing up validated WiFi.
933         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
934         cv = waitForConnectivityBroadcasts(1);
935         mWiFiNetworkAgent.connect(true);
936         waitFor(cv);
937         verifyActiveNetwork(TRANSPORT_WIFI);
938         // Test bringing up unvalidated cellular.
939         // Expect it to be torn down because it could never be the highest scoring network
940         // satisfying the default request even if it validated.
941         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
942         cv = mCellNetworkAgent.getDisconnectedCV();
943         mCellNetworkAgent.connect(false);
944         waitFor(cv);
945         verifyActiveNetwork(TRANSPORT_WIFI);
946         cv = mWiFiNetworkAgent.getDisconnectedCV();
947         mWiFiNetworkAgent.disconnect();
948         waitFor(cv);
949     }
950
951     @LargeTest
952     public void testCellularFallback() throws Exception {
953         // Test bringing up validated cellular.
954         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
955         ConditionVariable cv = waitForConnectivityBroadcasts(1);
956         mCellNetworkAgent.connect(true);
957         waitFor(cv);
958         verifyActiveNetwork(TRANSPORT_CELLULAR);
959         // Test bringing up validated WiFi.
960         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
961         cv = waitForConnectivityBroadcasts(2);
962         mWiFiNetworkAgent.connect(true);
963         waitFor(cv);
964         verifyActiveNetwork(TRANSPORT_WIFI);
965         // Reevaluate WiFi (it'll instantly fail DNS).
966         cv = waitForConnectivityBroadcasts(2);
967         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
968                 NET_CAPABILITY_VALIDATED));
969         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
970         // Should quickly fall back to Cellular.
971         waitFor(cv);
972         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
973                 NET_CAPABILITY_VALIDATED));
974         verifyActiveNetwork(TRANSPORT_CELLULAR);
975         // Reevaluate cellular (it'll instantly fail DNS).
976         cv = waitForConnectivityBroadcasts(2);
977         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
978                 NET_CAPABILITY_VALIDATED));
979         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
980         // Should quickly fall back to WiFi.
981         waitFor(cv);
982         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
983                 NET_CAPABILITY_VALIDATED));
984         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
985                 NET_CAPABILITY_VALIDATED));
986         verifyActiveNetwork(TRANSPORT_WIFI);
987         mCellNetworkAgent.disconnect();
988         mWiFiNetworkAgent.disconnect();
989     }
990
991     @LargeTest
992     public void testWiFiFallback() throws Exception {
993         // Test bringing up unvalidated WiFi.
994         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
995         ConditionVariable cv = waitForConnectivityBroadcasts(1);
996         mWiFiNetworkAgent.connect(false);
997         waitFor(cv);
998         verifyActiveNetwork(TRANSPORT_WIFI);
999         // Test bringing up validated cellular.
1000         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1001         cv = waitForConnectivityBroadcasts(2);
1002         mCellNetworkAgent.connect(true);
1003         waitFor(cv);
1004         verifyActiveNetwork(TRANSPORT_CELLULAR);
1005         // Reevaluate cellular (it'll instantly fail DNS).
1006         cv = waitForConnectivityBroadcasts(2);
1007         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1008                 NET_CAPABILITY_VALIDATED));
1009         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1010         // Should quickly fall back to WiFi.
1011         waitFor(cv);
1012         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1013                 NET_CAPABILITY_VALIDATED));
1014         verifyActiveNetwork(TRANSPORT_WIFI);
1015         mCellNetworkAgent.disconnect();
1016         mWiFiNetworkAgent.disconnect();
1017     }
1018
1019     enum CallbackState {
1020         NONE,
1021         AVAILABLE,
1022         LOSING,
1023         LOST
1024     }
1025
1026     /**
1027      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1028      * this class receives, by calling expectCallback() exactly once each time a callback is
1029      * received. assertNoCallback may be called at any time.
1030      */
1031     private class TestNetworkCallback extends NetworkCallback {
1032         private final ConditionVariable mConditionVariable = new ConditionVariable();
1033         private CallbackState mLastCallback = CallbackState.NONE;
1034         private Network mLastNetwork;
1035
1036         public void onAvailable(Network network) {
1037             assertEquals(CallbackState.NONE, mLastCallback);
1038             mLastCallback = CallbackState.AVAILABLE;
1039             mLastNetwork = network;
1040             mConditionVariable.open();
1041         }
1042
1043         public void onLosing(Network network, int maxMsToLive) {
1044             assertEquals(CallbackState.NONE, mLastCallback);
1045             mLastCallback = CallbackState.LOSING;
1046             mLastNetwork = network;
1047             mConditionVariable.open();
1048         }
1049
1050         public void onLost(Network network) {
1051             assertEquals(CallbackState.NONE, mLastCallback);
1052             mLastCallback = CallbackState.LOST;
1053             mLastNetwork = network;
1054             mConditionVariable.open();
1055         }
1056
1057         void expectCallback(CallbackState state) {
1058             expectCallback(state, null);
1059         }
1060
1061         void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
1062             waitFor(mConditionVariable);
1063             assertEquals(state, mLastCallback);
1064             if (mockAgent != null) {
1065                 assertEquals(mockAgent.getNetwork(), mLastNetwork);
1066             }
1067             mLastCallback = CallbackState.NONE;
1068             mLastNetwork = null;
1069             mConditionVariable.close();
1070         }
1071
1072         void assertNoCallback() {
1073             assertEquals(CallbackState.NONE, mLastCallback);
1074         }
1075     }
1076
1077     @LargeTest
1078     public void testStateChangeNetworkCallbacks() throws Exception {
1079         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1080         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1081         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1082                 .addTransportType(TRANSPORT_WIFI).build();
1083         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1084                 .addTransportType(TRANSPORT_CELLULAR).build();
1085         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1086         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1087
1088         // Test unvalidated networks
1089         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1090         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1091         mCellNetworkAgent.connect(false);
1092         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1093         wifiNetworkCallback.assertNoCallback();
1094         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1095         waitFor(cv);
1096
1097         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1098         mCellNetworkAgent.adjustScore(-1);
1099         mService.waitForIdle();
1100         wifiNetworkCallback.assertNoCallback();
1101         cellNetworkCallback.assertNoCallback();
1102         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1103
1104         cv = waitForConnectivityBroadcasts(2);
1105         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1106         mWiFiNetworkAgent.connect(false);
1107         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1108         cellNetworkCallback.assertNoCallback();
1109         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1110         waitFor(cv);
1111
1112         cv = waitForConnectivityBroadcasts(2);
1113         mWiFiNetworkAgent.disconnect();
1114         wifiNetworkCallback.expectCallback(CallbackState.LOST);
1115         cellNetworkCallback.assertNoCallback();
1116         waitFor(cv);
1117
1118         cv = waitForConnectivityBroadcasts(1);
1119         mCellNetworkAgent.disconnect();
1120         cellNetworkCallback.expectCallback(CallbackState.LOST);
1121         wifiNetworkCallback.assertNoCallback();
1122         waitFor(cv);
1123
1124         // Test validated networks
1125         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1126         mCellNetworkAgent.connect(true);
1127         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1128         wifiNetworkCallback.assertNoCallback();
1129         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1130
1131         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1132         mCellNetworkAgent.adjustScore(-1);
1133         mService.waitForIdle();
1134         wifiNetworkCallback.assertNoCallback();
1135         cellNetworkCallback.assertNoCallback();
1136         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1137
1138         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1139         mWiFiNetworkAgent.connect(true);
1140         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1141         cellNetworkCallback.expectCallback(CallbackState.LOSING);
1142         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1143
1144         mWiFiNetworkAgent.disconnect();
1145         wifiNetworkCallback.expectCallback(CallbackState.LOST);
1146         cellNetworkCallback.assertNoCallback();
1147
1148         mCellNetworkAgent.disconnect();
1149         cellNetworkCallback.expectCallback(CallbackState.LOST);
1150         wifiNetworkCallback.assertNoCallback();
1151     }
1152
1153     private void tryNetworkFactoryRequests(int capability) throws Exception {
1154         // Verify NOT_RESTRICTED is set appropriately
1155         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1156                 .build().networkCapabilities;
1157         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1158                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1159                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1160                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1161             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1162         } else {
1163             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1164         }
1165
1166         NetworkCapabilities filter = new NetworkCapabilities();
1167         filter.addCapability(capability);
1168         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1169         handlerThread.start();
1170         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1171                 mServiceContext, "testFactory", filter);
1172         testFactory.setScoreFilter(40);
1173         ConditionVariable cv = testFactory.getNetworkStartedCV();
1174         testFactory.expectAddRequests(1);
1175         testFactory.register();
1176         testFactory.waitForNetworkRequests(1);
1177         int expectedRequestCount = 1;
1178         NetworkCallback networkCallback = null;
1179         // For non-INTERNET capabilities we cannot rely on the default request being present, so
1180         // add one.
1181         if (capability != NET_CAPABILITY_INTERNET) {
1182             assertFalse(testFactory.getMyStartRequested());
1183             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1184             networkCallback = new NetworkCallback();
1185             testFactory.expectAddRequests(1);
1186             mCm.requestNetwork(request, networkCallback);
1187             expectedRequestCount++;
1188             testFactory.waitForNetworkRequests(expectedRequestCount);
1189         }
1190         waitFor(cv);
1191         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1192         assertTrue(testFactory.getMyStartRequested());
1193
1194         // Now bring in a higher scored network.
1195         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1196         // Rather than create a validated network which complicates things by registering it's
1197         // own NetworkRequest during startup, just bump up the score to cancel out the
1198         // unvalidated penalty.
1199         testAgent.adjustScore(40);
1200         cv = testFactory.getNetworkStoppedCV();
1201
1202         // When testAgent connects, ConnectivityService will re-send us all current requests with
1203         // the new score. There are expectedRequestCount such requests, and we must wait for all of
1204         // them.
1205         testFactory.expectAddRequests(expectedRequestCount);
1206         testAgent.connect(false);
1207         testAgent.addCapability(capability);
1208         waitFor(cv);
1209         testFactory.waitForNetworkRequests(expectedRequestCount);
1210         assertFalse(testFactory.getMyStartRequested());
1211
1212         // Bring in a bunch of requests.
1213         testFactory.expectAddRequests(10);
1214         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1215         ConnectivityManager.NetworkCallback[] networkCallbacks =
1216                 new ConnectivityManager.NetworkCallback[10];
1217         for (int i = 0; i< networkCallbacks.length; i++) {
1218             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1219             NetworkRequest.Builder builder = new NetworkRequest.Builder();
1220             builder.addCapability(capability);
1221             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1222         }
1223         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1224         assertFalse(testFactory.getMyStartRequested());
1225
1226         // Remove the requests.
1227         testFactory.expectRemoveRequests(10);
1228         for (int i = 0; i < networkCallbacks.length; i++) {
1229             mCm.unregisterNetworkCallback(networkCallbacks[i]);
1230         }
1231         testFactory.waitForNetworkRequests(expectedRequestCount);
1232         assertFalse(testFactory.getMyStartRequested());
1233
1234         // Drop the higher scored network.
1235         cv = testFactory.getNetworkStartedCV();
1236         testAgent.disconnect();
1237         waitFor(cv);
1238         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1239         assertTrue(testFactory.getMyStartRequested());
1240
1241         testFactory.unregister();
1242         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1243         handlerThread.quit();
1244     }
1245
1246     @LargeTest
1247     public void testNetworkFactoryRequests() throws Exception {
1248         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1249         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1250         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1251         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1252         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1253         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1254         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1255         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1256         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1257         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1258         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1259         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1260         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1261         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1262         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1263         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1264     }
1265
1266     @LargeTest
1267     public void testNoMutableNetworkRequests() throws Exception {
1268         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1269         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1270         builder.addCapability(NET_CAPABILITY_VALIDATED);
1271         try {
1272             mCm.requestNetwork(builder.build(), new NetworkCallback());
1273             fail();
1274         } catch (IllegalArgumentException expected) {}
1275         try {
1276             mCm.requestNetwork(builder.build(), pendingIntent);
1277             fail();
1278         } catch (IllegalArgumentException expected) {}
1279         builder = new NetworkRequest.Builder();
1280         builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1281         try {
1282             mCm.requestNetwork(builder.build(), new NetworkCallback());
1283             fail();
1284         } catch (IllegalArgumentException expected) {}
1285         try {
1286             mCm.requestNetwork(builder.build(), pendingIntent);
1287             fail();
1288         } catch (IllegalArgumentException expected) {}
1289     }
1290
1291     @LargeTest
1292     public void testMMSonWiFi() throws Exception {
1293         // Test bringing up cellular without MMS NetworkRequest gets reaped
1294         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1295         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1296         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1297         mCellNetworkAgent.connectWithoutInternet();
1298         waitFor(cv);
1299         waitFor(new Criteria() {
1300                 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1301         verifyNoNetwork();
1302         // Test bringing up validated WiFi.
1303         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1304         cv = waitForConnectivityBroadcasts(1);
1305         mWiFiNetworkAgent.connect(true);
1306         waitFor(cv);
1307         verifyActiveNetwork(TRANSPORT_WIFI);
1308         // Register MMS NetworkRequest
1309         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1310         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1311         final TestNetworkCallback networkCallback = new TestNetworkCallback();
1312         mCm.requestNetwork(builder.build(), networkCallback);
1313         // Test bringing up unvalidated cellular with MMS
1314         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1315         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1316         mCellNetworkAgent.connectWithoutInternet();
1317         networkCallback.expectCallback(CallbackState.AVAILABLE);
1318         verifyActiveNetwork(TRANSPORT_WIFI);
1319         // Test releasing NetworkRequest disconnects cellular with MMS
1320         cv = mCellNetworkAgent.getDisconnectedCV();
1321         mCm.unregisterNetworkCallback(networkCallback);
1322         waitFor(cv);
1323         verifyActiveNetwork(TRANSPORT_WIFI);
1324     }
1325
1326     @LargeTest
1327     public void testMMSonCell() throws Exception {
1328         // Test bringing up cellular without MMS
1329         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1330         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1331         mCellNetworkAgent.connect(false);
1332         waitFor(cv);
1333         verifyActiveNetwork(TRANSPORT_CELLULAR);
1334         // Register MMS NetworkRequest
1335         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1336         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1337         final TestNetworkCallback networkCallback = new TestNetworkCallback();
1338         mCm.requestNetwork(builder.build(), networkCallback);
1339         // Test bringing up MMS cellular network
1340         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1341         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1342         mmsNetworkAgent.connectWithoutInternet();
1343         networkCallback.expectCallback(CallbackState.AVAILABLE);
1344         verifyActiveNetwork(TRANSPORT_CELLULAR);
1345         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1346         cv = mmsNetworkAgent.getDisconnectedCV();
1347         mCm.unregisterNetworkCallback(networkCallback);
1348         waitFor(cv);
1349         verifyActiveNetwork(TRANSPORT_CELLULAR);
1350     }
1351
1352     @LargeTest
1353     public void testCaptivePortal() {
1354         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1355         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1356                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1357         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1358
1359         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1360         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1361                 .addCapability(NET_CAPABILITY_VALIDATED).build();
1362         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1363
1364         // Bring up a network with a captive portal.
1365         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1366         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1367         String firstRedirectUrl = "http://example.com/firstPath";
1368         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1369         captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1370         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
1371
1372         // Take down network.
1373         // Expect onLost callback.
1374         mWiFiNetworkAgent.disconnect();
1375         captivePortalCallback.expectCallback(CallbackState.LOST);
1376
1377         // Bring up a network with a captive portal.
1378         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1379         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1380         String secondRedirectUrl = "http://example.com/secondPath";
1381         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1382         captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1383         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
1384
1385         // Make captive portal disappear then revalidate.
1386         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1387         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1388         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1389         captivePortalCallback.expectCallback(CallbackState.LOST);
1390
1391         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1392         validatedCallback.expectCallback(CallbackState.AVAILABLE);
1393
1394         // Break network connectivity.
1395         // Expect NET_CAPABILITY_VALIDATED onLost callback.
1396         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1397         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1398         validatedCallback.expectCallback(CallbackState.LOST);
1399     }
1400
1401     @SmallTest
1402     public void testInvalidNetworkSpecifier() {
1403         boolean execptionCalled = true;
1404
1405         try {
1406             NetworkRequest.Builder builder = new NetworkRequest.Builder();
1407             builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1408             execptionCalled = false;
1409         } catch (IllegalArgumentException e) {
1410             // do nothing - should get here
1411         }
1412
1413         assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1414                 execptionCalled);
1415
1416         try {
1417             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1418             networkCapabilities.addTransportType(TRANSPORT_WIFI)
1419                     .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1420             mService.requestNetwork(networkCapabilities, null, 0, null,
1421                     ConnectivityManager.TYPE_WIFI);
1422             execptionCalled = false;
1423         } catch (IllegalArgumentException e) {
1424             // do nothing - should get here
1425         }
1426
1427         assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1428                 execptionCalled);
1429     }
1430
1431     @LargeTest
1432     public void testRegisterDefaultNetworkCallback() throws Exception {
1433         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1434         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1435         defaultNetworkCallback.assertNoCallback();
1436
1437         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1438         // whenever Wi-Fi is up. Without this, the mobile network agent is
1439         // reaped before any other activity can take place.
1440         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1441         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1442                 .addTransportType(TRANSPORT_CELLULAR).build();
1443         mCm.requestNetwork(cellRequest, cellNetworkCallback);
1444         cellNetworkCallback.assertNoCallback();
1445
1446         // Bring up cell and expect CALLBACK_AVAILABLE.
1447         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1448         mCellNetworkAgent.connect(true);
1449         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1450         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1451
1452         // Bring up wifi and expect CALLBACK_AVAILABLE.
1453         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1454         mWiFiNetworkAgent.connect(true);
1455         cellNetworkCallback.assertNoCallback();
1456         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1457
1458         // Bring down cell. Expect no default network callback, since it wasn't the default.
1459         mCellNetworkAgent.disconnect();
1460         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1461         defaultNetworkCallback.assertNoCallback();
1462
1463         // Bring up cell. Expect no default network callback, since it won't be the default.
1464         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1465         mCellNetworkAgent.connect(true);
1466         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1467         defaultNetworkCallback.assertNoCallback();
1468
1469         // Bring down wifi. Expect the default network callback to notified of LOST wifi
1470         // followed by AVAILABLE cell.
1471         mWiFiNetworkAgent.disconnect();
1472         cellNetworkCallback.assertNoCallback();
1473         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1474         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1475         mCellNetworkAgent.disconnect();
1476         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1477         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1478     }
1479
1480     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
1481
1482         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
1483
1484         private class CallbackValue {
1485             public CallbackType callbackType;
1486             public int error;
1487
1488             public CallbackValue(CallbackType type) {
1489                 this.callbackType = type;
1490                 this.error = PacketKeepalive.SUCCESS;
1491                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
1492             }
1493
1494             public CallbackValue(CallbackType type, int error) {
1495                 this.callbackType = type;
1496                 this.error = error;
1497                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
1498             }
1499
1500             @Override
1501             public boolean equals(Object o) {
1502                 return o instanceof CallbackValue &&
1503                         this.callbackType == ((CallbackValue) o).callbackType &&
1504                         this.error == ((CallbackValue) o).error;
1505             }
1506
1507             @Override
1508             public String toString() {
1509                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
1510             }
1511         }
1512
1513         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
1514
1515         @Override
1516         public void onStarted() {
1517             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
1518         }
1519
1520         @Override
1521         public void onStopped() {
1522             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
1523         }
1524
1525         @Override
1526         public void onError(int error) {
1527             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
1528         }
1529
1530         private void expectCallback(CallbackValue callbackValue) {
1531             try {
1532                 assertEquals(
1533                         callbackValue,
1534                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1535             } catch (InterruptedException e) {
1536                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
1537             }
1538         }
1539
1540         public void expectStarted() {
1541             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
1542         }
1543
1544         public void expectStopped() {
1545             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
1546         }
1547
1548         public void expectError(int error) {
1549             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
1550         }
1551     }
1552
1553     private Network connectKeepaliveNetwork(LinkProperties lp) {
1554         // Ensure the network is disconnected before we do anything.
1555         if (mWiFiNetworkAgent != null) {
1556             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
1557         }
1558
1559         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1560         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1561         mWiFiNetworkAgent.connect(true);
1562         waitFor(cv);
1563         verifyActiveNetwork(TRANSPORT_WIFI);
1564         mWiFiNetworkAgent.sendLinkProperties(lp);
1565         mService.waitForIdle();
1566         return mWiFiNetworkAgent.getNetwork();
1567     }
1568
1569     public void testPacketKeepalives() throws Exception {
1570         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
1571         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
1572         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
1573         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
1574         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
1575
1576         LinkProperties lp = new LinkProperties();
1577         lp.setInterfaceName("wlan12");
1578         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
1579         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
1580         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
1581         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
1582
1583         Network notMyNet = new Network(61234);
1584         Network myNet = connectKeepaliveNetwork(lp);
1585
1586         TestKeepaliveCallback callback = new TestKeepaliveCallback();
1587         PacketKeepalive ka;
1588
1589         // Attempt to start keepalives with invalid parameters and check for errors.
1590         ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
1591         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1592
1593         ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
1594         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
1595
1596         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
1597         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1598
1599         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
1600         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1601
1602         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
1603         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);  // NAT-T is IPv4-only.
1604
1605         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1606         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1607
1608         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1609         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1610
1611         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1612         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1613
1614         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1615         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1616
1617         // Check that a started keepalive can be stopped.
1618         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1619         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1620         callback.expectStarted();
1621         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
1622         ka.stop();
1623         callback.expectStopped();
1624
1625         // Check that deleting the IP address stops the keepalive.
1626         LinkProperties bogusLp = new LinkProperties(lp);
1627         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1628         callback.expectStarted();
1629         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
1630         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
1631         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
1632         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1633         mWiFiNetworkAgent.sendLinkProperties(lp);
1634
1635         // Check that a started keepalive is stopped correctly when the network disconnects.
1636         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1637         callback.expectStarted();
1638         mWiFiNetworkAgent.disconnect();
1639         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1640
1641         // ... and that stopping it after that has no adverse effects.
1642         assertNull(mCm.getNetworkCapabilities(myNet));
1643         ka.stop();
1644
1645         // Reconnect.
1646         myNet = connectKeepaliveNetwork(lp);
1647         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1648
1649         // Check things work as expected when the keepalive is stopped and the network disconnects.
1650         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1651         callback.expectStarted();
1652         ka.stop();
1653         mWiFiNetworkAgent.disconnect();
1654         mService.waitForIdle();
1655         callback.expectStopped();
1656
1657         // Reconnect.
1658         myNet = connectKeepaliveNetwork(lp);
1659         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1660
1661         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
1662         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1663         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1664         callback.expectStarted();
1665
1666         // The second one gets slot 2.
1667         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
1668         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
1669         PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
1670         callback2.expectStarted();
1671
1672         // Now stop the first one and create a third. This also gets slot 1.
1673         ka.stop();
1674         callback.expectStopped();
1675
1676         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1677         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
1678         PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
1679         callback3.expectStarted();
1680
1681         ka2.stop();
1682         callback2.expectStopped();
1683
1684         ka3.stop();
1685         callback3.expectStopped();
1686     }
1687
1688     @SmallTest
1689     public void testGetCaptivePortalServerUrl() throws Exception {
1690         String url = mCm.getCaptivePortalServerUrl();
1691         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
1692     }
1693
1694     private static class TestNetworkPinner extends NetworkPinner {
1695         public static boolean awaitPin(int timeoutMs) {
1696             synchronized(sLock) {
1697                 if (sNetwork == null) {
1698                     try {
1699                         sLock.wait(timeoutMs);
1700                     } catch (InterruptedException e) {}
1701                 }
1702                 return sNetwork != null;
1703             }
1704         }
1705
1706         public static boolean awaitUnpin(int timeoutMs) {
1707             synchronized(sLock) {
1708                 if (sNetwork != null) {
1709                     try {
1710                         sLock.wait(timeoutMs);
1711                     } catch (InterruptedException e) {}
1712                 }
1713                 return sNetwork == null;
1714             }
1715         }
1716     }
1717
1718     private void assertPinnedToWifiWithCellDefault() {
1719         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
1720         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1721     }
1722
1723     private void assertPinnedToWifiWithWifiDefault() {
1724         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
1725         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1726     }
1727
1728     private void assertNotPinnedToWifi() {
1729         assertNull(mCm.getBoundNetworkForProcess());
1730         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1731     }
1732
1733     @SmallTest
1734     public void testNetworkPinner() {
1735         NetworkRequest wifiRequest = new NetworkRequest.Builder()
1736                 .addTransportType(TRANSPORT_WIFI)
1737                 .build();
1738         assertNull(mCm.getBoundNetworkForProcess());
1739
1740         TestNetworkPinner.pin(mServiceContext, wifiRequest);
1741         assertNull(mCm.getBoundNetworkForProcess());
1742
1743         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1744         mCellNetworkAgent.connect(true);
1745         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1746         mWiFiNetworkAgent.connect(false);
1747
1748         // When wi-fi connects, expect to be pinned.
1749         assertTrue(TestNetworkPinner.awaitPin(100));
1750         assertPinnedToWifiWithCellDefault();
1751
1752         // Disconnect and expect the pin to drop.
1753         mWiFiNetworkAgent.disconnect();
1754         assertTrue(TestNetworkPinner.awaitUnpin(100));
1755         assertNotPinnedToWifi();
1756
1757         // Reconnecting does not cause the pin to come back.
1758         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1759         mWiFiNetworkAgent.connect(false);
1760         assertFalse(TestNetworkPinner.awaitPin(100));
1761         assertNotPinnedToWifi();
1762
1763         // Pinning while connected causes the pin to take effect immediately.
1764         TestNetworkPinner.pin(mServiceContext, wifiRequest);
1765         assertTrue(TestNetworkPinner.awaitPin(100));
1766         assertPinnedToWifiWithCellDefault();
1767
1768         // Explicitly unpin and expect to use the default network again.
1769         TestNetworkPinner.unpin();
1770         assertNotPinnedToWifi();
1771
1772         // Disconnect cell and wifi.
1773         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
1774         mCellNetworkAgent.disconnect();
1775         mWiFiNetworkAgent.disconnect();
1776         waitFor(cv);
1777
1778         // Pinning takes effect even if the pinned network is the default when the pin is set...
1779         TestNetworkPinner.pin(mServiceContext, wifiRequest);
1780         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1781         mWiFiNetworkAgent.connect(false);
1782         assertTrue(TestNetworkPinner.awaitPin(100));
1783         assertPinnedToWifiWithWifiDefault();
1784
1785         // ... and is maintained even when that network is no longer the default.
1786         cv = waitForConnectivityBroadcasts(1);
1787         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1788         mCellNetworkAgent.connect(true);
1789         waitFor(cv);
1790         assertPinnedToWifiWithCellDefault();
1791     }
1792
1793     @SmallTest
1794     public void testNetworkRequestMaximum() {
1795         final int MAX_REQUESTS = 100;
1796         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
1797         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
1798         ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
1799         try {
1800             for (int i = 0; i < MAX_REQUESTS; i++) {
1801                 NetworkCallback networkCallback = new NetworkCallback();
1802                 mCm.requestNetwork(networkRequest, networkCallback);
1803                 networkCallbacks.add(networkCallback);
1804             }
1805             fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
1806         } catch (IllegalArgumentException expected) {}
1807         for (NetworkCallback networkCallback : networkCallbacks) {
1808             mCm.unregisterNetworkCallback(networkCallback);
1809         }
1810         networkCallbacks.clear();
1811
1812         try {
1813             for (int i = 0; i < MAX_REQUESTS; i++) {
1814                 NetworkCallback networkCallback = new NetworkCallback();
1815                 mCm.registerNetworkCallback(networkRequest, networkCallback);
1816                 networkCallbacks.add(networkCallback);
1817             }
1818             fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
1819         } catch (IllegalArgumentException expected) {}
1820         for (NetworkCallback networkCallback : networkCallbacks) {
1821             mCm.unregisterNetworkCallback(networkCallback);
1822         }
1823         networkCallbacks.clear();
1824
1825         ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
1826         try {
1827             for (int i = 0; i < MAX_REQUESTS + 1; i++) {
1828                 PendingIntent pendingIntent =
1829                         PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
1830                 mCm.requestNetwork(networkRequest, pendingIntent);
1831                 pendingIntents.add(pendingIntent);
1832             }
1833             fail("Registering " + MAX_REQUESTS +
1834                     " PendingIntent NetworkRequests did not throw exception");
1835         } catch (IllegalArgumentException expected) {}
1836         for (PendingIntent pendingIntent : pendingIntents) {
1837             mCm.unregisterNetworkCallback(pendingIntent);
1838         }
1839         pendingIntents.clear();
1840
1841         try {
1842             for (int i = 0; i < MAX_REQUESTS + 1; i++) {
1843                 PendingIntent pendingIntent =
1844                         PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
1845                 mCm.registerNetworkCallback(networkRequest, pendingIntent);
1846                 pendingIntents.add(pendingIntent);
1847             }
1848             fail("Registering " + MAX_REQUESTS +
1849                     " PendingIntent NetworkCallbacks did not throw exception");
1850         } catch (IllegalArgumentException expected) {}
1851         for (PendingIntent pendingIntent : pendingIntents) {
1852             mCm.unregisterNetworkCallback(pendingIntent);
1853         }
1854         pendingIntents.clear();
1855         mService.waitForIdle(5000);
1856
1857         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
1858         for (int i = 0; i < MAX_REQUESTS; i++) {
1859             NetworkCallback networkCallback = new NetworkCallback();
1860             mCm.requestNetwork(networkRequest, networkCallback);
1861             mCm.unregisterNetworkCallback(networkCallback);
1862         }
1863         mService.waitForIdle();
1864         for (int i = 0; i < MAX_REQUESTS; i++) {
1865             NetworkCallback networkCallback = new NetworkCallback();
1866             mCm.registerNetworkCallback(networkRequest, networkCallback);
1867             mCm.unregisterNetworkCallback(networkCallback);
1868         }
1869         mService.waitForIdle();
1870         for (int i = 0; i < MAX_REQUESTS; i++) {
1871             PendingIntent pendingIntent =
1872                     PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
1873             mCm.requestNetwork(networkRequest, pendingIntent);
1874             mCm.unregisterNetworkCallback(pendingIntent);
1875         }
1876         mService.waitForIdle();
1877         for (int i = 0; i < MAX_REQUESTS; i++) {
1878             PendingIntent pendingIntent =
1879                     PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
1880             mCm.registerNetworkCallback(networkRequest, pendingIntent);
1881             mCm.unregisterNetworkCallback(pendingIntent);
1882         }
1883     }
1884 }