OSDN Git Service

system_server: add CAP_SYS_PTRACE am: 966619d0ab am: b8d972e973 am: c46889e2d2
[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.INetworkManagementService;
56 import android.os.Looper;
57 import android.os.Message;
58 import android.os.MessageQueue;
59 import android.os.MessageQueue.IdleHandler;
60 import android.test.AndroidTestCase;
61 import android.test.suitebuilder.annotation.LargeTest;
62 import android.util.Log;
63 import android.util.LogPrinter;
64
65 import com.android.server.connectivity.NetworkAgentInfo;
66 import com.android.server.connectivity.NetworkMonitor;
67
68 import java.net.InetAddress;
69 import java.util.concurrent.CountDownLatch;
70 import java.util.concurrent.LinkedBlockingQueue;
71 import java.util.concurrent.TimeUnit;
72 import java.util.concurrent.atomic.AtomicBoolean;
73
74 /**
75  * Tests for {@link ConnectivityService}.
76  *
77  * Build, install and run with:
78  *  runtest frameworks-services -c com.android.server.ConnectivityServiceTest
79  */
80 public class ConnectivityServiceTest extends AndroidTestCase {
81     private static final String TAG = "ConnectivityServiceTest";
82
83     private static final int TIMEOUT_MS = 500;
84
85     private BroadcastInterceptingContext mServiceContext;
86     private WrappedConnectivityService mService;
87     private ConnectivityManager mCm;
88     private MockNetworkAgent mWiFiNetworkAgent;
89     private MockNetworkAgent mCellNetworkAgent;
90
91     private class MockContext extends BroadcastInterceptingContext {
92         MockContext(Context base) {
93             super(base);
94         }
95
96         @Override
97         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
98             // PendingIntents sent by the AlarmManager are not intercepted by
99             // BroadcastInterceptingContext so we must really register the receiver.
100             // This shouldn't effect the real NetworkMonitors as the action contains a random token.
101             if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
102                 return getBaseContext().registerReceiver(receiver, filter);
103             } else {
104                 return super.registerReceiver(receiver, filter);
105             }
106         }
107
108         @Override
109         public Object getSystemService (String name) {
110             if (name == Context.CONNECTIVITY_SERVICE) return mCm;
111             return super.getSystemService(name);
112         }
113     }
114
115     /**
116      * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
117      * will return immediately if the handler is already idle.
118      */
119     private class IdleableHandlerThread extends HandlerThread {
120         private IdleHandler mIdleHandler;
121
122         public IdleableHandlerThread(String name) {
123             super(name);
124         }
125
126         public void waitForIdle(int timeoutMs) {
127             final ConditionVariable cv = new ConditionVariable();
128             final MessageQueue queue = getLooper().getQueue();
129
130             synchronized (queue) {
131                 if (queue.isIdle()) {
132                     return;
133                 }
134
135                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
136                 mIdleHandler = new IdleHandler() {
137                     public boolean queueIdle() {
138                         cv.open();
139                         mIdleHandler = null;
140                         return false;  // Remove the handler.
141                     }
142                 };
143                 queue.addIdleHandler(mIdleHandler);
144             }
145
146             if (!cv.block(timeoutMs)) {
147                 fail("HandlerThread " + getName() +
148                         " did not become idle after " + timeoutMs + " ms");
149                 queue.removeIdleHandler(mIdleHandler);
150             }
151         }
152     }
153
154     // Tests that IdleableHandlerThread works as expected.
155     public void testIdleableHandlerThread() {
156         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
157
158         // Tests that waitForIdle returns immediately if the service is already idle.
159         for (int i = 0; i < attempts; i++) {
160             mService.waitForIdle();
161         }
162
163         // Bring up a network that we can use to send messages to ConnectivityService.
164         ConditionVariable cv = waitForConnectivityBroadcasts(1);
165         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
166         mWiFiNetworkAgent.connect(false);
167         waitFor(cv);
168         Network n = mWiFiNetworkAgent.getNetwork();
169         assertNotNull(n);
170
171         // Tests that calling waitForIdle waits for messages to be processed.
172         for (int i = 0; i < attempts; i++) {
173             mWiFiNetworkAgent.setSignalStrength(i);
174             mService.waitForIdle();
175             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
176         }
177
178         // Ensure that not calling waitForIdle causes a race condition.
179         for (int i = 0; i < attempts; i++) {
180             mWiFiNetworkAgent.setSignalStrength(i);
181             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
182                 // We hit a race condition, as expected. Pass the test.
183                 return;
184             }
185         }
186
187         // No race? There is a bug in this test.
188         fail("expected race condition at least once in " + attempts + " attempts");
189     }
190
191     private class MockNetworkAgent {
192         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
193         private final NetworkInfo mNetworkInfo;
194         private final NetworkCapabilities mNetworkCapabilities;
195         private final IdleableHandlerThread mHandlerThread;
196         private final ConditionVariable mDisconnected = new ConditionVariable();
197         private int mScore;
198         private NetworkAgent mNetworkAgent;
199         private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
200         private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
201         private Integer mExpectedKeepaliveSlot = null;
202
203         MockNetworkAgent(int transport) {
204             final int type = transportToLegacyType(transport);
205             final String typeName = ConnectivityManager.getNetworkTypeName(type);
206             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
207             mNetworkCapabilities = new NetworkCapabilities();
208             mNetworkCapabilities.addTransportType(transport);
209             switch (transport) {
210                 case TRANSPORT_WIFI:
211                     mScore = 60;
212                     break;
213                 case TRANSPORT_CELLULAR:
214                     mScore = 50;
215                     break;
216                 default:
217                     throw new UnsupportedOperationException("unimplemented network type");
218             }
219             mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
220             mHandlerThread.start();
221             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
222                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
223                     new LinkProperties(), mScore, new NetworkMisc()) {
224                 @Override
225                 public void unwanted() { mDisconnected.open(); }
226
227                 @Override
228                 public void startPacketKeepalive(Message msg) {
229                     int slot = msg.arg1;
230                     if (mExpectedKeepaliveSlot != null) {
231                         assertEquals((int) mExpectedKeepaliveSlot, slot);
232                     }
233                     onPacketKeepaliveEvent(slot, mStartKeepaliveError);
234                 }
235
236                 @Override
237                 public void stopPacketKeepalive(Message msg) {
238                     onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
239                 }
240             };
241             // Waits for the NetworkAgent to be registered, which includes the creation of the
242             // NetworkMonitor.
243             mService.waitForIdle();
244             mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
245         }
246
247         public void waitForIdle(int timeoutMs) {
248             mHandlerThread.waitForIdle(timeoutMs);
249         }
250
251         public void waitForIdle() {
252             waitForIdle(TIMEOUT_MS);
253         }
254
255         public void adjustScore(int change) {
256             mScore += change;
257             mNetworkAgent.sendNetworkScore(mScore);
258         }
259
260         public void addCapability(int capability) {
261             mNetworkCapabilities.addCapability(capability);
262             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
263         }
264
265         public void setSignalStrength(int signalStrength) {
266             mNetworkCapabilities.setSignalStrength(signalStrength);
267             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
268         }
269
270         public void connectWithoutInternet() {
271             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
272             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
273         }
274
275         /**
276          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
277          * @param validated Indicate if network should pretend to be validated.
278          */
279         public void connect(boolean validated) {
280             assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE);
281             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
282
283             NetworkCallback callback = null;
284             final ConditionVariable validatedCv = new ConditionVariable();
285             if (validated) {
286                 mWrappedNetworkMonitor.gen204ProbeResult = 204;
287                 NetworkRequest request = new NetworkRequest.Builder()
288                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
289                         .build();
290                 callback = new NetworkCallback() {
291                     public void onCapabilitiesChanged(Network network,
292                             NetworkCapabilities networkCapabilities) {
293                         if (network.equals(getNetwork()) &&
294                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
295                             validatedCv.open();
296                         }
297                     }
298                 };
299                 mCm.registerNetworkCallback(request, callback);
300             }
301             addCapability(NET_CAPABILITY_INTERNET);
302
303             connectWithoutInternet();
304
305             if (validated) {
306                 // Wait for network to validate.
307                 waitFor(validatedCv);
308                 mWrappedNetworkMonitor.gen204ProbeResult = 500;
309             }
310
311             if (callback != null) mCm.unregisterNetworkCallback(callback);
312         }
313
314         public void connectWithCaptivePortal() {
315             mWrappedNetworkMonitor.gen204ProbeResult = 200;
316             connect(false);
317             waitFor(new Criteria() { public boolean get() {
318                 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
319                 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
320             mWrappedNetworkMonitor.gen204ProbeResult = 500;
321         }
322
323         public void disconnect() {
324             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
325             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
326         }
327
328         public Network getNetwork() {
329             return new Network(mNetworkAgent.netId);
330         }
331
332         public ConditionVariable getDisconnectedCV() {
333             return mDisconnected;
334         }
335
336         public WrappedNetworkMonitor getWrappedNetworkMonitor() {
337             return mWrappedNetworkMonitor;
338         }
339
340         public void sendLinkProperties(LinkProperties lp) {
341             mNetworkAgent.sendLinkProperties(lp);
342         }
343
344         public void setStartKeepaliveError(int error) {
345             mStartKeepaliveError = error;
346         }
347
348         public void setStopKeepaliveError(int error) {
349             mStopKeepaliveError = error;
350         }
351
352         public void setExpectedKeepaliveSlot(Integer slot) {
353             mExpectedKeepaliveSlot = slot;
354         }
355     }
356
357     /**
358      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
359      * operations have been processed. Before ConnectivityService can add or remove any requests,
360      * the factory must be told to expect those operations by calling expectAddRequests or
361      * expectRemoveRequests.
362      */
363     private static class MockNetworkFactory extends NetworkFactory {
364         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
365         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
366         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
367
368         // Used to expect that requests be removed or added on a separate thread, without sleeping.
369         // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
370         // cause some other thread to add or remove requests, then call waitForRequests(). We can
371         // either expect requests to be added or removed, but not both, because CountDownLatch can
372         // only count in one direction.
373         private CountDownLatch mExpectations;
374
375         // Whether we are currently expecting requests to be added or removed. Valid only if
376         // mExpectations is non-null.
377         private boolean mExpectingAdditions;
378
379         public MockNetworkFactory(Looper looper, Context context, String logTag,
380                 NetworkCapabilities filter) {
381             super(looper, context, logTag, filter);
382         }
383
384         public int getMyRequestCount() {
385             return getRequestCount();
386         }
387
388         protected void startNetwork() {
389             mNetworkStarted.set(true);
390             mNetworkStartedCV.open();
391         }
392
393         protected void stopNetwork() {
394             mNetworkStarted.set(false);
395             mNetworkStoppedCV.open();
396         }
397
398         public boolean getMyStartRequested() {
399             return mNetworkStarted.get();
400         }
401
402         public ConditionVariable getNetworkStartedCV() {
403             mNetworkStartedCV.close();
404             return mNetworkStartedCV;
405         }
406
407         public ConditionVariable getNetworkStoppedCV() {
408             mNetworkStoppedCV.close();
409             return mNetworkStoppedCV;
410         }
411
412         @Override
413         protected void handleAddRequest(NetworkRequest request, int score) {
414             // If we're expecting anything, we must be expecting additions.
415             if (mExpectations != null && !mExpectingAdditions) {
416                 fail("Can't add requests while expecting requests to be removed");
417             }
418
419             // Add the request.
420             super.handleAddRequest(request, score);
421
422             // Reduce the number of request additions we're waiting for.
423             if (mExpectingAdditions) {
424                 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
425                 mExpectations.countDown();
426             }
427         }
428
429         @Override
430         protected void handleRemoveRequest(NetworkRequest request) {
431             // If we're expecting anything, we must be expecting removals.
432             if (mExpectations != null && mExpectingAdditions) {
433                 fail("Can't remove requests while expecting requests to be added");
434             }
435
436             // Remove the request.
437             super.handleRemoveRequest(request);
438
439             // Reduce the number of request removals we're waiting for.
440             if (!mExpectingAdditions) {
441                 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
442                 mExpectations.countDown();
443             }
444         }
445
446         private void assertNoExpectations() {
447             if (mExpectations != null) {
448                 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
449             }
450         }
451
452         // Expects that count requests will be added.
453         public void expectAddRequests(final int count) {
454             assertNoExpectations();
455             mExpectingAdditions = true;
456             mExpectations = new CountDownLatch(count);
457         }
458
459         // Expects that count requests will be removed.
460         public void expectRemoveRequests(final int count) {
461             assertNoExpectations();
462             mExpectingAdditions = false;
463             mExpectations = new CountDownLatch(count);
464         }
465
466         // Waits for the expected request additions or removals to happen within a timeout.
467         public void waitForRequests() throws InterruptedException {
468             assertNotNull("Nothing to wait for", mExpectations);
469             mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
470             final long count = mExpectations.getCount();
471             final String msg = count + " requests still not " +
472                     (mExpectingAdditions ? "added" : "removed") +
473                     " after " + TIMEOUT_MS + " ms";
474             assertEquals(msg, 0, count);
475             mExpectations = null;
476         }
477
478         public void waitForNetworkRequests(final int count) throws InterruptedException {
479             waitForRequests();
480             assertEquals(count, getMyRequestCount());
481         }
482     }
483
484     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
485     private class WrappedNetworkMonitor extends NetworkMonitor {
486         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
487         public int gen204ProbeResult = 500;
488
489         public WrappedNetworkMonitor(Context context, Handler handler,
490             NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
491             super(context, handler, networkAgentInfo, defaultRequest);
492         }
493
494         @Override
495         protected int isCaptivePortal() {
496             return gen204ProbeResult;
497         }
498     }
499
500     private class WrappedConnectivityService extends ConnectivityService {
501         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
502
503         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
504                 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
505             super(context, netManager, statsService, policyManager);
506         }
507
508         @Override
509         protected HandlerThread createHandlerThread() {
510             return new IdleableHandlerThread("WrappedConnectivityService");
511         }
512
513         @Override
514         protected int getDefaultTcpRwnd() {
515             // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
516             return 0;
517         }
518
519         @Override
520         protected int reserveNetId() {
521             while (true) {
522                 final int netId = super.reserveNetId();
523
524                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
525                 // can have odd side-effects, like network validations succeeding.
526                 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
527                 boolean overlaps = false;
528                 for (Network network : networks) {
529                     if (netId == network.netId) {
530                         overlaps = true;
531                         break;
532                     }
533                 }
534                 if (overlaps) continue;
535
536                 return netId;
537             }
538         }
539
540         @Override
541         public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
542                 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
543             final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai,
544                     defaultRequest);
545             mLastCreatedNetworkMonitor = monitor;
546             return monitor;
547         }
548
549         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
550             return mLastCreatedNetworkMonitor;
551         }
552
553         public void waitForIdle(int timeoutMs) {
554             ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
555         }
556
557         public void waitForIdle() {
558             waitForIdle(TIMEOUT_MS);
559         }
560
561     }
562
563     private interface Criteria {
564         public boolean get();
565     }
566
567     /**
568      * Wait up to 500ms for {@code criteria.get()} to become true, polling.
569      * Fails if 500ms goes by before {@code criteria.get()} to become true.
570      */
571     static private void waitFor(Criteria criteria) {
572         int delays = 0;
573         while (!criteria.get()) {
574             try {
575                 Thread.sleep(100);
576             } catch (InterruptedException e) {
577             }
578             if (++delays == 5) fail();
579         }
580     }
581
582     /**
583      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
584      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
585      */
586     static private void waitFor(ConditionVariable conditionVariable) {
587         assertTrue(conditionVariable.block(TIMEOUT_MS));
588     }
589
590     @Override
591     public void setUp() throws Exception {
592         super.setUp();
593
594         mServiceContext = new MockContext(getContext());
595         mService = new WrappedConnectivityService(mServiceContext,
596                 mock(INetworkManagementService.class),
597                 mock(INetworkStatsService.class),
598                 mock(INetworkPolicyManager.class));
599
600         mService.systemReady();
601         mCm = new ConnectivityManager(getContext(), mService);
602     }
603
604     private int transportToLegacyType(int transport) {
605         switch (transport) {
606             case TRANSPORT_WIFI:
607                 return TYPE_WIFI;
608             case TRANSPORT_CELLULAR:
609                 return TYPE_MOBILE;
610             default:
611                 throw new IllegalStateException("Unknown transport" + transport);
612         }
613     }
614
615     private void verifyActiveNetwork(int transport) {
616         // Test getActiveNetworkInfo()
617         assertNotNull(mCm.getActiveNetworkInfo());
618         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
619         // Test getActiveNetwork()
620         assertNotNull(mCm.getActiveNetwork());
621         switch (transport) {
622             case TRANSPORT_WIFI:
623                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
624                 break;
625             case TRANSPORT_CELLULAR:
626                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
627                 break;
628             default:
629                 throw new IllegalStateException("Unknown transport" + transport);
630         }
631         // Test getNetworkInfo(Network)
632         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
633         assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
634         // Test getNetworkCapabilities(Network)
635         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
636         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
637     }
638
639     private void verifyNoNetwork() {
640         // Test getActiveNetworkInfo()
641         assertNull(mCm.getActiveNetworkInfo());
642         // Test getActiveNetwork()
643         assertNull(mCm.getActiveNetwork());
644         // Test getAllNetworks()
645         assertEquals(0, mCm.getAllNetworks().length);
646     }
647
648     /**
649      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
650      * broadcasts are received.
651      */
652     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
653         final ConditionVariable cv = new ConditionVariable();
654         mServiceContext.registerReceiver(new BroadcastReceiver() {
655                     private int remaining = count;
656                     public void onReceive(Context context, Intent intent) {
657                         if (--remaining == 0) {
658                             cv.open();
659                             mServiceContext.unregisterReceiver(this);
660                         }
661                     }
662                 }, new IntentFilter(CONNECTIVITY_ACTION));
663         return cv;
664     }
665
666     @LargeTest
667     public void testLingering() throws Exception {
668         // Decrease linger timeout to the minimum allowed by AlarmManagerService.
669         NetworkMonitor.SetDefaultLingerTime(5000);
670         verifyNoNetwork();
671         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
672         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
673         assertNull(mCm.getActiveNetworkInfo());
674         assertNull(mCm.getActiveNetwork());
675         // Test bringing up validated cellular.
676         ConditionVariable cv = waitForConnectivityBroadcasts(1);
677         mCellNetworkAgent.connect(true);
678         waitFor(cv);
679         verifyActiveNetwork(TRANSPORT_CELLULAR);
680         assertEquals(2, mCm.getAllNetworks().length);
681         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
682                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
683         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
684                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
685         // Test bringing up validated WiFi.
686         cv = waitForConnectivityBroadcasts(2);
687         mWiFiNetworkAgent.connect(true);
688         waitFor(cv);
689         verifyActiveNetwork(TRANSPORT_WIFI);
690         assertEquals(2, mCm.getAllNetworks().length);
691         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
692                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
693         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
694                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
695         // Test cellular linger timeout.
696         try {
697             Thread.sleep(6000);
698         } catch (InterruptedException e) {
699         }
700         verifyActiveNetwork(TRANSPORT_WIFI);
701         assertEquals(1, mCm.getAllNetworks().length);
702         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
703         // Test WiFi disconnect.
704         cv = waitForConnectivityBroadcasts(1);
705         mWiFiNetworkAgent.disconnect();
706         waitFor(cv);
707         verifyNoNetwork();
708     }
709
710     @LargeTest
711     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
712         // Test bringing up unvalidated WiFi
713         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
714         ConditionVariable cv = waitForConnectivityBroadcasts(1);
715         mWiFiNetworkAgent.connect(false);
716         waitFor(cv);
717         verifyActiveNetwork(TRANSPORT_WIFI);
718         // Test bringing up unvalidated cellular
719         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
720         mCellNetworkAgent.connect(false);
721         mService.waitForIdle();
722         verifyActiveNetwork(TRANSPORT_WIFI);
723         // Test cellular disconnect.
724         mCellNetworkAgent.disconnect();
725         mService.waitForIdle();
726         verifyActiveNetwork(TRANSPORT_WIFI);
727         // Test bringing up validated cellular
728         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
729         cv = waitForConnectivityBroadcasts(2);
730         mCellNetworkAgent.connect(true);
731         waitFor(cv);
732         verifyActiveNetwork(TRANSPORT_CELLULAR);
733         // Test cellular disconnect.
734         cv = waitForConnectivityBroadcasts(2);
735         mCellNetworkAgent.disconnect();
736         waitFor(cv);
737         verifyActiveNetwork(TRANSPORT_WIFI);
738         // Test WiFi disconnect.
739         cv = waitForConnectivityBroadcasts(1);
740         mWiFiNetworkAgent.disconnect();
741         waitFor(cv);
742         verifyNoNetwork();
743     }
744
745     @LargeTest
746     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
747         // Test bringing up unvalidated cellular.
748         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
749         ConditionVariable cv = waitForConnectivityBroadcasts(1);
750         mCellNetworkAgent.connect(false);
751         waitFor(cv);
752         verifyActiveNetwork(TRANSPORT_CELLULAR);
753         // Test bringing up unvalidated WiFi.
754         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
755         cv = waitForConnectivityBroadcasts(2);
756         mWiFiNetworkAgent.connect(false);
757         waitFor(cv);
758         verifyActiveNetwork(TRANSPORT_WIFI);
759         // Test WiFi disconnect.
760         cv = waitForConnectivityBroadcasts(2);
761         mWiFiNetworkAgent.disconnect();
762         waitFor(cv);
763         verifyActiveNetwork(TRANSPORT_CELLULAR);
764         // Test cellular disconnect.
765         cv = waitForConnectivityBroadcasts(1);
766         mCellNetworkAgent.disconnect();
767         waitFor(cv);
768         verifyNoNetwork();
769     }
770
771     @LargeTest
772     public void testUnlingeringDoesNotValidate() throws Exception {
773         // Test bringing up unvalidated WiFi.
774         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
775         ConditionVariable cv = waitForConnectivityBroadcasts(1);
776         mWiFiNetworkAgent.connect(false);
777         waitFor(cv);
778         verifyActiveNetwork(TRANSPORT_WIFI);
779         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
780                 NET_CAPABILITY_VALIDATED));
781         // Test bringing up validated cellular.
782         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
783         cv = waitForConnectivityBroadcasts(2);
784         mCellNetworkAgent.connect(true);
785         waitFor(cv);
786         verifyActiveNetwork(TRANSPORT_CELLULAR);
787         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
788                 NET_CAPABILITY_VALIDATED));
789         // Test cellular disconnect.
790         cv = waitForConnectivityBroadcasts(2);
791         mCellNetworkAgent.disconnect();
792         waitFor(cv);
793         verifyActiveNetwork(TRANSPORT_WIFI);
794         // Unlingering a network should not cause it to be marked as validated.
795         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
796                 NET_CAPABILITY_VALIDATED));
797     }
798
799     @LargeTest
800     public void testCellularOutscoresWeakWifi() throws Exception {
801         // Test bringing up validated cellular.
802         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
803         ConditionVariable cv = waitForConnectivityBroadcasts(1);
804         mCellNetworkAgent.connect(true);
805         waitFor(cv);
806         verifyActiveNetwork(TRANSPORT_CELLULAR);
807         // Test bringing up validated WiFi.
808         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
809         cv = waitForConnectivityBroadcasts(2);
810         mWiFiNetworkAgent.connect(true);
811         waitFor(cv);
812         verifyActiveNetwork(TRANSPORT_WIFI);
813         // Test WiFi getting really weak.
814         cv = waitForConnectivityBroadcasts(2);
815         mWiFiNetworkAgent.adjustScore(-11);
816         waitFor(cv);
817         verifyActiveNetwork(TRANSPORT_CELLULAR);
818         // Test WiFi restoring signal strength.
819         cv = waitForConnectivityBroadcasts(2);
820         mWiFiNetworkAgent.adjustScore(11);
821         waitFor(cv);
822         verifyActiveNetwork(TRANSPORT_WIFI);
823         mCellNetworkAgent.disconnect();
824         mWiFiNetworkAgent.disconnect();
825     }
826
827     @LargeTest
828     public void testReapingNetwork() throws Exception {
829         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
830         // Expect it to be torn down immediately because it satisfies no requests.
831         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
832         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
833         mWiFiNetworkAgent.connectWithoutInternet();
834         waitFor(cv);
835         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
836         // Expect it to be torn down immediately because it satisfies no requests.
837         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
838         cv = mCellNetworkAgent.getDisconnectedCV();
839         mCellNetworkAgent.connectWithoutInternet();
840         waitFor(cv);
841         // Test bringing up validated WiFi.
842         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
843         cv = waitForConnectivityBroadcasts(1);
844         mWiFiNetworkAgent.connect(true);
845         waitFor(cv);
846         verifyActiveNetwork(TRANSPORT_WIFI);
847         // Test bringing up unvalidated cellular.
848         // Expect it to be torn down because it could never be the highest scoring network
849         // satisfying the default request even if it validated.
850         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
851         cv = mCellNetworkAgent.getDisconnectedCV();
852         mCellNetworkAgent.connect(false);
853         waitFor(cv);
854         verifyActiveNetwork(TRANSPORT_WIFI);
855         cv = mWiFiNetworkAgent.getDisconnectedCV();
856         mWiFiNetworkAgent.disconnect();
857         waitFor(cv);
858     }
859
860     @LargeTest
861     public void testCellularFallback() throws Exception {
862         // Test bringing up validated cellular.
863         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
864         ConditionVariable cv = waitForConnectivityBroadcasts(1);
865         mCellNetworkAgent.connect(true);
866         waitFor(cv);
867         verifyActiveNetwork(TRANSPORT_CELLULAR);
868         // Test bringing up validated WiFi.
869         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
870         cv = waitForConnectivityBroadcasts(2);
871         mWiFiNetworkAgent.connect(true);
872         waitFor(cv);
873         verifyActiveNetwork(TRANSPORT_WIFI);
874         // Reevaluate WiFi (it'll instantly fail DNS).
875         cv = waitForConnectivityBroadcasts(2);
876         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
877                 NET_CAPABILITY_VALIDATED));
878         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
879         // Should quickly fall back to Cellular.
880         waitFor(cv);
881         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
882                 NET_CAPABILITY_VALIDATED));
883         verifyActiveNetwork(TRANSPORT_CELLULAR);
884         // Reevaluate cellular (it'll instantly fail DNS).
885         cv = waitForConnectivityBroadcasts(2);
886         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
887                 NET_CAPABILITY_VALIDATED));
888         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
889         // Should quickly fall back to WiFi.
890         waitFor(cv);
891         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
892                 NET_CAPABILITY_VALIDATED));
893         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
894                 NET_CAPABILITY_VALIDATED));
895         verifyActiveNetwork(TRANSPORT_WIFI);
896         mCellNetworkAgent.disconnect();
897         mWiFiNetworkAgent.disconnect();
898     }
899
900     @LargeTest
901     public void testWiFiFallback() throws Exception {
902         // Test bringing up unvalidated WiFi.
903         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
904         ConditionVariable cv = waitForConnectivityBroadcasts(1);
905         mWiFiNetworkAgent.connect(false);
906         waitFor(cv);
907         verifyActiveNetwork(TRANSPORT_WIFI);
908         // Test bringing up validated cellular.
909         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
910         cv = waitForConnectivityBroadcasts(2);
911         mCellNetworkAgent.connect(true);
912         waitFor(cv);
913         verifyActiveNetwork(TRANSPORT_CELLULAR);
914         // Reevaluate cellular (it'll instantly fail DNS).
915         cv = waitForConnectivityBroadcasts(2);
916         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
917                 NET_CAPABILITY_VALIDATED));
918         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
919         // Should quickly fall back to WiFi.
920         waitFor(cv);
921         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
922                 NET_CAPABILITY_VALIDATED));
923         verifyActiveNetwork(TRANSPORT_WIFI);
924         mCellNetworkAgent.disconnect();
925         mWiFiNetworkAgent.disconnect();
926     }
927
928     enum CallbackState {
929         NONE,
930         AVAILABLE,
931         LOSING,
932         LOST
933     }
934
935     /**
936      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
937      * this class receives, by calling expectCallback() exactly once each time a callback is
938      * received. assertNoCallback may be called at any time.
939      */
940     private class TestNetworkCallback extends NetworkCallback {
941         private final ConditionVariable mConditionVariable = new ConditionVariable();
942         private CallbackState mLastCallback = CallbackState.NONE;
943
944         public void onAvailable(Network network) {
945             assertEquals(CallbackState.NONE, mLastCallback);
946             mLastCallback = CallbackState.AVAILABLE;
947             mConditionVariable.open();
948         }
949
950         public void onLosing(Network network, int maxMsToLive) {
951             assertEquals(CallbackState.NONE, mLastCallback);
952             mLastCallback = CallbackState.LOSING;
953             mConditionVariable.open();
954         }
955
956         public void onLost(Network network) {
957             assertEquals(CallbackState.NONE, mLastCallback);
958             mLastCallback = CallbackState.LOST;
959             mConditionVariable.open();
960         }
961
962         void expectCallback(CallbackState state) {
963             waitFor(mConditionVariable);
964             assertEquals(state, mLastCallback);
965             mLastCallback = CallbackState.NONE;
966             mConditionVariable.close();
967         }
968
969         void assertNoCallback() {
970             assertEquals(CallbackState.NONE, mLastCallback);
971         }
972     }
973
974     @LargeTest
975     public void testStateChangeNetworkCallbacks() throws Exception {
976         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
977         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
978         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
979                 .addTransportType(TRANSPORT_WIFI).build();
980         final NetworkRequest cellRequest = new NetworkRequest.Builder()
981                 .addTransportType(TRANSPORT_CELLULAR).build();
982         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
983         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
984
985         // Test unvalidated networks
986         ConditionVariable cv = waitForConnectivityBroadcasts(1);
987         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
988         mCellNetworkAgent.connect(false);
989         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
990         wifiNetworkCallback.assertNoCallback();
991         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
992         waitFor(cv);
993
994         // This should not trigger spurious onAvailable() callbacks, b/21762680.
995         mCellNetworkAgent.adjustScore(-1);
996         mService.waitForIdle();
997         wifiNetworkCallback.assertNoCallback();
998         cellNetworkCallback.assertNoCallback();
999         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1000
1001         cv = waitForConnectivityBroadcasts(2);
1002         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1003         mWiFiNetworkAgent.connect(false);
1004         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1005         cellNetworkCallback.assertNoCallback();
1006         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1007         waitFor(cv);
1008
1009         cv = waitForConnectivityBroadcasts(2);
1010         mWiFiNetworkAgent.disconnect();
1011         wifiNetworkCallback.expectCallback(CallbackState.LOST);
1012         cellNetworkCallback.assertNoCallback();
1013         waitFor(cv);
1014
1015         cv = waitForConnectivityBroadcasts(1);
1016         mCellNetworkAgent.disconnect();
1017         cellNetworkCallback.expectCallback(CallbackState.LOST);
1018         wifiNetworkCallback.assertNoCallback();
1019         waitFor(cv);
1020
1021         // Test validated networks
1022         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023         mCellNetworkAgent.connect(true);
1024         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1025         wifiNetworkCallback.assertNoCallback();
1026         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1027
1028         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1029         mCellNetworkAgent.adjustScore(-1);
1030         mService.waitForIdle();
1031         wifiNetworkCallback.assertNoCallback();
1032         cellNetworkCallback.assertNoCallback();
1033         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1034
1035         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1036         mWiFiNetworkAgent.connect(true);
1037         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1038         cellNetworkCallback.expectCallback(CallbackState.LOSING);
1039         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1040
1041         mWiFiNetworkAgent.disconnect();
1042         wifiNetworkCallback.expectCallback(CallbackState.LOST);
1043         cellNetworkCallback.assertNoCallback();
1044
1045         mCellNetworkAgent.disconnect();
1046         cellNetworkCallback.expectCallback(CallbackState.LOST);
1047         wifiNetworkCallback.assertNoCallback();
1048     }
1049
1050     private void tryNetworkFactoryRequests(int capability) throws Exception {
1051         // Verify NOT_RESTRICTED is set appropriately
1052         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1053                 .build().networkCapabilities;
1054         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1055                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1056                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1057                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1058             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1059         } else {
1060             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1061         }
1062
1063         NetworkCapabilities filter = new NetworkCapabilities();
1064         filter.addCapability(capability);
1065         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1066         handlerThread.start();
1067         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1068                 mServiceContext, "testFactory", filter);
1069         testFactory.setScoreFilter(40);
1070         ConditionVariable cv = testFactory.getNetworkStartedCV();
1071         testFactory.expectAddRequests(1);
1072         testFactory.register();
1073         testFactory.waitForNetworkRequests(1);
1074         int expectedRequestCount = 1;
1075         NetworkCallback networkCallback = null;
1076         // For non-INTERNET capabilities we cannot rely on the default request being present, so
1077         // add one.
1078         if (capability != NET_CAPABILITY_INTERNET) {
1079             assertFalse(testFactory.getMyStartRequested());
1080             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1081             networkCallback = new NetworkCallback();
1082             testFactory.expectAddRequests(1);
1083             mCm.requestNetwork(request, networkCallback);
1084             expectedRequestCount++;
1085             testFactory.waitForNetworkRequests(expectedRequestCount);
1086         }
1087         waitFor(cv);
1088         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1089         assertTrue(testFactory.getMyStartRequested());
1090
1091         // Now bring in a higher scored network.
1092         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1093         // Rather than create a validated network which complicates things by registering it's
1094         // own NetworkRequest during startup, just bump up the score to cancel out the
1095         // unvalidated penalty.
1096         testAgent.adjustScore(40);
1097         cv = testFactory.getNetworkStoppedCV();
1098
1099         // When testAgent connects, ConnectivityService will re-send us all current requests with
1100         // the new score. There are expectedRequestCount such requests, and we must wait for all of
1101         // them.
1102         testFactory.expectAddRequests(expectedRequestCount);
1103         testAgent.connect(false);
1104         testAgent.addCapability(capability);
1105         waitFor(cv);
1106         testFactory.waitForNetworkRequests(expectedRequestCount);
1107         assertFalse(testFactory.getMyStartRequested());
1108
1109         // Bring in a bunch of requests.
1110         testFactory.expectAddRequests(10);
1111         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1112         ConnectivityManager.NetworkCallback[] networkCallbacks =
1113                 new ConnectivityManager.NetworkCallback[10];
1114         for (int i = 0; i< networkCallbacks.length; i++) {
1115             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1116             NetworkRequest.Builder builder = new NetworkRequest.Builder();
1117             builder.addCapability(capability);
1118             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1119         }
1120         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1121         assertFalse(testFactory.getMyStartRequested());
1122
1123         // Remove the requests.
1124         testFactory.expectRemoveRequests(10);
1125         for (int i = 0; i < networkCallbacks.length; i++) {
1126             mCm.unregisterNetworkCallback(networkCallbacks[i]);
1127         }
1128         testFactory.waitForNetworkRequests(expectedRequestCount);
1129         assertFalse(testFactory.getMyStartRequested());
1130
1131         // Drop the higher scored network.
1132         cv = testFactory.getNetworkStartedCV();
1133         testAgent.disconnect();
1134         waitFor(cv);
1135         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1136         assertTrue(testFactory.getMyStartRequested());
1137
1138         testFactory.unregister();
1139         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1140         handlerThread.quit();
1141     }
1142
1143     @LargeTest
1144     public void testNetworkFactoryRequests() throws Exception {
1145         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1146         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1147         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1148         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1149         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1150         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1151         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1152         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1153         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1154         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1155         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1156         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1157         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1158         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1159         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1160         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1161     }
1162
1163     @LargeTest
1164     public void testNoMutableNetworkRequests() throws Exception {
1165         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1166         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1167         builder.addCapability(NET_CAPABILITY_VALIDATED);
1168         try {
1169             mCm.requestNetwork(builder.build(), new NetworkCallback());
1170             fail();
1171         } catch (IllegalArgumentException expected) {}
1172         try {
1173             mCm.requestNetwork(builder.build(), pendingIntent);
1174             fail();
1175         } catch (IllegalArgumentException expected) {}
1176         builder = new NetworkRequest.Builder();
1177         builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1178         try {
1179             mCm.requestNetwork(builder.build(), new NetworkCallback());
1180             fail();
1181         } catch (IllegalArgumentException expected) {}
1182         try {
1183             mCm.requestNetwork(builder.build(), pendingIntent);
1184             fail();
1185         } catch (IllegalArgumentException expected) {}
1186     }
1187
1188     @LargeTest
1189     public void testMMSonWiFi() throws Exception {
1190         // Test bringing up cellular without MMS NetworkRequest gets reaped
1191         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1192         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1193         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1194         mCellNetworkAgent.connectWithoutInternet();
1195         waitFor(cv);
1196         waitFor(new Criteria() {
1197                 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1198         verifyNoNetwork();
1199         // Test bringing up validated WiFi.
1200         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1201         cv = waitForConnectivityBroadcasts(1);
1202         mWiFiNetworkAgent.connect(true);
1203         waitFor(cv);
1204         verifyActiveNetwork(TRANSPORT_WIFI);
1205         // Register MMS NetworkRequest
1206         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1207         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1208         final TestNetworkCallback networkCallback = new TestNetworkCallback();
1209         mCm.requestNetwork(builder.build(), networkCallback);
1210         // Test bringing up unvalidated cellular with MMS
1211         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1212         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1213         mCellNetworkAgent.connectWithoutInternet();
1214         networkCallback.expectCallback(CallbackState.AVAILABLE);
1215         verifyActiveNetwork(TRANSPORT_WIFI);
1216         // Test releasing NetworkRequest disconnects cellular with MMS
1217         cv = mCellNetworkAgent.getDisconnectedCV();
1218         mCm.unregisterNetworkCallback(networkCallback);
1219         waitFor(cv);
1220         verifyActiveNetwork(TRANSPORT_WIFI);
1221     }
1222
1223     @LargeTest
1224     public void testMMSonCell() throws Exception {
1225         // Test bringing up cellular without MMS
1226         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1227         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1228         mCellNetworkAgent.connect(false);
1229         waitFor(cv);
1230         verifyActiveNetwork(TRANSPORT_CELLULAR);
1231         // Register MMS NetworkRequest
1232         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1233         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1234         final TestNetworkCallback networkCallback = new TestNetworkCallback();
1235         mCm.requestNetwork(builder.build(), networkCallback);
1236         // Test bringing up MMS cellular network
1237         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1238         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1239         mmsNetworkAgent.connectWithoutInternet();
1240         networkCallback.expectCallback(CallbackState.AVAILABLE);
1241         verifyActiveNetwork(TRANSPORT_CELLULAR);
1242         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1243         cv = mmsNetworkAgent.getDisconnectedCV();
1244         mCm.unregisterNetworkCallback(networkCallback);
1245         waitFor(cv);
1246         verifyActiveNetwork(TRANSPORT_CELLULAR);
1247     }
1248
1249     @LargeTest
1250     public void testCaptivePortal() {
1251         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1252         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1253                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1254         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1255
1256         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1257         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1258                 .addCapability(NET_CAPABILITY_VALIDATED).build();
1259         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1260
1261         // Bring up a network with a captive portal.
1262         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1263         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1264         mWiFiNetworkAgent.connectWithCaptivePortal();
1265         captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1266
1267         // Take down network.
1268         // Expect onLost callback.
1269         mWiFiNetworkAgent.disconnect();
1270         captivePortalCallback.expectCallback(CallbackState.LOST);
1271
1272         // Bring up a network with a captive portal.
1273         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1274         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1275         mWiFiNetworkAgent.connectWithCaptivePortal();
1276         captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1277
1278         // Make captive portal disappear then revalidate.
1279         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1280         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1281         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1282         captivePortalCallback.expectCallback(CallbackState.LOST);
1283
1284         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1285         validatedCallback.expectCallback(CallbackState.AVAILABLE);
1286
1287         // Break network connectivity.
1288         // Expect NET_CAPABILITY_VALIDATED onLost callback.
1289         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1290         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1291         validatedCallback.expectCallback(CallbackState.LOST);
1292     }
1293
1294     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
1295
1296         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
1297
1298         private class CallbackValue {
1299             public CallbackType callbackType;
1300             public int error;
1301
1302             public CallbackValue(CallbackType type) {
1303                 this.callbackType = type;
1304                 this.error = PacketKeepalive.SUCCESS;
1305                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
1306             }
1307
1308             public CallbackValue(CallbackType type, int error) {
1309                 this.callbackType = type;
1310                 this.error = error;
1311                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
1312             }
1313
1314             @Override
1315             public boolean equals(Object o) {
1316                 return o instanceof CallbackValue &&
1317                         this.callbackType == ((CallbackValue) o).callbackType &&
1318                         this.error == ((CallbackValue) o).error;
1319             }
1320
1321             @Override
1322             public String toString() {
1323                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
1324             }
1325         }
1326
1327         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
1328
1329         @Override
1330         public void onStarted() {
1331             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
1332         }
1333
1334         @Override
1335         public void onStopped() {
1336             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
1337         }
1338
1339         @Override
1340         public void onError(int error) {
1341             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
1342         }
1343
1344         private void expectCallback(CallbackValue callbackValue) {
1345             try {
1346                 assertEquals(
1347                         callbackValue,
1348                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1349             } catch (InterruptedException e) {
1350                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
1351             }
1352         }
1353
1354         public void expectStarted() {
1355             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
1356         }
1357
1358         public void expectStopped() {
1359             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
1360         }
1361
1362         public void expectError(int error) {
1363             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
1364         }
1365     }
1366
1367     private Network connectKeepaliveNetwork(LinkProperties lp) {
1368         // Ensure the network is disconnected before we do anything.
1369         if (mWiFiNetworkAgent != null) {
1370             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
1371         }
1372
1373         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1374         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1375         mWiFiNetworkAgent.connect(true);
1376         waitFor(cv);
1377         verifyActiveNetwork(TRANSPORT_WIFI);
1378         mWiFiNetworkAgent.sendLinkProperties(lp);
1379         mService.waitForIdle();
1380         return mWiFiNetworkAgent.getNetwork();
1381     }
1382
1383     public void testPacketKeepalives() throws Exception {
1384         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
1385         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
1386         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
1387         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
1388         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
1389
1390         LinkProperties lp = new LinkProperties();
1391         lp.setInterfaceName("wlan12");
1392         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
1393         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
1394         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
1395         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
1396
1397         Network notMyNet = new Network(61234);
1398         Network myNet = connectKeepaliveNetwork(lp);
1399
1400         TestKeepaliveCallback callback = new TestKeepaliveCallback();
1401         PacketKeepalive ka;
1402
1403         // Attempt to start keepalives with invalid parameters and check for errors.
1404         ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
1405         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1406
1407         ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
1408         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
1409
1410         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
1411         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1412
1413         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
1414         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1415
1416         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
1417         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);  // NAT-T is IPv4-only.
1418
1419         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1420         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1421
1422         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1423         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1424
1425         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1426         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1427
1428         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1429         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1430
1431         // Check that a started keepalive can be stopped.
1432         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1433         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1434         callback.expectStarted();
1435         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
1436         ka.stop();
1437         callback.expectStopped();
1438
1439         // Check that deleting the IP address stops the keepalive.
1440         LinkProperties bogusLp = new LinkProperties(lp);
1441         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1442         callback.expectStarted();
1443         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
1444         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
1445         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
1446         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1447         mWiFiNetworkAgent.sendLinkProperties(lp);
1448
1449         // Check that a started keepalive is stopped correctly when the network disconnects.
1450         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1451         callback.expectStarted();
1452         mWiFiNetworkAgent.disconnect();
1453         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1454
1455         // ... and that stopping it after that has no adverse effects.
1456         assertNull(mCm.getNetworkCapabilities(myNet));
1457         ka.stop();
1458
1459         // Reconnect.
1460         myNet = connectKeepaliveNetwork(lp);
1461         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1462
1463         // Check things work as expected when the keepalive is stopped and the network disconnects.
1464         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1465         callback.expectStarted();
1466         ka.stop();
1467         mWiFiNetworkAgent.disconnect();
1468         mService.waitForIdle();
1469         callback.expectStopped();
1470
1471         // Reconnect.
1472         myNet = connectKeepaliveNetwork(lp);
1473         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1474
1475         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
1476         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1477         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1478         callback.expectStarted();
1479
1480         // The second one gets slot 2.
1481         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
1482         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
1483         PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
1484         callback2.expectStarted();
1485
1486         // Now stop the first one and create a third. This also gets slot 1.
1487         ka.stop();
1488         callback.expectStopped();
1489
1490         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1491         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
1492         PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
1493         callback3.expectStarted();
1494
1495         ka2.stop();
1496         callback2.expectStopped();
1497
1498         ka3.stop();
1499         callback3.expectStopped();
1500     }
1501 }