diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java deleted file mode 100644 index f95a8c6de5..0000000000 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ /dev/null @@ -1,2791 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.ConnectivityManager.getNetworkTypeName; -import static android.net.NetworkCapabilities.*; - -import static org.mockito.Mockito.mock; - -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.ConnectivityManager.PacketKeepalive; -import android.net.ConnectivityManager.PacketKeepaliveCallback; -import android.net.INetworkPolicyManager; -import android.net.INetworkStatsService; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkCapabilities; -import android.net.NetworkConfig; -import android.net.NetworkFactory; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkMisc; -import android.net.NetworkRequest; -import android.net.RouteInfo; -import android.net.metrics.IpConnectivityLog; -import android.net.util.AvoidBadWifiTracker; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.INetworkManagementService; -import android.os.Looper; -import android.os.Message; -import android.os.MessageQueue; -import android.os.Messenger; -import android.os.MessageQueue.IdleHandler; -import android.os.Process; -import android.os.SystemClock; -import android.provider.Settings; -import android.test.AndroidTestCase; -import android.test.FlakyTest; -import android.test.mock.MockContentResolver; -import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; -import android.util.LogPrinter; - -import com.android.internal.util.WakeupMessage; -import com.android.internal.util.test.BroadcastInterceptingContext; -import com.android.internal.util.test.FakeSettingsProvider; -import com.android.server.connectivity.NetworkAgentInfo; -import com.android.server.connectivity.NetworkMonitor; -import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; -import com.android.server.net.NetworkPinner; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Objects; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Tests for {@link ConnectivityService}. - * - * Build, install and run with: - * runtest frameworks-services -c com.android.server.ConnectivityServiceTest - */ -public class ConnectivityServiceTest extends AndroidTestCase { - private static final String TAG = "ConnectivityServiceTest"; - - private static final int TIMEOUT_MS = 500; - private static final int TEST_LINGER_DELAY_MS = 120; - - private BroadcastInterceptingContext mServiceContext; - private WrappedConnectivityService mService; - private WrappedConnectivityManager mCm; - private MockNetworkAgent mWiFiNetworkAgent; - private MockNetworkAgent mCellNetworkAgent; - private MockNetworkAgent mEthernetNetworkAgent; - - // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods - // do not go through ConnectivityService but talk to netd directly, so they don't automatically - // reflect the state of our test ConnectivityService. - private class WrappedConnectivityManager extends ConnectivityManager { - private Network mFakeBoundNetwork; - - public synchronized boolean bindProcessToNetwork(Network network) { - mFakeBoundNetwork = network; - return true; - } - - public synchronized Network getBoundNetworkForProcess() { - return mFakeBoundNetwork; - } - - public WrappedConnectivityManager(Context context, ConnectivityService service) { - super(context, service); - } - } - - private class MockContext extends BroadcastInterceptingContext { - private final MockContentResolver mContentResolver; - - MockContext(Context base) { - super(base); - mContentResolver = new MockContentResolver(); - mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); - } - - @Override - public Object getSystemService(String name) { - if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; - if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class); - return super.getSystemService(name); - } - - @Override - public ContentResolver getContentResolver() { - return mContentResolver; - } - } - - /** - * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle - * will return immediately if the handler is already idle. - */ - private class IdleableHandlerThread extends HandlerThread { - private IdleHandler mIdleHandler; - - public IdleableHandlerThread(String name) { - super(name); - } - - public void waitForIdle(int timeoutMs) { - final ConditionVariable cv = new ConditionVariable(); - final MessageQueue queue = getLooper().getQueue(); - - synchronized (queue) { - if (queue.isIdle()) { - return; - } - - assertNull("BUG: only one idle handler allowed", mIdleHandler); - mIdleHandler = new IdleHandler() { - public boolean queueIdle() { - synchronized (queue) { - cv.open(); - mIdleHandler = null; - return false; // Remove the handler. - } - } - }; - queue.addIdleHandler(mIdleHandler); - } - - if (!cv.block(timeoutMs)) { - fail("HandlerThread " + getName() + - " did not become idle after " + timeoutMs + " ms"); - queue.removeIdleHandler(mIdleHandler); - } - } - } - - // Tests that IdleableHandlerThread works as expected. - public void testIdleableHandlerThread() { - final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. - - // Tests that waitForIdle returns immediately if the service is already idle. - for (int i = 0; i < attempts; i++) { - mService.waitForIdle(); - } - - // Bring up a network that we can use to send messages to ConnectivityService. - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - waitFor(cv); - Network n = mWiFiNetworkAgent.getNetwork(); - assertNotNull(n); - - // Tests that calling waitForIdle waits for messages to be processed. - for (int i = 0; i < attempts; i++) { - mWiFiNetworkAgent.setSignalStrength(i); - mService.waitForIdle(); - assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); - } - } - - @FlakyTest(tolerance = 3) - public void testNotWaitingForIdleCausesRaceConditions() { - // Bring up a network that we can use to send messages to ConnectivityService. - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - waitFor(cv); - Network n = mWiFiNetworkAgent.getNetwork(); - assertNotNull(n); - - // Ensure that not calling waitForIdle causes a race condition. - final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. - for (int i = 0; i < attempts; i++) { - mWiFiNetworkAgent.setSignalStrength(i); - if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { - // We hit a race condition, as expected. Pass the test. - return; - } - } - - // No race? There is a bug in this test. - fail("expected race condition at least once in " + attempts + " attempts"); - } - - private class MockNetworkAgent { - private final WrappedNetworkMonitor mWrappedNetworkMonitor; - private final NetworkInfo mNetworkInfo; - private final NetworkCapabilities mNetworkCapabilities; - private final IdleableHandlerThread mHandlerThread; - private final ConditionVariable mDisconnected = new ConditionVariable(); - private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); - private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); - private int mScore; - private NetworkAgent mNetworkAgent; - private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED; - private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE; - private Integer mExpectedKeepaliveSlot = null; - // Contains the redirectUrl from networkStatus(). Before reading, wait for - // mNetworkStatusReceived. - private String mRedirectUrl; - - MockNetworkAgent(int transport) { - final int type = transportToLegacyType(transport); - final String typeName = ConnectivityManager.getNetworkTypeName(type); - mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); - mNetworkCapabilities = new NetworkCapabilities(); - mNetworkCapabilities.addTransportType(transport); - switch (transport) { - case TRANSPORT_ETHERNET: - mScore = 70; - break; - case TRANSPORT_WIFI: - mScore = 60; - break; - case TRANSPORT_CELLULAR: - mScore = 50; - break; - default: - throw new UnsupportedOperationException("unimplemented network type"); - } - mHandlerThread = new IdleableHandlerThread("Mock-" + typeName); - mHandlerThread.start(); - mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, - "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, - new LinkProperties(), mScore, new NetworkMisc()) { - @Override - public void unwanted() { mDisconnected.open(); } - - @Override - public void startPacketKeepalive(Message msg) { - int slot = msg.arg1; - if (mExpectedKeepaliveSlot != null) { - assertEquals((int) mExpectedKeepaliveSlot, slot); - } - onPacketKeepaliveEvent(slot, mStartKeepaliveError); - } - - @Override - public void stopPacketKeepalive(Message msg) { - onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); - } - - @Override - public void networkStatus(int status, String redirectUrl) { - mRedirectUrl = redirectUrl; - mNetworkStatusReceived.open(); - } - - @Override - protected void preventAutomaticReconnect() { - mPreventReconnectReceived.open(); - } - }; - // Waits for the NetworkAgent to be registered, which includes the creation of the - // NetworkMonitor. - mService.waitForIdle(); - mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor(); - } - - public void waitForIdle(int timeoutMs) { - mHandlerThread.waitForIdle(timeoutMs); - } - - public void waitForIdle() { - waitForIdle(TIMEOUT_MS); - } - - public void adjustScore(int change) { - mScore += change; - mNetworkAgent.sendNetworkScore(mScore); - } - - public void addCapability(int capability) { - mNetworkCapabilities.addCapability(capability); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void removeCapability(int capability) { - mNetworkCapabilities.removeCapability(capability); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void setSignalStrength(int signalStrength) { - mNetworkCapabilities.setSignalStrength(signalStrength); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void connectWithoutInternet() { - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); - } - - /** - * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. - * @param validated Indicate if network should pretend to be validated. - */ - public void connect(boolean validated) { - assertEquals("MockNetworkAgents can only be connected once", - mNetworkInfo.getDetailedState(), DetailedState.IDLE); - assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)); - - NetworkCallback callback = null; - final ConditionVariable validatedCv = new ConditionVariable(); - if (validated) { - mWrappedNetworkMonitor.gen204ProbeResult = 204; - NetworkRequest request = new NetworkRequest.Builder() - .addTransportType(mNetworkCapabilities.getTransportTypes()[0]) - .build(); - callback = new NetworkCallback() { - public void onCapabilitiesChanged(Network network, - NetworkCapabilities networkCapabilities) { - if (network.equals(getNetwork()) && - networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { - validatedCv.open(); - } - } - }; - mCm.registerNetworkCallback(request, callback); - } - addCapability(NET_CAPABILITY_INTERNET); - - connectWithoutInternet(); - - if (validated) { - // Wait for network to validate. - waitFor(validatedCv); - mWrappedNetworkMonitor.gen204ProbeResult = 500; - } - - if (callback != null) mCm.unregisterNetworkCallback(callback); - } - - public void connectWithCaptivePortal(String redirectUrl) { - mWrappedNetworkMonitor.gen204ProbeResult = 200; - mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl; - connect(false); - } - - public void disconnect() { - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); - } - - public Network getNetwork() { - return new Network(mNetworkAgent.netId); - } - - public ConditionVariable getPreventReconnectReceived() { - return mPreventReconnectReceived; - } - - public ConditionVariable getDisconnectedCV() { - return mDisconnected; - } - - public WrappedNetworkMonitor getWrappedNetworkMonitor() { - return mWrappedNetworkMonitor; - } - - public void sendLinkProperties(LinkProperties lp) { - mNetworkAgent.sendLinkProperties(lp); - } - - public void setStartKeepaliveError(int error) { - mStartKeepaliveError = error; - } - - public void setStopKeepaliveError(int error) { - mStopKeepaliveError = error; - } - - public void setExpectedKeepaliveSlot(Integer slot) { - mExpectedKeepaliveSlot = slot; - } - - public String waitForRedirectUrl() { - assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); - return mRedirectUrl; - } - } - - /** - * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove - * operations have been processed. Before ConnectivityService can add or remove any requests, - * the factory must be told to expect those operations by calling expectAddRequests or - * expectRemoveRequests. - */ - private static class MockNetworkFactory extends NetworkFactory { - private final ConditionVariable mNetworkStartedCV = new ConditionVariable(); - private final ConditionVariable mNetworkStoppedCV = new ConditionVariable(); - private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); - - // Used to expect that requests be removed or added on a separate thread, without sleeping. - // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then - // cause some other thread to add or remove requests, then call waitForRequests(). We can - // either expect requests to be added or removed, but not both, because CountDownLatch can - // only count in one direction. - private CountDownLatch mExpectations; - - // Whether we are currently expecting requests to be added or removed. Valid only if - // mExpectations is non-null. - private boolean mExpectingAdditions; - - public MockNetworkFactory(Looper looper, Context context, String logTag, - NetworkCapabilities filter) { - super(looper, context, logTag, filter); - } - - public int getMyRequestCount() { - return getRequestCount(); - } - - protected void startNetwork() { - mNetworkStarted.set(true); - mNetworkStartedCV.open(); - } - - protected void stopNetwork() { - mNetworkStarted.set(false); - mNetworkStoppedCV.open(); - } - - public boolean getMyStartRequested() { - return mNetworkStarted.get(); - } - - public ConditionVariable getNetworkStartedCV() { - mNetworkStartedCV.close(); - return mNetworkStartedCV; - } - - public ConditionVariable getNetworkStoppedCV() { - mNetworkStoppedCV.close(); - return mNetworkStoppedCV; - } - - @Override - protected void handleAddRequest(NetworkRequest request, int score) { - // If we're expecting anything, we must be expecting additions. - if (mExpectations != null && !mExpectingAdditions) { - fail("Can't add requests while expecting requests to be removed"); - } - - // Add the request. - super.handleAddRequest(request, score); - - // Reduce the number of request additions we're waiting for. - if (mExpectingAdditions) { - assertTrue("Added more requests than expected", mExpectations.getCount() > 0); - mExpectations.countDown(); - } - } - - @Override - protected void handleRemoveRequest(NetworkRequest request) { - // If we're expecting anything, we must be expecting removals. - if (mExpectations != null && mExpectingAdditions) { - fail("Can't remove requests while expecting requests to be added"); - } - - // Remove the request. - super.handleRemoveRequest(request); - - // Reduce the number of request removals we're waiting for. - if (!mExpectingAdditions) { - assertTrue("Removed more requests than expected", mExpectations.getCount() > 0); - mExpectations.countDown(); - } - } - - private void assertNoExpectations() { - if (mExpectations != null) { - fail("Can't add expectation, " + mExpectations.getCount() + " already pending"); - } - } - - // Expects that count requests will be added. - public void expectAddRequests(final int count) { - assertNoExpectations(); - mExpectingAdditions = true; - mExpectations = new CountDownLatch(count); - } - - // Expects that count requests will be removed. - public void expectRemoveRequests(final int count) { - assertNoExpectations(); - mExpectingAdditions = false; - mExpectations = new CountDownLatch(count); - } - - // Waits for the expected request additions or removals to happen within a timeout. - public void waitForRequests() throws InterruptedException { - assertNotNull("Nothing to wait for", mExpectations); - mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); - final long count = mExpectations.getCount(); - final String msg = count + " requests still not " + - (mExpectingAdditions ? "added" : "removed") + - " after " + TIMEOUT_MS + " ms"; - assertEquals(msg, 0, count); - mExpectations = null; - } - - public void waitForNetworkRequests(final int count) throws InterruptedException { - waitForRequests(); - assertEquals(count, getMyRequestCount()); - } - } - - private class FakeWakeupMessage extends WakeupMessage { - private static final int UNREASONABLY_LONG_WAIT = 1000; - - public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) { - super(context, handler, cmdName, cmd); - } - - public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, - int arg1, int arg2, Object obj) { - super(context, handler, cmdName, cmd, arg1, arg2, obj); - } - - @Override - public void schedule(long when) { - long delayMs = when - SystemClock.elapsedRealtime(); - if (delayMs < 0) delayMs = 0; - if (delayMs > UNREASONABLY_LONG_WAIT) { - fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT + - "ms into the future: " + delayMs); - } - Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); - mHandler.sendMessageDelayed(msg, delayMs); - } - - @Override - public void cancel() { - mHandler.removeMessages(mCmd, mObj); - } - - @Override - public void onAlarm() { - throw new AssertionError("Should never happen. Update this fake."); - } - } - - // NetworkMonitor implementation allowing overriding of Internet connectivity probe result. - private class WrappedNetworkMonitor extends NetworkMonitor { - // HTTP response code fed back to NetworkMonitor for Internet connectivity probe. - public int gen204ProbeResult = 500; - public String gen204ProbeRedirectUrl = null; - - public WrappedNetworkMonitor(Context context, Handler handler, - NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest, - IpConnectivityLog log) { - super(context, handler, networkAgentInfo, defaultRequest, log); - } - - @Override - protected CaptivePortalProbeResult isCaptivePortal() { - if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); } - return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null); - } - } - - private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker { - public boolean configRestrictsAvoidBadWifi; - - public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) { - super(c, h, r); - } - - @Override - public boolean configRestrictsAvoidBadWifi() { - return configRestrictsAvoidBadWifi; - } - } - - private class WrappedConnectivityService extends ConnectivityService { - public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker; - private WrappedNetworkMonitor mLastCreatedNetworkMonitor; - - public WrappedConnectivityService(Context context, INetworkManagementService netManager, - INetworkStatsService statsService, INetworkPolicyManager policyManager, - IpConnectivityLog log) { - super(context, netManager, statsService, policyManager, log); - mLingerDelayMs = TEST_LINGER_DELAY_MS; - } - - @Override - protected HandlerThread createHandlerThread() { - return new IdleableHandlerThread("WrappedConnectivityService"); - } - - @Override - protected int getDefaultTcpRwnd() { - // Prevent wrapped ConnectivityService from trying to write to SystemProperties. - return 0; - } - - @Override - protected int reserveNetId() { - while (true) { - final int netId = super.reserveNetId(); - - // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks - // can have odd side-effects, like network validations succeeding. - final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks(); - boolean overlaps = false; - for (Network network : networks) { - if (netId == network.netId) { - overlaps = true; - break; - } - } - if (overlaps) continue; - - return netId; - } - } - - @Override - public NetworkMonitor createNetworkMonitor(Context context, Handler handler, - NetworkAgentInfo nai, NetworkRequest defaultRequest) { - final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor( - context, handler, nai, defaultRequest, mock(IpConnectivityLog.class)); - mLastCreatedNetworkMonitor = monitor; - return monitor; - } - - @Override - public AvoidBadWifiTracker createAvoidBadWifiTracker( - Context c, Handler h, Runnable r) { - final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r); - return tracker; - } - - public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() { - return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker; - } - - @Override - public WakeupMessage makeWakeupMessage( - Context context, Handler handler, String cmdName, int cmd, Object obj) { - return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj); - } - - public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { - return mLastCreatedNetworkMonitor; - } - - public void waitForIdle(int timeoutMs) { - ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs); - } - - public void waitForIdle() { - waitForIdle(TIMEOUT_MS); - } - } - - private interface Criteria { - public boolean get(); - } - - /** - * Wait up to 500ms for {@code criteria.get()} to become true, polling. - * Fails if 500ms goes by before {@code criteria.get()} to become true. - */ - static private void waitFor(Criteria criteria) { - int delays = 0; - while (!criteria.get()) { - try { - Thread.sleep(50); - } catch (InterruptedException e) { - } - if (++delays == 10) fail(); - } - } - - /** - * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. - * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. - */ - static private void waitFor(ConditionVariable conditionVariable) { - assertTrue(conditionVariable.block(TIMEOUT_MS)); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. - // http://b/25897652 . - if (Looper.myLooper() == null) { - Looper.prepare(); - } - - mServiceContext = new MockContext(getContext()); - mService = new WrappedConnectivityService(mServiceContext, - mock(INetworkManagementService.class), - mock(INetworkStatsService.class), - mock(INetworkPolicyManager.class), - mock(IpConnectivityLog.class)); - - mService.systemReady(); - mCm = new WrappedConnectivityManager(getContext(), mService); - mCm.bindProcessToNetwork(null); - - // Ensure that the default setting for Captive Portals is used for most tests - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); - } - - public void tearDown() throws Exception { - setMobileDataAlwaysOn(false); - if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); } - if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); } - mCellNetworkAgent = mWiFiNetworkAgent = null; - super.tearDown(); - } - - private int transportToLegacyType(int transport) { - switch (transport) { - case TRANSPORT_ETHERNET: - return TYPE_ETHERNET; - case TRANSPORT_WIFI: - return TYPE_WIFI; - case TRANSPORT_CELLULAR: - return TYPE_MOBILE; - default: - throw new IllegalStateException("Unknown transport " + transport); - } - } - - private void verifyActiveNetwork(int transport) { - // Test getActiveNetworkInfo() - assertNotNull(mCm.getActiveNetworkInfo()); - assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); - // Test getActiveNetwork() - assertNotNull(mCm.getActiveNetwork()); - assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid())); - switch (transport) { - case TRANSPORT_WIFI: - assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); - break; - case TRANSPORT_CELLULAR: - assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); - break; - default: - throw new IllegalStateException("Unknown transport" + transport); - } - // Test getNetworkInfo(Network) - assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); - assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); - // Test getNetworkCapabilities(Network) - assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); - assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); - } - - private void verifyNoNetwork() { - // Test getActiveNetworkInfo() - assertNull(mCm.getActiveNetworkInfo()); - // Test getActiveNetwork() - assertNull(mCm.getActiveNetwork()); - assertNull(mCm.getActiveNetworkForUid(Process.myUid())); - // Test getAllNetworks() - assertEquals(0, mCm.getAllNetworks().length); - } - - /** - * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION - * broadcasts are received. - */ - private ConditionVariable waitForConnectivityBroadcasts(final int count) { - final ConditionVariable cv = new ConditionVariable(); - mServiceContext.registerReceiver(new BroadcastReceiver() { - private int remaining = count; - public void onReceive(Context context, Intent intent) { - if (--remaining == 0) { - cv.open(); - mServiceContext.unregisterReceiver(this); - } - } - }, new IntentFilter(CONNECTIVITY_ACTION)); - return cv; - } - - @LargeTest - public void testLingering() throws Exception { - verifyNoNetwork(); - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - assertNull(mCm.getActiveNetworkInfo()); - assertNull(mCm.getActiveNetwork()); - // Test bringing up validated cellular. - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - assertEquals(2, mCm.getAllNetworks().length); - assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || - mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); - assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || - mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); - // Test bringing up validated WiFi. - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - assertEquals(2, mCm.getAllNetworks().length); - assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || - mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); - assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || - mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); - // Test cellular linger timeout. - waitFor(new Criteria() { - public boolean get() { return mCm.getAllNetworks().length == 1; } }); - verifyActiveNetwork(TRANSPORT_WIFI); - assertEquals(1, mCm.getAllNetworks().length); - assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); - // Test WiFi disconnect. - cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.disconnect(); - waitFor(cv); - verifyNoNetwork(); - } - - @LargeTest - public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { - // Test bringing up unvalidated WiFi - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up unvalidated cellular - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); - mService.waitForIdle(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test cellular disconnect. - mCellNetworkAgent.disconnect(); - mService.waitForIdle(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up validated cellular - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - cv = waitForConnectivityBroadcasts(2); - mCellNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test cellular disconnect. - cv = waitForConnectivityBroadcasts(2); - mCellNetworkAgent.disconnect(); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test WiFi disconnect. - cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.disconnect(); - waitFor(cv); - verifyNoNetwork(); - } - - @LargeTest - public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { - // Test bringing up unvalidated cellular. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test bringing up unvalidated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test WiFi disconnect. - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.disconnect(); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test cellular disconnect. - cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.disconnect(); - waitFor(cv); - verifyNoNetwork(); - } - - @LargeTest - public void testUnlingeringDoesNotValidate() throws Exception { - // Test bringing up unvalidated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - // Test bringing up validated cellular. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - cv = waitForConnectivityBroadcasts(2); - mCellNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - // Test cellular disconnect. - cv = waitForConnectivityBroadcasts(2); - mCellNetworkAgent.disconnect(); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Unlingering a network should not cause it to be marked as validated. - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - } - - @LargeTest - public void testCellularOutscoresWeakWifi() throws Exception { - // Test bringing up validated cellular. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test WiFi getting really weak. - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.adjustScore(-11); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test WiFi restoring signal strength. - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.adjustScore(11); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @LargeTest - public void testReapingNetwork() throws Exception { - // Test bringing up WiFi without NET_CAPABILITY_INTERNET. - // Expect it to be torn down immediately because it satisfies no requests. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV(); - mWiFiNetworkAgent.connectWithoutInternet(); - waitFor(cv); - // Test bringing up cellular without NET_CAPABILITY_INTERNET. - // Expect it to be torn down immediately because it satisfies no requests. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - cv = mCellNetworkAgent.getDisconnectedCV(); - mCellNetworkAgent.connectWithoutInternet(); - waitFor(cv); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up unvalidated cellular. - // Expect it to be torn down because it could never be the highest scoring network - // satisfying the default request even if it validated. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - cv = mCellNetworkAgent.getDisconnectedCV(); - mCellNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - cv = mWiFiNetworkAgent.getDisconnectedCV(); - mWiFiNetworkAgent.disconnect(); - waitFor(cv); - } - - @LargeTest - public void testCellularFallback() throws Exception { - // Test bringing up validated cellular. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Reevaluate WiFi (it'll instantly fail DNS). - cv = waitForConnectivityBroadcasts(2); - assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); - // Should quickly fall back to Cellular. - waitFor(cv); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Reevaluate cellular (it'll instantly fail DNS). - cv = waitForConnectivityBroadcasts(2); - assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); - // Should quickly fall back to WiFi. - waitFor(cv); - assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @LargeTest - public void testWiFiFallback() throws Exception { - // Test bringing up unvalidated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up validated cellular. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - cv = waitForConnectivityBroadcasts(2); - mCellNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Reevaluate cellular (it'll instantly fail DNS). - cv = waitForConnectivityBroadcasts(2); - assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); - // Should quickly fall back to WiFi. - waitFor(cv); - assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - enum CallbackState { - NONE, - AVAILABLE, - NETWORK_CAPABILITIES, - LINK_PROPERTIES, - LOSING, - LOST, - UNAVAILABLE - } - - private static class CallbackInfo { - public final CallbackState state; - public final Network network; - public final Object arg; - public CallbackInfo(CallbackState s, Network n, Object o) { - state = s; network = n; arg = o; - } - public String toString() { - return String.format("%s (%s)", state, network); - } - @Override - public boolean equals(Object o) { - if (!(o instanceof CallbackInfo)) return false; - // Ignore timeMs, since it's unpredictable. - CallbackInfo other = (CallbackInfo) o; - return (state == other.state) && Objects.equals(network, other.network); - } - @Override - public int hashCode() { - return Objects.hash(state, network); - } - } - - /** - * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks - * this class receives, by calling expectCallback() exactly once each time a callback is - * received. assertNoCallback may be called at any time. - */ - private class TestNetworkCallback extends NetworkCallback { - // Chosen to be much less than the linger timeout. This ensures that we can distinguish - // between a LOST callback that arrives immediately and a LOST callback that arrives after - // the linger timeout. - private final static int TIMEOUT_MS = 50; - - private final LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); - - protected void setLastCallback(CallbackState state, Network network, Object o) { - mCallbacks.offer(new CallbackInfo(state, network, o)); - } - - @Override - public void onAvailable(Network network) { - setLastCallback(CallbackState.AVAILABLE, network, null); - } - - @Override - public void onUnavailable() { - setLastCallback(CallbackState.UNAVAILABLE, null, null); - } - - @Override - public void onLosing(Network network, int maxMsToLive) { - setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */); - } - - @Override - public void onLost(Network network) { - setLastCallback(CallbackState.LOST, network, null); - } - - CallbackInfo nextCallback(int timeoutMs) { - CallbackInfo cb = null; - try { - cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - } - if (cb == null) { - // LinkedBlockingQueue.poll() returns null if it timeouts. - fail("Did not receive callback after " + timeoutMs + "ms"); - } - return cb; - } - - void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) { - CallbackInfo expected = new CallbackInfo( - state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0); - CallbackInfo actual = nextCallback(timeoutMs); - assertEquals("Unexpected callback:", expected, actual); - if (state == CallbackState.LOSING) { - String msg = String.format( - "Invalid linger time value %d, must be between %d and %d", - actual.arg, 0, TEST_LINGER_DELAY_MS); - int maxMsToLive = (Integer) actual.arg; - assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS); - } - } - - void expectCallback(CallbackState state, MockNetworkAgent mockAgent) { - expectCallback(state, mockAgent, TIMEOUT_MS); - } - - void assertNoCallback() { - mService.waitForIdle(); - CallbackInfo c = mCallbacks.peek(); - assertNull("Unexpected callback: " + c, c); - } - } - - // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can - // only be declared in a static or top level type". - static void assertNoCallbacks(TestNetworkCallback ... callbacks) { - for (TestNetworkCallback c : callbacks) { - c.assertNoCallback(); - } - } - - @LargeTest - public void testStateChangeNetworkCallbacks() throws Exception { - final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest genericRequest = new NetworkRequest.Builder() - .clearCapabilities().build(); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); - mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); - mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); - - // Test unvalidated networks - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); - genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - waitFor(cv); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - // This should not trigger spurious onAvailable() callbacks, b/21762680. - mCellNetworkAgent.adjustScore(-1); - mService.waitForIdle(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - waitFor(cv); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - cv = waitForConnectivityBroadcasts(2); - mWiFiNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - cellNetworkCallback.assertNoCallback(); - waitFor(cv); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - waitFor(cv); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - // Test validated networks - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - // This should not trigger spurious onAvailable() callbacks, b/21762680. - mCellNetworkAgent.adjustScore(-1); - mService.waitForIdle(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - mWiFiNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - mCellNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - } - - @SmallTest - public void testMultipleLingering() { - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED) - .build(); - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); - - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - - mCellNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent.connect(true); - // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request. - // We then get LOSING when wifi validates and cell is outscored. - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mEthernetNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent); - callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent); - assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mEthernetNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - - for (int i = 0; i < 4; i++) { - MockNetworkAgent oldNetwork, newNetwork; - if (i % 2 == 0) { - mWiFiNetworkAgent.adjustScore(-15); - oldNetwork = mWiFiNetworkAgent; - newNetwork = mCellNetworkAgent; - } else { - mWiFiNetworkAgent.adjustScore(15); - oldNetwork = mCellNetworkAgent; - newNetwork = mWiFiNetworkAgent; - - } - callback.expectCallback(CallbackState.LOSING, oldNetwork); - // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no - // longer lingering? - defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork); - assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork()); - } - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even - // if the network is still up. - mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - // Wifi no longer satisfies our listen, which is for an unmetered network. - // But because its score is 55, it's still up (and the default network). - defaultCallback.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Disconnect our test networks. - mWiFiNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - mCellNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - - mCm.unregisterNetworkCallback(callback); - mService.waitForIdle(); - - // Check that a network is only lingered or torn down if it would not satisfy a request even - // if it validated. - request = new NetworkRequest.Builder().clearCapabilities().build(); - callback = new TestNetworkCallback(); - - mCm.registerNetworkCallback(request, callback); - - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); // Score: 10 - callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Bring up wifi with a score of 20. - // Cell stays up because it would satisfy the default request if it validated. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); // Score: 20 - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Bring up wifi with a score of 70. - // Cell is lingered because it would not satisfy any request, even if it validated. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.adjustScore(50); - mWiFiNetworkAgent.connect(false); // Score: 70 - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Tear down wifi. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but - // it's arguably correct to linger it, since it was the default network before it validated. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - mCellNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - - // If a network is lingering, and we add and remove a request from it, resume lingering. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - - NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - NetworkCallback noopCallback = new NetworkCallback(); - mCm.requestNetwork(cellRequest, noopCallback); - // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer - // lingering? - mCm.unregisterNetworkCallback(noopCallback); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - - // Similar to the above: lingering can start even after the lingered request is removed. - // Disconnect wifi and switch to cell. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - - // Cell is now the default network. Pin it with a cell-specific request. - noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525 - mCm.requestNetwork(cellRequest, noopCallback); - - // Now connect wifi, and expect it to become the default network. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - // The default request is lingering on cell, but nothing happens to cell, and we send no - // callbacks for it, because it's kept up by cellRequest. - callback.assertNoCallback(); - // Now unregister cellRequest and expect cell to start lingering. - mCm.unregisterNetworkCallback(noopCallback); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - - // Let linger run its course. - callback.assertNoCallback(); - callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, - TEST_LINGER_DELAY_MS /* timeoutMs */); - - // Clean up. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - mCm.unregisterNetworkCallback(callback); - mCm.unregisterNetworkCallback(defaultCallback); - } - - private void tryNetworkFactoryRequests(int capability) throws Exception { - // Verify NOT_RESTRICTED is set appropriately - final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) - .build().networkCapabilities; - if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || - capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || - capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || - capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - } else { - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - } - - NetworkCapabilities filter = new NetworkCapabilities(); - filter.addCapability(capability); - final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); - handlerThread.start(); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); - testFactory.setScoreFilter(40); - ConditionVariable cv = testFactory.getNetworkStartedCV(); - testFactory.expectAddRequests(1); - testFactory.register(); - testFactory.waitForNetworkRequests(1); - int expectedRequestCount = 1; - NetworkCallback networkCallback = null; - // For non-INTERNET capabilities we cannot rely on the default request being present, so - // add one. - if (capability != NET_CAPABILITY_INTERNET) { - assertFalse(testFactory.getMyStartRequested()); - NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); - networkCallback = new NetworkCallback(); - testFactory.expectAddRequests(1); - mCm.requestNetwork(request, networkCallback); - expectedRequestCount++; - testFactory.waitForNetworkRequests(expectedRequestCount); - } - waitFor(cv); - assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); - assertTrue(testFactory.getMyStartRequested()); - - // Now bring in a higher scored network. - MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - // Rather than create a validated network which complicates things by registering it's - // own NetworkRequest during startup, just bump up the score to cancel out the - // unvalidated penalty. - testAgent.adjustScore(40); - cv = testFactory.getNetworkStoppedCV(); - - // When testAgent connects, ConnectivityService will re-send us all current requests with - // the new score. There are expectedRequestCount such requests, and we must wait for all of - // them. - testFactory.expectAddRequests(expectedRequestCount); - testAgent.connect(false); - testAgent.addCapability(capability); - waitFor(cv); - testFactory.waitForNetworkRequests(expectedRequestCount); - assertFalse(testFactory.getMyStartRequested()); - - // Bring in a bunch of requests. - testFactory.expectAddRequests(10); - assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); - ConnectivityManager.NetworkCallback[] networkCallbacks = - new ConnectivityManager.NetworkCallback[10]; - for (int i = 0; i< networkCallbacks.length; i++) { - networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(capability); - mCm.requestNetwork(builder.build(), networkCallbacks[i]); - } - testFactory.waitForNetworkRequests(10 + expectedRequestCount); - assertFalse(testFactory.getMyStartRequested()); - - // Remove the requests. - testFactory.expectRemoveRequests(10); - for (int i = 0; i < networkCallbacks.length; i++) { - mCm.unregisterNetworkCallback(networkCallbacks[i]); - } - testFactory.waitForNetworkRequests(expectedRequestCount); - assertFalse(testFactory.getMyStartRequested()); - - // Drop the higher scored network. - cv = testFactory.getNetworkStartedCV(); - testAgent.disconnect(); - waitFor(cv); - assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); - assertTrue(testFactory.getMyStartRequested()); - - testFactory.unregister(); - if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); - handlerThread.quit(); - } - - @LargeTest - public void testNetworkFactoryRequests() throws Exception { - tryNetworkFactoryRequests(NET_CAPABILITY_MMS); - tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); - tryNetworkFactoryRequests(NET_CAPABILITY_DUN); - tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); - tryNetworkFactoryRequests(NET_CAPABILITY_IMS); - tryNetworkFactoryRequests(NET_CAPABILITY_CBS); - tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); - tryNetworkFactoryRequests(NET_CAPABILITY_IA); - tryNetworkFactoryRequests(NET_CAPABILITY_RCS); - tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); - tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); - tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); - tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); - tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); - tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); - // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. - } - - @LargeTest - public void testNoMutableNetworkRequests() throws Exception { - PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(NET_CAPABILITY_VALIDATED); - try { - mCm.requestNetwork(builder.build(), new NetworkCallback()); - fail(); - } catch (IllegalArgumentException expected) {} - try { - mCm.requestNetwork(builder.build(), pendingIntent); - fail(); - } catch (IllegalArgumentException expected) {} - builder = new NetworkRequest.Builder(); - builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - try { - mCm.requestNetwork(builder.build(), new NetworkCallback()); - fail(); - } catch (IllegalArgumentException expected) {} - try { - mCm.requestNetwork(builder.build(), pendingIntent); - fail(); - } catch (IllegalArgumentException expected) {} - } - - @LargeTest - public void testMMSonWiFi() throws Exception { - // Test bringing up cellular without MMS NetworkRequest gets reaped - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); - ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV(); - mCellNetworkAgent.connectWithoutInternet(); - waitFor(cv); - waitFor(new Criteria() { - public boolean get() { return mCm.getAllNetworks().length == 0; } }); - verifyNoNetwork(); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - // Register MMS NetworkRequest - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(builder.build(), networkCallback); - // Test bringing up unvalidated cellular with MMS - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); - mCellNetworkAgent.connectWithoutInternet(); - networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test releasing NetworkRequest disconnects cellular with MMS - cv = mCellNetworkAgent.getDisconnectedCV(); - mCm.unregisterNetworkCallback(networkCallback); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @LargeTest - public void testMMSonCell() throws Exception { - // Test bringing up cellular without MMS - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent.connect(false); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Register MMS NetworkRequest - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(builder.build(), networkCallback); - // Test bringing up MMS cellular network - MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); - mmsNetworkAgent.connectWithoutInternet(); - networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent - cv = mmsNetworkAgent.getDisconnectedCV(); - mCm.unregisterNetworkCallback(networkCallback); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_CELLULAR); - } - - @LargeTest - public void testCaptivePortal() { - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - final TestNetworkCallback validatedCallback = new TestNetworkCallback(); - final NetworkRequest validatedRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED).build(); - mCm.registerNetworkCallback(validatedRequest, validatedCallback); - - // Bring up a network with a captive portal. - // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - String firstRedirectUrl = "http://example.com/firstPath"; - mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); - captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); - - // Take down network. - // Expect onLost callback. - mWiFiNetworkAgent.disconnect(); - captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - // Bring up a network with a captive portal. - // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - String secondRedirectUrl = "http://example.com/secondPath"; - mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); - captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); - - // Make captive portal disappear then revalidate. - // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); - captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - // Expect NET_CAPABILITY_VALIDATED onAvailable callback. - validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - - // Break network connectivity. - // Expect NET_CAPABILITY_VALIDATED onLost callback. - mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500; - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); - validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - } - - @LargeTest - public void testAvoidOrIgnoreCaptivePortals() { - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - final TestNetworkCallback validatedCallback = new TestNetworkCallback(); - final NetworkRequest validatedRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED).build(); - mCm.registerNetworkCallback(validatedRequest, validatedCallback); - - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID); - // Bring up a network with a captive portal. - // Expect it to fail to connect and not result in any callbacks. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - String firstRedirectUrl = "http://example.com/firstPath"; - - ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV(); - ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived(); - mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); - waitFor(disconnectCv); - waitFor(avoidCv); - - assertNoCallbacks(captivePortalCallback, validatedCallback); - - // Now test ignore mode. - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE); - - // Bring up a network with a captive portal. - // Since we're ignoring captive portals, the network will validate. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - String secondRedirectUrl = "http://example.com/secondPath"; - mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); - - // Expect NET_CAPABILITY_VALIDATED onAvailable callback. - validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - // But there should be no CaptivePortal callback. - captivePortalCallback.assertNoCallback(); - } - - @SmallTest - public void testInvalidNetworkSpecifier() { - boolean execptionCalled = true; - - try { - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); - execptionCalled = false; - } catch (IllegalArgumentException e) { - // do nothing - should get here - } - - assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", - execptionCalled); - - try { - NetworkCapabilities networkCapabilities = new NetworkCapabilities(); - networkCapabilities.addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); - mService.requestNetwork(networkCapabilities, null, 0, null, - ConnectivityManager.TYPE_WIFI); - execptionCalled = false; - } catch (IllegalArgumentException e) { - // do nothing - should get here - } - - assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", - execptionCalled); - } - - @LargeTest - public void testRegisterDefaultNetworkCallback() throws Exception { - final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultNetworkCallback); - defaultNetworkCallback.assertNoCallback(); - - // Create a TRANSPORT_CELLULAR request to keep the mobile interface up - // whenever Wi-Fi is up. Without this, the mobile network agent is - // reaped before any other activity can take place. - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - cellNetworkCallback.assertNoCallback(); - - // Bring up cell and expect CALLBACK_AVAILABLE. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - - // Bring up wifi and expect CALLBACK_AVAILABLE. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - cellNetworkCallback.assertNoCallback(); - defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - - // Bring down cell. Expect no default network callback, since it wasn't the default. - mCellNetworkAgent.disconnect(); - cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - defaultNetworkCallback.assertNoCallback(); - - // Bring up cell. Expect no default network callback, since it won't be the default. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - defaultNetworkCallback.assertNoCallback(); - - // Bring down wifi. Expect the default network callback to notified of LOST wifi - // followed by AVAILABLE cell. - mWiFiNetworkAgent.disconnect(); - cellNetworkCallback.assertNoCallback(); - defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - mCellNetworkAgent.disconnect(); - cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - } - - private class TestRequestUpdateCallback extends TestNetworkCallback { - @Override - public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) { - setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap); - } - - @Override - public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) { - setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp); - } - } - - @LargeTest - public void testRequestCallbackUpdates() throws Exception { - // File a network request for mobile. - final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - - // Bring up the mobile network. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - // We should get onAvailable(). - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - // We should get onCapabilitiesChanged(), when the mobile network successfully validates. - cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - - // Update LinkProperties. - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("foonet_data0"); - mCellNetworkAgent.sendLinkProperties(lp); - // We should get onLinkPropertiesChanged(). - cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - - // Register a garden variety default network request. - final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback(); - mCm.registerDefaultNetworkCallback(dfltNetworkCallback); - // Only onAvailable() is called; no other information is delivered. - dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - dfltNetworkCallback.assertNoCallback(); - - // Request a NetworkCapabilities update; only the requesting callback is notified. - mCm.requestNetworkCapabilities(dfltNetworkCallback); - dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - dfltNetworkCallback.assertNoCallback(); - - // Request a LinkProperties update; only the requesting callback is notified. - mCm.requestLinkProperties(dfltNetworkCallback); - dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - dfltNetworkCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(dfltNetworkCallback); - mCm.unregisterNetworkCallback(cellNetworkCallback); - } - - private void setCaptivePortalMode(int mode) { - ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); - } - - private void setMobileDataAlwaysOn(boolean enable) { - ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0); - mService.updateMobileDataAlwaysOn(); - mService.waitForIdle(); - } - - private boolean isForegroundNetwork(MockNetworkAgent network) { - NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); - assertNotNull(nc); - return nc.hasCapability(NET_CAPABILITY_FOREGROUND); - } - - @SmallTest - public void testBackgroundNetworks() throws Exception { - // Create a background request. We can't do this ourselves because ConnectivityService - // doesn't have an API for it. So just turn on mobile data always on. - setMobileDataAlwaysOn(true); - final NetworkRequest request = new NetworkRequest.Builder().build(); - final NetworkRequest fgRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_FOREGROUND).build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - final TestNetworkCallback fgCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - mCm.registerNetworkCallback(fgRequest, fgCallback); - - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - - // When wifi connects, cell lingers. - callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // When lingering is complete, cell is still there but is now in the background. - fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS); - callback.assertNoCallback(); - assertFalse(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // File a cell request and check that cell comes into the foreground. - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - final TestNetworkCallback cellCallback = new TestNetworkCallback(); - mCm.requestNetwork(cellRequest, cellCallback); - cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - callback.assertNoCallback(); // Because the network is already up. - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // Release the request. The network immediately goes into the background, since it was not - // lingering. - mCm.unregisterNetworkCallback(cellCallback); - fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - callback.assertNoCallback(); - assertFalse(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // Disconnect wifi and check that cell is foreground again. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - - mCm.unregisterNetworkCallback(callback); - mCm.unregisterNetworkCallback(fgCallback); - } - - @SmallTest - public void testRequestBenchmark() throws Exception { - // Benchmarks connecting and switching performance in the presence of a large number of - // NetworkRequests. - // 1. File NUM_REQUESTS requests. - // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire. - // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing - // and NUM_REQUESTS onAvailable callbacks to fire. - // See how long it took. - final int NUM_REQUESTS = 90; - final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); - final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS]; - final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); - final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); - - final int REGISTER_TIME_LIMIT_MS = 100; - long startTime = System.currentTimeMillis(); - for (int i = 0; i < NUM_REQUESTS; i++) { - callbacks[i] = new NetworkCallback() { - @Override public void onAvailable(Network n) { availableLatch.countDown(); } - @Override public void onLosing(Network n, int t) { losingLatch.countDown(); } - }; - mCm.registerNetworkCallback(request, callbacks[i]); - } - long timeTaken = System.currentTimeMillis() - startTime; - String msg = String.format("Register %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS); - Log.d(TAG, msg); - assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS); - - final int CONNECT_TIME_LIMIT_MS = 30; - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - // Don't request that the network validate, because otherwise connect() will block until - // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, - // and we won't actually measure anything. - mCellNetworkAgent.connect(false); - startTime = System.currentTimeMillis(); - if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) { - fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms", - NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, - CONNECT_TIME_LIMIT_MS)); - } - timeTaken = System.currentTimeMillis() - startTime; - Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS)); - - final int SWITCH_TIME_LIMIT_MS = 30; - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - // Give wifi a high enough score that we'll linger cell when wifi comes up. - mWiFiNetworkAgent.adjustScore(40); - mWiFiNetworkAgent.connect(false); - startTime = System.currentTimeMillis(); - if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) { - fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms", - NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS)); - } - timeTaken = System.currentTimeMillis() - startTime; - Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS)); - - final int UNREGISTER_TIME_LIMIT_MS = 10; - startTime = System.currentTimeMillis(); - for (int i = 0; i < NUM_REQUESTS; i++) { - mCm.unregisterNetworkCallback(callbacks[i]); - } - timeTaken = System.currentTimeMillis() - startTime; - msg = String.format("Unregister %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS); - Log.d(TAG, msg); - assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS); - } - - @SmallTest - public void testMobileDataAlwaysOn() throws Exception { - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); - - final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory"); - handlerThread.start(); - NetworkCapabilities filter = new NetworkCapabilities() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); - testFactory.setScoreFilter(40); - - // Register the factory and expect it to start looking for a network. - testFactory.expectAddRequests(1); - testFactory.register(); - testFactory.waitForNetworkRequests(1); - assertTrue(testFactory.getMyStartRequested()); - - // Bring up wifi. The factory stops looking for a network. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - testFactory.expectAddRequests(2); // Because the default request changes score twice. - mWiFiNetworkAgent.connect(true); - testFactory.waitForNetworkRequests(1); - assertFalse(testFactory.getMyStartRequested()); - - ContentResolver cr = mServiceContext.getContentResolver(); - - // Turn on mobile data always on. The factory starts looking again. - testFactory.expectAddRequests(1); - setMobileDataAlwaysOn(true); - testFactory.waitForNetworkRequests(2); - assertTrue(testFactory.getMyStartRequested()); - - // Bring up cell data and check that the factory stops looking. - assertEquals(1, mCm.getAllNetworks().length); - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - testFactory.expectAddRequests(2); // Because the cell request changes score twice. - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - testFactory.waitForNetworkRequests(2); - assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us. - - // Check that cell data stays up. - mService.waitForIdle(); - verifyActiveNetwork(TRANSPORT_WIFI); - assertEquals(2, mCm.getAllNetworks().length); - - // Turn off mobile data always on and expect the request to disappear... - testFactory.expectRemoveRequests(1); - setMobileDataAlwaysOn(false); - testFactory.waitForNetworkRequests(1); - - // ... and cell data to be torn down. - cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - assertEquals(1, mCm.getAllNetworks().length); - - testFactory.unregister(); - mCm.unregisterNetworkCallback(cellNetworkCallback); - handlerThread.quit(); - } - - @SmallTest - public void testAvoidBadWifiSetting() throws Exception { - final ContentResolver cr = mServiceContext.getContentResolver(); - final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker(); - final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI; - - tracker.configRestrictsAvoidBadWifi = false; - String[] values = new String[] {null, "0", "1"}; - for (int i = 0; i < values.length; i++) { - Settings.Global.putInt(cr, settingName, 1); - tracker.reevaluate(); - mService.waitForIdle(); - String msg = String.format("config=false, setting=%s", values[i]); - assertTrue(msg, mService.avoidBadWifi()); - assertFalse(msg, tracker.shouldNotifyWifiUnvalidated()); - } - - tracker.configRestrictsAvoidBadWifi = true; - - Settings.Global.putInt(cr, settingName, 0); - tracker.reevaluate(); - mService.waitForIdle(); - assertFalse(mService.avoidBadWifi()); - assertFalse(tracker.shouldNotifyWifiUnvalidated()); - - Settings.Global.putInt(cr, settingName, 1); - tracker.reevaluate(); - mService.waitForIdle(); - assertTrue(mService.avoidBadWifi()); - assertFalse(tracker.shouldNotifyWifiUnvalidated()); - - Settings.Global.putString(cr, settingName, null); - tracker.reevaluate(); - mService.waitForIdle(); - assertFalse(mService.avoidBadWifi()); - assertTrue(tracker.shouldNotifyWifiUnvalidated()); - } - - @SmallTest - public void testAvoidBadWifi() throws Exception { - final ContentResolver cr = mServiceContext.getContentResolver(); - final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker(); - - // Pretend we're on a carrier that restricts switching away from bad wifi. - tracker.configRestrictsAvoidBadWifi = true; - - // File a request for cell to ensure it doesn't go down. - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - - TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - NetworkRequest validatedWifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .addCapability(NET_CAPABILITY_VALIDATED) - .build(); - TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); - - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0); - tracker.reevaluate(); - - // Bring up validated cell. - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - Network cellNetwork = mCellNetworkAgent.getNetwork(); - - // Bring up validated wifi. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); - - // Fail validation on wifi. - mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599; - mCm.reportNetworkConnectivity(wifiNetwork, false); - validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - // Because avoid bad wifi is off, we don't switch to cellular. - defaultCallback.assertNoCallback(); - assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertEquals(mCm.getActiveNetwork(), wifiNetwork); - - // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect - // that we switch back to cell. - tracker.configRestrictsAvoidBadWifi = false; - tracker.reevaluate(); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // Switch back to a restrictive carrier. - tracker.configRestrictsAvoidBadWifi = true; - tracker.reevaluate(); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mCm.getActiveNetwork(), wifiNetwork); - - // Simulate the user selecting "switch" on the dialog, and check that we switch to cell. - mCm.setAvoidUnvalidated(wifiNetwork); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // Disconnect and reconnect wifi to clear the one-time switch above. - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - wifiNetwork = mWiFiNetworkAgent.getNetwork(); - - // Fail validation on wifi and expect the dialog to appear. - mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599; - mCm.reportNetworkConnectivity(wifiNetwork, false); - validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - // Simulate the user selecting "switch" and checking the don't ask again checkbox. - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); - tracker.reevaluate(); - - // We now switch to cell. - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // Simulate the user turning the cellular fallback setting off and then on. - // We switch to wifi and then to cell. - Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); - tracker.reevaluate(); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - assertEquals(mCm.getActiveNetwork(), wifiNetwork); - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); - tracker.reevaluate(); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // If cell goes down, we switch to wifi. - mCellNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - validatedWifiCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(cellNetworkCallback); - mCm.unregisterNetworkCallback(validatedWifiCallback); - mCm.unregisterNetworkCallback(defaultCallback); - } - - /** - * Validate that a satisfied network request does not trigger onUnavailable() once the - * time-out period expires. - */ - @SmallTest - public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(nr, networkCallback, 10); - - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - - // pass timeout and validate that UNAVAILABLE is not called - try { - Thread.sleep(15); - } catch (InterruptedException e) { - } - networkCallback.assertNoCallback(); - } - - /** - * Validate that when a time-out is specified for a network request the onUnavailable() - * callback is called when time-out expires. Then validate that if network request is - * (somehow) satisfied - the callback isn't called later. - */ - @SmallTest - public void testTimedoutNetworkRequest() { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(nr, networkCallback, 10); - - // pass timeout and validate that UNAVAILABLE is called - networkCallback.expectCallback(CallbackState.UNAVAILABLE, null); - - // create a network satisfying request - validate that request not triggered - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.assertNoCallback(); - } - - /** - * Validate that when a network request is unregistered (cancelled) the time-out for that - * request doesn't trigger the onUnavailable() callback. - */ - @SmallTest - public void testTimedoutAfterUnregisteredNetworkRequest() { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(nr, networkCallback, 10); - - // remove request - mCm.unregisterNetworkCallback(networkCallback); - - // pass timeout and validate that no callbacks - // Note: doesn't validate that nothing called from CS since even if called the CM already - // unregisters the callback and won't pass it through! - try { - Thread.sleep(15); - } catch (InterruptedException e) { - } - networkCallback.assertNoCallback(); - - // create a network satisfying request - validate that request not triggered - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.assertNoCallback(); - } - - private static class TestKeepaliveCallback extends PacketKeepaliveCallback { - - public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; - - private class CallbackValue { - public CallbackType callbackType; - public int error; - - public CallbackValue(CallbackType type) { - this.callbackType = type; - this.error = PacketKeepalive.SUCCESS; - assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); - } - - public CallbackValue(CallbackType type, int error) { - this.callbackType = type; - this.error = error; - assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); - } - - @Override - public boolean equals(Object o) { - return o instanceof CallbackValue && - this.callbackType == ((CallbackValue) o).callbackType && - this.error == ((CallbackValue) o).error; - } - - @Override - public String toString() { - return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); - } - } - - private LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); - - @Override - public void onStarted() { - mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); - } - - @Override - public void onStopped() { - mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); - } - - @Override - public void onError(int error) { - mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); - } - - private void expectCallback(CallbackValue callbackValue) { - try { - assertEquals( - callbackValue, - mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } catch (InterruptedException e) { - fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms"); - } - } - - public void expectStarted() { - expectCallback(new CallbackValue(CallbackType.ON_STARTED)); - } - - public void expectStopped() { - expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); - } - - public void expectError(int error) { - expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); - } - } - - private Network connectKeepaliveNetwork(LinkProperties lp) { - // Ensure the network is disconnected before we do anything. - if (mWiFiNetworkAgent != null) { - assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); - } - - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - ConditionVariable cv = waitForConnectivityBroadcasts(1); - mWiFiNetworkAgent.connect(true); - waitFor(cv); - verifyActiveNetwork(TRANSPORT_WIFI); - mWiFiNetworkAgent.sendLinkProperties(lp); - mService.waitForIdle(); - return mWiFiNetworkAgent.getNetwork(); - } - - public void testPacketKeepalives() throws Exception { - InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); - InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); - InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); - InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); - InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); - - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("wlan12"); - lp.addLinkAddress(new LinkAddress(myIPv6, 64)); - lp.addLinkAddress(new LinkAddress(myIPv4, 25)); - lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); - lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); - - Network notMyNet = new Network(61234); - Network myNet = connectKeepaliveNetwork(lp); - - TestKeepaliveCallback callback = new TestKeepaliveCallback(); - PacketKeepalive ka; - - // Attempt to start keepalives with invalid parameters and check for errors. - ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); - - ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only. - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); - - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); - - // Check that a started keepalive can be stopped. - mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS); - ka.stop(); - callback.expectStopped(); - - // Check that deleting the IP address stops the keepalive. - LinkProperties bogusLp = new LinkProperties(lp); - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); - bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); - mWiFiNetworkAgent.sendLinkProperties(bogusLp); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - mWiFiNetworkAgent.sendLinkProperties(lp); - - // Check that a started keepalive is stopped correctly when the network disconnects. - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - mWiFiNetworkAgent.disconnect(); - callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); - - // ... and that stopping it after that has no adverse effects. - assertNull(mCm.getNetworkCapabilities(myNet)); - ka.stop(); - - // Reconnect. - myNet = connectKeepaliveNetwork(lp); - mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); - - // Check things work as expected when the keepalive is stopped and the network disconnects. - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - ka.stop(); - mWiFiNetworkAgent.disconnect(); - mService.waitForIdle(); - callback.expectStopped(); - - // Reconnect. - myNet = connectKeepaliveNetwork(lp); - mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); - - // Check that keepalive slots start from 1 and increment. The first one gets slot 1. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); - ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - - // The second one gets slot 2. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); - TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); - PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4); - callback2.expectStarted(); - - // Now stop the first one and create a third. This also gets slot 1. - ka.stop(); - callback.expectStopped(); - - mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); - TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); - PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4); - callback3.expectStarted(); - - ka2.stop(); - callback2.expectStopped(); - - ka3.stop(); - callback3.expectStopped(); - } - - @SmallTest - public void testGetCaptivePortalServerUrl() throws Exception { - String url = mCm.getCaptivePortalServerUrl(); - assertEquals("http://connectivitycheck.gstatic.com/generate_204", url); - } - - private static class TestNetworkPinner extends NetworkPinner { - public static boolean awaitPin(int timeoutMs) { - synchronized(sLock) { - if (sNetwork == null) { - try { - sLock.wait(timeoutMs); - } catch (InterruptedException e) {} - } - return sNetwork != null; - } - } - - public static boolean awaitUnpin(int timeoutMs) { - synchronized(sLock) { - if (sNetwork != null) { - try { - sLock.wait(timeoutMs); - } catch (InterruptedException e) {} - } - return sNetwork == null; - } - } - } - - private void assertPinnedToWifiWithCellDefault() { - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - } - - private void assertPinnedToWifiWithWifiDefault() { - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - } - - private void assertNotPinnedToWifi() { - assertNull(mCm.getBoundNetworkForProcess()); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - } - - @SmallTest - public void testNetworkPinner() { - NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .build(); - assertNull(mCm.getBoundNetworkForProcess()); - - TestNetworkPinner.pin(mServiceContext, wifiRequest); - assertNull(mCm.getBoundNetworkForProcess()); - - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - - // When wi-fi connects, expect to be pinned. - assertTrue(TestNetworkPinner.awaitPin(100)); - assertPinnedToWifiWithCellDefault(); - - // Disconnect and expect the pin to drop. - mWiFiNetworkAgent.disconnect(); - assertTrue(TestNetworkPinner.awaitUnpin(100)); - assertNotPinnedToWifi(); - - // Reconnecting does not cause the pin to come back. - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - assertFalse(TestNetworkPinner.awaitPin(100)); - assertNotPinnedToWifi(); - - // Pinning while connected causes the pin to take effect immediately. - TestNetworkPinner.pin(mServiceContext, wifiRequest); - assertTrue(TestNetworkPinner.awaitPin(100)); - assertPinnedToWifiWithCellDefault(); - - // Explicitly unpin and expect to use the default network again. - TestNetworkPinner.unpin(); - assertNotPinnedToWifi(); - - // Disconnect cell and wifi. - ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down. - mCellNetworkAgent.disconnect(); - mWiFiNetworkAgent.disconnect(); - waitFor(cv); - - // Pinning takes effect even if the pinned network is the default when the pin is set... - TestNetworkPinner.pin(mServiceContext, wifiRequest); - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - assertTrue(TestNetworkPinner.awaitPin(100)); - assertPinnedToWifiWithWifiDefault(); - - // ... and is maintained even when that network is no longer the default. - cv = waitForConnectivityBroadcasts(1); - mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mCellNetworkAgent.connect(true); - waitFor(cv); - assertPinnedToWifiWithCellDefault(); - } - - @SmallTest - public void testNetworkRequestMaximum() { - final int MAX_REQUESTS = 100; - // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added. - NetworkRequest networkRequest = new NetworkRequest.Builder().build(); - ArrayList networkCallbacks = new ArrayList(); - try { - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.requestNetwork(networkRequest, networkCallback); - networkCallbacks.add(networkCallback); - } - fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception"); - } catch (IllegalArgumentException expected) {} - for (NetworkCallback networkCallback : networkCallbacks) { - mCm.unregisterNetworkCallback(networkCallback); - } - networkCallbacks.clear(); - - try { - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - networkCallbacks.add(networkCallback); - } - fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception"); - } catch (IllegalArgumentException expected) {} - for (NetworkCallback networkCallback : networkCallbacks) { - mCm.unregisterNetworkCallback(networkCallback); - } - networkCallbacks.clear(); - - ArrayList pendingIntents = new ArrayList(); - try { - for (int i = 0; i < MAX_REQUESTS + 1; i++) { - PendingIntent pendingIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0); - mCm.requestNetwork(networkRequest, pendingIntent); - pendingIntents.add(pendingIntent); - } - fail("Registering " + MAX_REQUESTS + - " PendingIntent NetworkRequests did not throw exception"); - } catch (IllegalArgumentException expected) {} - for (PendingIntent pendingIntent : pendingIntents) { - mCm.unregisterNetworkCallback(pendingIntent); - } - pendingIntents.clear(); - - try { - for (int i = 0; i < MAX_REQUESTS + 1; i++) { - PendingIntent pendingIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0); - mCm.registerNetworkCallback(networkRequest, pendingIntent); - pendingIntents.add(pendingIntent); - } - fail("Registering " + MAX_REQUESTS + - " PendingIntent NetworkCallbacks did not throw exception"); - } catch (IllegalArgumentException expected) {} - for (PendingIntent pendingIntent : pendingIntents) { - mCm.unregisterNetworkCallback(pendingIntent); - } - pendingIntents.clear(); - mService.waitForIdle(5000); - - // Test that the limit is not hit when MAX_REQUESTS requests are added and removed. - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.requestNetwork(networkRequest, networkCallback); - mCm.unregisterNetworkCallback(networkCallback); - } - mService.waitForIdle(); - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - mCm.unregisterNetworkCallback(networkCallback); - } - mService.waitForIdle(); - for (int i = 0; i < MAX_REQUESTS; i++) { - PendingIntent pendingIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0); - mCm.requestNetwork(networkRequest, pendingIntent); - mCm.unregisterNetworkCallback(pendingIntent); - } - mService.waitForIdle(); - for (int i = 0; i < MAX_REQUESTS; i++) { - PendingIntent pendingIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0); - mCm.registerNetworkCallback(networkRequest, pendingIntent); - mCm.unregisterNetworkCallback(pendingIntent); - } - } -} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index d62c30da58..f95a8c6de5 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -70,6 +70,7 @@ import android.provider.Settings; import android.test.AndroidTestCase; import android.test.FlakyTest; import android.test.mock.MockContentResolver; +import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import android.util.LogPrinter; @@ -90,7 +91,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.BooleanSupplier; /** * Tests for {@link ConnectivityService}. @@ -195,7 +195,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { } // Tests that IdleableHandlerThread works as expected. - @SmallTest public void testIdleableHandlerThread() { final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. @@ -220,7 +219,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @SmallTest @FlakyTest(tolerance = 3) public void testNotWaitingForIdleCausesRaceConditions() { // Bring up a network that we can use to send messages to ConnectivityService. @@ -624,7 +622,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker { - public volatile boolean configRestrictsAvoidBadWifi; + public boolean configRestrictsAvoidBadWifi; public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) { super(c, h, r); @@ -729,7 +727,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { static private void waitFor(Criteria criteria) { int delays = 0; while (!criteria.get()) { - sleepFor(50); + try { + Thread.sleep(50); + } catch (InterruptedException e) { + } if (++delays == 10) fail(); } } @@ -841,7 +842,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { return cv; } - @SmallTest + @LargeTest public void testLingering() throws Exception { verifyNoNetwork(); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -881,7 +882,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @SmallTest + @LargeTest public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { // Test bringing up unvalidated WiFi mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -916,7 +917,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @SmallTest + @LargeTest public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { // Test bringing up unvalidated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -942,7 +943,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @SmallTest + @LargeTest public void testUnlingeringDoesNotValidate() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -970,7 +971,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { NET_CAPABILITY_VALIDATED)); } - @SmallTest + @LargeTest public void testCellularOutscoresWeakWifi() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -996,7 +997,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @SmallTest + @LargeTest public void testReapingNetwork() throws Exception { // Test bringing up WiFi without NET_CAPABILITY_INTERNET. // Expect it to be torn down immediately because it satisfies no requests. @@ -1029,7 +1030,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { waitFor(cv); } - @SmallTest + @LargeTest public void testCellularFallback() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1067,7 +1068,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @SmallTest + @LargeTest public void testWiFiFallback() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -1103,6 +1104,29 @@ public class ConnectivityServiceTest extends AndroidTestCase { UNAVAILABLE } + private static class CallbackInfo { + public final CallbackState state; + public final Network network; + public final Object arg; + public CallbackInfo(CallbackState s, Network n, Object o) { + state = s; network = n; arg = o; + } + public String toString() { + return String.format("%s (%s)", state, network); + } + @Override + public boolean equals(Object o) { + if (!(o instanceof CallbackInfo)) return false; + // Ignore timeMs, since it's unpredictable. + CallbackInfo other = (CallbackInfo) o; + return (state == other.state) && Objects.equals(network, other.network); + } + @Override + public int hashCode() { + return Objects.hash(state, network); + } + } + /** * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks * this class receives, by calling expectCallback() exactly once each time a callback is @@ -1114,21 +1138,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { // the linger timeout. private final static int TIMEOUT_MS = 50; - private class CallbackInfo { - public final CallbackState state; - public final Network network; - public Object arg; - public CallbackInfo(CallbackState s, Network n, Object o) { - state = s; network = n; arg = o; - } - public String toString() { return String.format("%s (%s)", state, network); } - public boolean equals(Object o) { - if (!(o instanceof CallbackInfo)) return false; - // Ignore timeMs, since it's unpredictable. - CallbackInfo other = (CallbackInfo) o; - return state == other.state && Objects.equals(network, other.network); - } - } private final LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); protected void setLastCallback(CallbackState state, Network network, Object o) { @@ -1155,17 +1164,24 @@ public class ConnectivityServiceTest extends AndroidTestCase { setLastCallback(CallbackState.LOST, network, null); } + CallbackInfo nextCallback(int timeoutMs) { + CallbackInfo cb = null; + try { + cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + } + if (cb == null) { + // LinkedBlockingQueue.poll() returns null if it timeouts. + fail("Did not receive callback after " + timeoutMs + "ms"); + } + return cb; + } + void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) { CallbackInfo expected = new CallbackInfo( state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0); - CallbackInfo actual; - try { - actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); - assertEquals("Unexpected callback:", expected, actual); - } catch (InterruptedException e) { - fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms"); - actual = null; // Or the compiler can't tell it's never used uninitialized. - } + CallbackInfo actual = nextCallback(timeoutMs); + assertEquals("Unexpected callback:", expected, actual); if (state == CallbackState.LOSING) { String msg = String.format( "Invalid linger time value %d, must be between %d and %d", @@ -1194,7 +1210,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @SmallTest + @LargeTest public void testStateChangeNetworkCallbacks() throws Exception { final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); @@ -1577,7 +1593,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { handlerThread.quit(); } - @SmallTest + @LargeTest public void testNetworkFactoryRequests() throws Exception { tryNetworkFactoryRequests(NET_CAPABILITY_MMS); tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); @@ -1597,7 +1613,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. } - @SmallTest + @LargeTest public void testNoMutableNetworkRequests() throws Exception { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); NetworkRequest.Builder builder = new NetworkRequest.Builder(); @@ -1622,7 +1638,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } catch (IllegalArgumentException expected) {} } - @SmallTest + @LargeTest public void testMMSonWiFi() throws Exception { // Test bringing up cellular without MMS NetworkRequest gets reaped mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1657,7 +1673,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @SmallTest + @LargeTest public void testMMSonCell() throws Exception { // Test bringing up cellular without MMS mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1683,7 +1699,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_CELLULAR); } - @SmallTest + @LargeTest public void testCaptivePortal() { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() @@ -1732,7 +1748,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); } - @SmallTest + @LargeTest public void testAvoidOrIgnoreCaptivePortals() { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() @@ -1803,7 +1819,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { execptionCalled); } - @SmallTest + @LargeTest public void testRegisterDefaultNetworkCallback() throws Exception { final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultNetworkCallback); @@ -1864,7 +1880,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @SmallTest + @LargeTest public void testRequestCallbackUpdates() throws Exception { // File a network request for mobile. final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback(); @@ -1999,7 +2015,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { @SmallTest public void testRequestBenchmark() throws Exception { - // TODO: turn this unit test into a real benchmarking test. // Benchmarks connecting and switching performance in the presence of a large number of // NetworkRequests. // 1. File NUM_REQUESTS requests. @@ -2013,80 +2028,61 @@ public class ConnectivityServiceTest extends AndroidTestCase { final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); + final int REGISTER_TIME_LIMIT_MS = 100; + long startTime = System.currentTimeMillis(); for (int i = 0; i < NUM_REQUESTS; i++) { callbacks[i] = new NetworkCallback() { @Override public void onAvailable(Network n) { availableLatch.countDown(); } @Override public void onLosing(Network n, int t) { losingLatch.countDown(); } }; + mCm.registerNetworkCallback(request, callbacks[i]); } + long timeTaken = System.currentTimeMillis() - startTime; + String msg = String.format("Register %d callbacks: %dms, acceptable %dms", + NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS); + Log.d(TAG, msg); + assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS); - final int REGISTER_TIME_LIMIT_MS = 180; - assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> { - for (NetworkCallback cb : callbacks) { - mCm.registerNetworkCallback(request, cb); - } - }); - - final int CONNECT_TIME_LIMIT_MS = 40; + final int CONNECT_TIME_LIMIT_MS = 30; mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); // Don't request that the network validate, because otherwise connect() will block until // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, // and we won't actually measure anything. mCellNetworkAgent.connect(false); - - long onAvailableDispatchingDuration = durationOf(() -> { - if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) { - fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms", - NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, - CONNECT_TIME_LIMIT_MS)); - } - }); + startTime = System.currentTimeMillis(); + if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) { + fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms", + NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, + CONNECT_TIME_LIMIT_MS)); + } + timeTaken = System.currentTimeMillis() - startTime; Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS)); + NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS)); - final int SWITCH_TIME_LIMIT_MS = 40; + final int SWITCH_TIME_LIMIT_MS = 30; mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); // Give wifi a high enough score that we'll linger cell when wifi comes up. mWiFiNetworkAgent.adjustScore(40); mWiFiNetworkAgent.connect(false); - - long onLostDispatchingDuration = durationOf(() -> { - if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) { - fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms", - NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS)); - } - }); + startTime = System.currentTimeMillis(); + if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) { + fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms", + NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS)); + } + timeTaken = System.currentTimeMillis() - startTime; Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS)); + NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS)); final int UNREGISTER_TIME_LIMIT_MS = 10; - assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> { - for (NetworkCallback cb : callbacks) { - mCm.unregisterNetworkCallback(cb); - } - }); - } - - private long durationOf(Runnable fn) { - long startTime = SystemClock.elapsedRealtime(); - fn.run(); - return SystemClock.elapsedRealtime() - startTime; - } - - private void assertTimeLimit(String descr, long timeLimit, Runnable fn) { - long timeTaken = durationOf(fn); - String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit); + startTime = System.currentTimeMillis(); + for (int i = 0; i < NUM_REQUESTS; i++) { + mCm.unregisterNetworkCallback(callbacks[i]); + } + timeTaken = System.currentTimeMillis() - startTime; + msg = String.format("Unregister %d callbacks: %dms, acceptable %dms", + NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS); Log.d(TAG, msg); - assertTrue(msg, timeTaken <= timeLimit); - } - - private boolean awaitLatch(CountDownLatch l, long timeoutMs) { - try { - if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) { - return true; - } - } catch (InterruptedException e) {} - return false; + assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS); } @SmallTest @@ -2167,7 +2163,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { tracker.reevaluate(); mService.waitForIdle(); String msg = String.format("config=false, setting=%s", values[i]); - assertEventuallyTrue(() -> mService.avoidBadWifi(), 50); + assertTrue(msg, mService.avoidBadWifi()); assertFalse(msg, tracker.shouldNotifyWifiUnvalidated()); } @@ -2176,19 +2172,19 @@ public class ConnectivityServiceTest extends AndroidTestCase { Settings.Global.putInt(cr, settingName, 0); tracker.reevaluate(); mService.waitForIdle(); - assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50); + assertFalse(mService.avoidBadWifi()); assertFalse(tracker.shouldNotifyWifiUnvalidated()); Settings.Global.putInt(cr, settingName, 1); tracker.reevaluate(); mService.waitForIdle(); - assertEventuallyTrue(() -> mService.avoidBadWifi(), 50); + assertTrue(mService.avoidBadWifi()); assertFalse(tracker.shouldNotifyWifiUnvalidated()); Settings.Global.putString(cr, settingName, null); tracker.reevaluate(); mService.waitForIdle(); - assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50); + assertFalse(mService.avoidBadWifi()); assertTrue(tracker.shouldNotifyWifiUnvalidated()); } @@ -2331,30 +2327,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); // pass timeout and validate that UNAVAILABLE is not called - sleepFor(15); - networkCallback.assertNoCallback(); - } - - /** - * Validate that a satisfied network request followed by a disconnected (lost) network does - * not trigger onUnavailable() once the time-out period expires. - */ - @SmallTest - public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(nr, networkCallback, 500); - - mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); - sleepFor(20); - mWiFiNetworkAgent.disconnect(); - networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); - - // pass timeout and validate that UNAVAILABLE is not called - sleepFor(600); + try { + Thread.sleep(15); + } catch (InterruptedException e) { + } networkCallback.assertNoCallback(); } @@ -2396,7 +2372,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { // pass timeout and validate that no callbacks // Note: doesn't validate that nothing called from CS since even if called the CM already // unregisters the callback and won't pass it through! - sleepFor(15); + try { + Thread.sleep(15); + } catch (InterruptedException e) { + } networkCallback.assertNoCallback(); // create a network satisfying request - validate that request not triggered @@ -2405,17 +2384,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { networkCallback.assertNoCallback(); } - public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) throws Exception { - long start = SystemClock.elapsedRealtime(); - while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) { - if (fn.getAsBoolean()) { - return; - } - Thread.sleep(10); - } - assertTrue(fn.getAsBoolean()); - } - private static class TestKeepaliveCallback extends PacketKeepaliveCallback { public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; @@ -2505,7 +2473,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { return mWiFiNetworkAgent.getNetwork(); } - @SmallTest public void testPacketKeepalives() throws Exception { InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); @@ -2821,13 +2788,4 @@ public class ConnectivityServiceTest extends AndroidTestCase { mCm.unregisterNetworkCallback(pendingIntent); } } - - /* test utilities */ - static private void sleepFor(int ms) { - try { - Thread.sleep(ms); - } catch (InterruptedException e) { - } - - } } diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index 84f0f9040b..aed3635245 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java @@ -71,8 +71,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " transport_types: 3", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -94,8 +93,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " state_transition: \"SomeState\"", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -116,8 +114,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " state_transition: \"\"", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -163,8 +160,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " return_codes: 178", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -185,8 +181,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " latency_ms: 5678", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -205,8 +200,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"wlan0\"", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -229,8 +223,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " >", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -255,8 +248,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " probe_result: 204", " probe_type: 1", " >", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -282,8 +274,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " program_length: 2048", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -314,8 +305,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " zero_lifetime_ras: 1", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } @@ -342,8 +332,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " router_lifetime: 2000", " >", " time_ms: 1", - ">", - "version: 2"); + ">"); verifySerialization(want, ev); } diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index aa491bbabd..3fc89b9ff1 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -19,7 +19,6 @@ package com.android.server.connectivity; import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.net.IIpConnectivityMetrics; -import android.net.metrics.ApfProgramEvent; import android.net.metrics.ApfStats; import android.net.metrics.DefaultNetworkEvent; import android.net.metrics.DhcpClientEvent; @@ -58,7 +57,7 @@ public class IpConnectivityMetricsTest extends TestCase { public void setUp() { MockitoAnnotations.initMocks(this); - mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000); + mService = new IpConnectivityMetrics(mCtx); } public void testLoggingEvents() throws Exception { @@ -113,27 +112,6 @@ public class IpConnectivityMetricsTest extends TestCase { assertEquals("", output3); } - public void testRateLimiting() { - final IpConnectivityLog logger = new IpConnectivityLog(mService.impl); - final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0); - final long fakeTimestamp = 1; - - int attempt = 100; // More than burst quota, but less than buffer size. - for (int i = 0; i < attempt; i++) { - logger.log(ev); - } - - String output1 = getdump("flush"); - assertFalse("".equals(output1)); - - for (int i = 0; i < attempt; i++) { - assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev)); - } - - String output2 = getdump("flush"); - assertEquals("", output2); - } - public void testEndToEndLogging() { IpConnectivityLog logger = new IpConnectivityLog(mService.impl); @@ -226,8 +204,7 @@ public class IpConnectivityMetricsTest extends TestCase { " router_lifetime: 2000", " >", " time_ms: 700", - ">", - "version: 2"); + ">"); verifySerialization(want, getdump("flush")); } diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 77956be66c..bce5787ed9 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -24,7 +24,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkMisc; -import android.test.suitebuilder.annotation.SmallTest; import android.text.format.DateUtils; import com.android.internal.R; import com.android.server.ConnectivityService; @@ -71,7 +70,6 @@ public class LingerMonitorTest extends TestCase { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT); } - @SmallTest public void testTransitions() { setNotificationSwitch(transition(WIFI, CELLULAR)); NetworkAgentInfo nai1 = wifiNai(100); @@ -81,7 +79,6 @@ public class LingerMonitorTest extends TestCase { assertFalse(mMonitor.isNotificationEnabled(nai2, nai1)); } - @SmallTest public void testNotificationOnLinger() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -92,7 +89,6 @@ public class LingerMonitorTest extends TestCase { verifyNotification(from, to); } - @SmallTest public void testToastOnLinger() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); @@ -103,7 +99,6 @@ public class LingerMonitorTest extends TestCase { verifyToast(from, to); } - @SmallTest public void testNotificationClearedAfterDisconnect() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -117,7 +112,6 @@ public class LingerMonitorTest extends TestCase { verify(mNotifier, times(1)).clearNotification(100); } - @SmallTest public void testNotificationClearedAfterSwitchingBack() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -131,7 +125,6 @@ public class LingerMonitorTest extends TestCase { verify(mNotifier, times(1)).clearNotification(100); } - @SmallTest public void testUniqueToast() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); @@ -149,7 +142,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testMultipleNotifications() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -168,7 +160,6 @@ public class LingerMonitorTest extends TestCase { verifyNotification(wifi2, cell); } - @SmallTest public void testRateLimiting() throws InterruptedException { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT); @@ -194,7 +185,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testDailyLimiting() throws InterruptedException { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT); @@ -221,7 +211,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testUniqueNotification() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -238,7 +227,6 @@ public class LingerMonitorTest extends TestCase { verifyNotification(from, to); } - @SmallTest public void testIgnoreNeverValidatedNetworks() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -250,7 +238,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testIgnoreCurrentlyValidatedNetworks() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -262,7 +249,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testNoNotificationType() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(); @@ -273,7 +259,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testNoTransitionToNotify() { setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -284,7 +269,6 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } - @SmallTest public void testDifferentTransitionToNotify() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(CELLULAR, WIFI)); diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 2bb62bbdcf..9e2fd6231b 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -22,8 +22,6 @@ import android.net.Network; import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; -import android.os.RemoteException; -import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; import org.junit.Before; @@ -84,7 +82,6 @@ public class NetdEventListenerServiceTest extends TestCase { verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture()); } - @SmallTest public void testOneBatch() throws Exception { log(105, LATENCIES); log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event @@ -99,7 +96,6 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES)); } - @SmallTest public void testSeveralBatches() throws Exception { log(105, LATENCIES); log(106, LATENCIES); @@ -113,7 +109,6 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES)); } - @SmallTest public void testBatchAndNetworkLost() throws Exception { byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20); byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20); @@ -130,7 +125,6 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES)); } - @SmallTest public void testConcurrentBatchesAndDumps() throws Exception { final long stop = System.currentTimeMillis() + 100; final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null")); @@ -152,7 +146,6 @@ public class NetdEventListenerServiceTest extends TestCase { new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES)); } - @SmallTest public void testConcurrentBatchesAndNetworkLoss() throws Exception { logAsync(105, LATENCIES); Thread.sleep(10L); @@ -164,13 +157,9 @@ public class NetdEventListenerServiceTest extends TestCase { } void log(int netId, int[] latencies) { - try { - for (int l : latencies) { - mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, - 0, 0); - } - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); + for (int l : latencies) { + mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, 0, + 0); } } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index b51b2771db..5d8b843bbc 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -25,11 +25,9 @@ import static org.mockito.Mockito.*; import android.annotation.UserIdInt; import android.app.AppOpsManager; -import android.app.NotificationManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; -import android.net.NetworkInfo.DetailedState; import android.net.UidRange; import android.os.INetworkManagementService; import android.os.Looper; @@ -45,8 +43,6 @@ import java.util.Arrays; import java.util.Map; import java.util.Set; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -92,18 +88,14 @@ public class VpnTest extends AndroidTestCase { @Mock private PackageManager mPackageManager; @Mock private INetworkManagementService mNetService; @Mock private AppOpsManager mAppOps; - @Mock private NotificationManager mNotificationManager; @Override public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getPackageManager()).thenReturn(mPackageManager); setMockedPackages(mPackages); - when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName()); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); - when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE))) - .thenReturn(mNotificationManager); doNothing().when(mNetService).registerObserver(any()); } @@ -111,7 +103,7 @@ public class VpnTest extends AndroidTestCase { public void testRestrictedProfilesAreAddedToVpn() { setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); - final Vpn vpn = spyVpn(primaryUser.id); + final Vpn vpn = new MockVpn(primaryUser.id); final Set ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); @@ -125,7 +117,7 @@ public class VpnTest extends AndroidTestCase { public void testManagedProfilesAreNotAddedToVpn() { setMockedUsers(primaryUser, managedProfileA); - final Vpn vpn = spyVpn(primaryUser.id); + final Vpn vpn = new MockVpn(primaryUser.id); final Set ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); @@ -138,7 +130,7 @@ public class VpnTest extends AndroidTestCase { public void testAddUserToVpnOnlyAddsOneUser() { setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); - final Vpn vpn = spyVpn(primaryUser.id); + final Vpn vpn = new MockVpn(primaryUser.id); final Set ranges = new ArraySet<>(); vpn.addUserToRanges(ranges, primaryUser.id, null, null); @@ -149,7 +141,7 @@ public class VpnTest extends AndroidTestCase { @SmallTest public void testUidWhiteAndBlacklist() throws Exception { - final Vpn vpn = spyVpn(primaryUser.id); + final Vpn vpn = new MockVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; @@ -174,15 +166,15 @@ public class VpnTest extends AndroidTestCase { @SmallTest public void testLockdownChangingPackage() throws Exception { - final Vpn vpn = spyVpn(primaryUser.id); + final MockVpn vpn = new MockVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); // Default state. - assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false)); - assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true)); @@ -190,8 +182,8 @@ public class VpnTest extends AndroidTestCase { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) })); - assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); - assertUnblocked(vpn, user.start + PKG_UIDS[1]); + vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + vpn.assertUnblocked(user.start + PKG_UIDS[1]); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); @@ -203,13 +195,13 @@ public class VpnTest extends AndroidTestCase { new UidRange(user.start, user.start + PKG_UIDS[3] - 1), new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) })); - assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - assertUnblocked(vpn, user.start + PKG_UIDS[3]); + vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); + vpn.assertUnblocked(user.start + PKG_UIDS[3]); } @SmallTest public void testLockdownAddingAProfile() throws Exception { - final Vpn vpn = spyVpn(primaryUser.id); + final MockVpn vpn = new MockVpn(primaryUser.id); setMockedUsers(primaryUser); // Make a copy of the restricted profile, as we're going to mark it deleted halfway through. @@ -228,7 +220,7 @@ public class VpnTest extends AndroidTestCase { })); // Verify restricted user isn't affected at first. - assertUnblocked(vpn, profile.start + PKG_UIDS[0]); + vpn.assertUnblocked(profile.start + PKG_UIDS[0]); // Add the restricted user. setMockedUsers(primaryUser, tempProfile); @@ -247,53 +239,24 @@ public class VpnTest extends AndroidTestCase { })); } - @SmallTest - public void testNotificationShownForAlwaysOnApp() { - final Vpn vpn = spyVpn(primaryUser.id); - final InOrder order = inOrder(vpn); - setMockedUsers(primaryUser); - - // Don't show a notification for regular disconnected states. - vpn.updateState(DetailedState.DISCONNECTED, TAG); - order.verify(vpn).updateAlwaysOnNotificationInternal(false); - - // Start showing a notification for disconnected once always-on. - vpn.setAlwaysOnPackage(PKGS[0], false); - order.verify(vpn).updateAlwaysOnNotificationInternal(true); - - // Stop showing the notification once connected. - vpn.updateState(DetailedState.CONNECTED, TAG); - order.verify(vpn).updateAlwaysOnNotificationInternal(false); - - // Show the notification if we disconnect again. - vpn.updateState(DetailedState.DISCONNECTED, TAG); - order.verify(vpn).updateAlwaysOnNotificationInternal(true); - - // Notification should be cleared after unsetting always-on package. - vpn.setAlwaysOnPackage(null, false); - order.verify(vpn).updateAlwaysOnNotificationInternal(false); - } - /** - * Mock some methods of vpn object. + * A subclass of {@link Vpn} with some of the fields pre-mocked. */ - private Vpn spyVpn(@UserIdInt int userId) { - final Vpn vpn = spy(new Vpn(Looper.myLooper(), mContext, mNetService, userId)); - - // Block calls to the NotificationManager or PendingIntent#getActivity. - doNothing().when(vpn).updateAlwaysOnNotificationInternal(anyBoolean()); - return vpn; - } - - private static void assertBlocked(Vpn vpn, int... uids) { - for (int uid : uids) { - assertTrue("Uid " + uid + " should be blocked", vpn.isBlockingUid(uid)); + private class MockVpn extends Vpn { + public MockVpn(@UserIdInt int userId) { + super(Looper.myLooper(), mContext, mNetService, userId); } - } - private static void assertUnblocked(Vpn vpn, int... uids) { - for (int uid : uids) { - assertFalse("Uid " + uid + " should not be blocked", vpn.isBlockingUid(uid)); + public void assertBlocked(int... uids) { + for (int uid : uids) { + assertTrue("Uid " + uid + " should be blocked", isBlockingUid(uid)); + } + } + + public void assertUnblocked(int... uids) { + for (int uid : uids) { + assertFalse("Uid " + uid + " should not be blocked", isBlockingUid(uid)); + } } }