From e3b646f25d8c96c43d28c72a98e2c90de9ae9273 Mon Sep 17 00:00:00 2001 From: Pierre Imai Date: Mon, 8 Feb 2016 16:01:40 +0900 Subject: [PATCH 01/19] Silence the obnoxious MTU 0 error message that occur when no MTU is specified for a given network. Bug: 10705136 (cherry picked from commit 07c53a35aeda587f887cfe4e1d0ccf0e4628f49c) Change-Id: I89e2fdfbbfa981d435a2974422d9d9c009872d76 --- .../core/java/com/android/server/ConnectivityService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4c90794555..4cd7d41ca9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1804,11 +1804,14 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updateMtu(LinkProperties newLp, LinkProperties oldLp) { final String iface = newLp.getInterfaceName(); final int mtu = newLp.getMtu(); + if (oldLp == null && mtu == 0) { + // Silently ignore unset MTU value. + return; + } if (oldLp != null && newLp.isIdenticalMtu(oldLp)) { if (VDBG) log("identical MTU - not setting"); return; } - if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) { if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface); return; From d99da81faed29c0533561783432ba4a20d012fc9 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Wed, 25 Nov 2015 12:49:38 +0900 Subject: [PATCH 02/19] Support timeouts for requestNetwork() invocations. (cherry-pick of 0b7a74842b89975a678f4e406ad3d0f512dfa702) (cherry picked from commit 155a59aa6323ba22e75b86ee84c1409468e06a69) Bug: 21414325 Change-Id: I1a58823a372154589f972b98c4c428eab0e0523e --- .../java/android/net/ConnectivityManager.java | 110 +++++++++++------- .../android/server/ConnectivityService.java | 27 ++++- .../server/ConnectivityServiceTest.java | 81 ++++++++++++- 3 files changed, 169 insertions(+), 49 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 51431ebfaf..43c8c81da2 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2079,8 +2079,6 @@ public class ConnectivityManager { @SystemApi public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { - checkNotNull(callback, "OnStartTetheringCallback cannot be null."); - ResultReceiver wrappedCallback = new ResultReceiver(handler) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -2091,7 +2089,6 @@ public class ConnectivityManager { } } }; - try { mService.startTethering(type, wrappedCallback, showProvisioningUi); } catch (RemoteException e) { @@ -2660,7 +2657,6 @@ public class ConnectivityManager { public static final int CALLBACK_IP_CHANGED = BASE + 7; /** @hide */ public static final int CALLBACK_RELEASED = BASE + 8; - // TODO: consider deleting CALLBACK_EXIT and shifting following enum codes down by 1. /** @hide */ public static final int CALLBACK_EXIT = BASE + 9; /** @hide obj = NetworkCapabilities, arg1 = seq number */ @@ -2691,17 +2687,24 @@ public class ConnectivityManager { } private class CallbackHandler extends Handler { + private final HashMapmCallbackMap; + private final AtomicInteger mRefCount; private static final String TAG = "ConnectivityManager.CallbackHandler"; + private final ConnectivityManager mCm; private static final boolean DBG = false; - CallbackHandler(Looper looper) { + CallbackHandler(Looper looper, HashMapcallbackMap, + AtomicInteger refCount, ConnectivityManager cm) { super(looper); + mCallbackMap = callbackMap; + mRefCount = refCount; + mCm = cm; } @Override public void handleMessage(Message message) { - NetworkRequest request = getObject(message, NetworkRequest.class); - Network network = getObject(message, Network.class); + NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class); + Network network = (Network) getObject(message, Network.class); if (DBG) { Log.d(TAG, whatToString(message.what) + " for network " + network); } @@ -2744,7 +2747,9 @@ public class ConnectivityManager { case CALLBACK_CAP_CHANGED: { NetworkCallback callback = getCallback(request, "CAP_CHANGED"); if (callback != null) { - NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); + NetworkCapabilities cap = (NetworkCapabilities)getObject(message, + NetworkCapabilities.class); + callback.onCapabilitiesChanged(network, cap); } break; @@ -2752,7 +2757,9 @@ public class ConnectivityManager { case CALLBACK_IP_CHANGED: { NetworkCallback callback = getCallback(request, "IP_CHANGED"); if (callback != null) { - LinkProperties lp = getObject(message, LinkProperties.class); + LinkProperties lp = (LinkProperties)getObject(message, + LinkProperties.class); + callback.onLinkPropertiesChanged(network, lp); } break; @@ -2772,16 +2779,24 @@ public class ConnectivityManager { break; } case CALLBACK_RELEASED: { - final NetworkCallback callback; - synchronized(sCallbacks) { - callback = sCallbacks.remove(request); + NetworkCallback callback = null; + synchronized(mCallbackMap) { + callback = mCallbackMap.remove(request); } - if (callback == null) { + if (callback != null) { + synchronized(mRefCount) { + if (mRefCount.decrementAndGet() == 0) { + getLooper().quit(); + } + } + } else { Log.e(TAG, "callback not found for RELEASED message"); } break; } case CALLBACK_EXIT: { + Log.d(TAG, "Listener quitting"); + getLooper().quit(); break; } case EXPIRE_LEGACY_REQUEST: { @@ -2791,14 +2806,14 @@ public class ConnectivityManager { } } - private T getObject(Message msg, Class c) { - return (T) msg.getData().getParcelable(c.getSimpleName()); + private Object getObject(Message msg, Class c) { + return msg.getData().getParcelable(c.getSimpleName()); } private NetworkCallback getCallback(NetworkRequest req, String name) { NetworkCallback callback; - synchronized(sCallbacks) { - callback = sCallbacks.get(req); + synchronized(mCallbackMap) { + callback = mCallbackMap.get(req); } if (callback == null) { Log.e(TAG, "callback not found for " + name + " message"); @@ -2807,56 +2822,63 @@ public class ConnectivityManager { } } - private CallbackHandler getHandler() { - synchronized (sCallbacks) { - if (sCallbackHandler == null) { - sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper()); + private void incCallbackHandlerRefCount() { + synchronized(sCallbackRefCount) { + if (sCallbackRefCount.incrementAndGet() == 1) { + // TODO: switch this to ConnectivityThread + HandlerThread callbackThread = new HandlerThread("ConnectivityManager"); + callbackThread.start(); + sCallbackHandler = new CallbackHandler(callbackThread.getLooper(), + sNetworkCallback, sCallbackRefCount, this); } - return sCallbackHandler; } } - static final HashMap sCallbacks = new HashMap<>(); - static CallbackHandler sCallbackHandler; + private void decCallbackHandlerRefCount() { + synchronized(sCallbackRefCount) { + if (sCallbackRefCount.decrementAndGet() == 0) { + sCallbackHandler.obtainMessage(CALLBACK_EXIT).sendToTarget(); + sCallbackHandler = null; + } + } + } + + static final HashMap sNetworkCallback = + new HashMap(); + static final AtomicInteger sCallbackRefCount = new AtomicInteger(0); + static CallbackHandler sCallbackHandler = null; private final static int LISTEN = 1; private final static int REQUEST = 2; private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, - NetworkCallback callback, int timeoutMs, int action, int legacyType) { - return sendRequestForNetwork(need, callback, getHandler(), timeoutMs, action, legacyType); - } - - private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, - NetworkCallback callback, Handler handler, int timeoutMs, int action, int legacyType) { - if (callback == null) { + NetworkCallback networkCallback, int timeoutMs, int action, + int legacyType) { + if (networkCallback == null) { throw new IllegalArgumentException("null NetworkCallback"); } if (need == null && action != REQUEST) { throw new IllegalArgumentException("null NetworkCapabilities"); } - // TODO: throw an exception if callback.networkRequest is not null. - // http://b/20701525 - final NetworkRequest request; try { - synchronized(sCallbacks) { - Messenger messenger = new Messenger(handler); - Binder binder = new Binder(); + incCallbackHandlerRefCount(); + synchronized(sNetworkCallback) { if (action == LISTEN) { - request = mService.listenForNetwork(need, messenger, binder); + networkCallback.networkRequest = mService.listenForNetwork(need, + new Messenger(sCallbackHandler), new Binder()); } else { - request = mService.requestNetwork( - need, messenger, timeoutMs, binder, legacyType); + networkCallback.networkRequest = mService.requestNetwork(need, + new Messenger(sCallbackHandler), timeoutMs, new Binder(), legacyType); } - if (request != null) { - sCallbacks.put(request, callback); + if (networkCallback.networkRequest != null) { + sNetworkCallback.put(networkCallback.networkRequest, networkCallback); } - callback.networkRequest = request; } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - return request; + if (networkCallback.networkRequest == null) decCallbackHandlerRefCount(); + return networkCallback.networkRequest; } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4cd7d41ca9..64ca629bf0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2591,14 +2591,28 @@ public class ConnectivityService extends IConnectivityManager.Stub "request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED); } + private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) { + if (mNetworkRequests.get(nri.request) != null && mNetworkForRequestId.get( + nri.request.requestId) == null) { + handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_UNAVAIL); + } + } + private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) { final NetworkRequestInfo nri = getNriForAppRequest( request, callingUid, "release NetworkRequest"); - if (nri == null) return; + if (nri != null) { + handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_RELEASED); + } + } - if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request); + private void handleRemoveNetworkRequest(final NetworkRequestInfo nri, final int whichCallback) { + final String logCallbackType = ConnectivityManager.getCallbackName(whichCallback); + if (VDBG || (DBG && nri.request.isRequest())) { + log("releasing " + nri.request + " (" + logCallbackType + ")"); + } nri.unlinkDeathRecipient(); - mNetworkRequests.remove(request); + mNetworkRequests.remove(nri.request); synchronized (mUidToNetworkRequestCount) { int requests = mUidToNetworkRequestCount.get(nri.mUid, 0); if (requests < 1) { @@ -2692,7 +2706,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } - callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0); + callCallbackForRequest(nri, null, whichCallback, 0); } @Override @@ -2929,6 +2943,11 @@ public class ConnectivityService extends IConnectivityManager.Stub handleRegisterNetworkRequestWithIntent(msg); break; } + case EVENT_TIMEOUT_NETWORK_REQUEST: { + NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj; + handleTimedOutNetworkRequest(nri); + break; + } case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: { handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1); break; diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index cb9d9629db..c5cca251c8 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -1077,7 +1077,8 @@ public class ConnectivityServiceTest extends AndroidTestCase { NETWORK_CAPABILITIES, LINK_PROPERTIES, LOSING, - LOST + LOST, + UNAVAILABLE } private static class CallbackInfo { @@ -1125,6 +1126,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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 */); @@ -2236,6 +2242,79 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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 }; From c11a8e2206691687e6b41c251fabceba0c4e1a2e Mon Sep 17 00:00:00 2001 From: Calvin On Date: Tue, 11 Oct 2016 15:10:46 -0700 Subject: [PATCH 03/19] Add option to skip and avoid captive portals. Test: ConnectivityServiceTest updated with test cases. Test: Manually tested against att-wifi in B42. Bug: 30222699 (cherry picked from commit dada145a85984063eedd6a871c71d14747763446) Change-Id: I90c0f97fe0e41de4059bceae7b56ab3a70145696 --- .../android/server/ConnectivityService.java | 16 ++++- .../server/ConnectivityServiceTest.java | 65 +++++++++++++++++-- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 64ca629bf0..eae4bc7822 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2257,11 +2257,19 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (mNetworkForNetId) { nai = mNetworkForNetId.get(netId); } - // If captive portal status has changed, update capabilities. + // If captive portal status has changed, update capabilities or disconnect. if (nai != null && (visible != nai.lastCaptivePortalDetected)) { final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; + if (nai.lastCaptivePortalDetected && + Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { + if (DBG) log("Avoiding captive portal network: " + nai.name()); + nai.asyncChannel.sendMessage( + NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT); + teardownUnneededNetwork(nai); + break; + } updateCapabilities(oldScore, nai, nai.networkCapabilities); } if (!visible) { @@ -2282,6 +2290,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return true; } + private int getCaptivePortalMode() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.CAPTIVE_PORTAL_MODE, + Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); + } + private boolean maybeHandleNetworkAgentInfoMessage(Message msg) { switch (msg.what) { default: diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index c5cca251c8..c5a5678a52 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -236,6 +236,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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; @@ -291,6 +292,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { mRedirectUrl = redirectUrl; mNetworkStatusReceived.open(); } + + @Override + protected void preventAutomaticReconnect() { + mPreventReconnectReceived.open(); + } }; // Waits for the NetworkAgent to be registered, which includes the creation of the // NetworkMonitor. @@ -375,11 +381,6 @@ public class ConnectivityServiceTest extends AndroidTestCase { mWrappedNetworkMonitor.gen204ProbeResult = 200; mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl; connect(false); - waitFor(new Criteria() { public boolean get() { - NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork()); - return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} }); - mWrappedNetworkMonitor.gen204ProbeResult = 500; - mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null; } public void disconnect() { @@ -391,6 +392,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { return new Network(mNetworkAgent.netId); } + public ConditionVariable getPreventReconnectReceived() { + return mPreventReconnectReceived; + } + public ConditionVariable getDisconnectedCV() { return mDisconnected; } @@ -597,6 +602,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { @Override protected CaptivePortalProbeResult isCaptivePortal() { + if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); } return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null); } } @@ -743,6 +749,9 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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 { @@ -1725,6 +1734,47 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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; @@ -1865,6 +1915,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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); From 65ecfacf150382ab97e00c3ef3b769cec2200d76 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 17 Oct 2016 15:54:51 +0900 Subject: [PATCH 04/19] ConnectivityServiceTest: mark flaky test as such This patch extracts into its own independent test a test sub-block looking for a race condition when not waiting on handlers to become idle: there is no way to prevent the race from not happening when looking for it this way. This makes the test flakky. This new independent test is tagged with @FlakkyTest(tolerance = 3). Test: ConnectivityServiceTest passes, with higher probability. Bug: 31479480 (cherry picked from commit 144810b6cf38ebc5c2e51ce37bb456724c5b15b3) Change-Id: I3c702bd981ed80ed606be0fb52d61eb3d7195a6f --- .../com/android/server/ConnectivityServiceTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index c5a5678a52..794d028123 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -68,6 +68,7 @@ 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; @@ -215,8 +216,20 @@ public class ConnectivityServiceTest extends AndroidTestCase { 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()) { From 91772021e91717048a2393471f33c6be76ece3d6 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 28 Oct 2016 12:37:38 +0900 Subject: [PATCH 05/19] Move FakeSettingsProvider to a common location. (cherry picked from commit 4163f9ca8fb2c9605b6ec0b9ef7763d6d68342fb) Test: runtest frameworks-util -c com.android.internal.util.test.FakeSettingsProviderTest Test: runtest frameworks-services -c com.android.server.ConnectivityServiceTest Test: runtest frameworks-services -c com.android.server.retaildemo.PreloadAppsInstallerTest Test: runtest frameworks-services -c com.android.server.retaildemo.RetailDemoModeServiceTest Bug: 31479480 Change-Id: I8d4d4de2937012dd33924f53e68f96241a9b2b4f --- .../src/com/android/server/ConnectivityServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index 794d028123..9bf3c2cf5e 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -75,8 +75,8 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import android.util.LogPrinter; -import com.android.internal.util.FakeSettingsProvider; import com.android.internal.util.WakeupMessage; +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; From ae5c443943eb8d7265e02b06baf2d85d415d524c Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 28 Oct 2016 12:56:03 +0900 Subject: [PATCH 06/19] De-guava BroadcastInterceptingContext and move it to testutils. Removing the static dependency on guava reduces test compile time by about 20 seconds on a Z840, thus substantially speeding up the compile/test cycle. Make FutureIntent public instead of package-private because it is used directly by NetworkPolicyManagementServiceTest, which as of this CL is now in a different package. (cherry picked from commit 6a64dd21782fc089474e1a4a5a7e0f8a193ba50d) Test: runtest frameworks-services -c com.android.server.ConnectivityServiceTest # PASS Test: runtest frameworks-services -c com.android.server.NetworkPolicyManagerServiceTest # PASS Test: runtest frameworks-services -c com.android.server.net.NetworkStatsServiceTest # PASS Test: runtest frameworks-services -c com.android.server.NetworkManagementServiceTest # Already failing. Bug: 31479480 Change-Id: Ifab32c9214e9caab71dbf93b3d3ca88df6f49636 --- .../server/ConnectivityServiceTest.java | 1 + .../server/net/NetworkStatsServiceTest.java | 523 ++++++++++-------- 2 files changed, 293 insertions(+), 231 deletions(-) diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index 9bf3c2cf5e..f95a8c6de5 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -76,6 +76,7 @@ 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; diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java index 728eb734c5..4b69eb3ac3 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java @@ -22,9 +22,6 @@ import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkStats.IFACE_ALL; -import static android.net.NetworkStats.METERED_ALL; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; @@ -43,21 +40,21 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; - import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.verify; +import static org.easymock.EasyMock.anyInt; +import static org.easymock.EasyMock.anyLong; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; import android.app.AlarmManager; +import android.app.IAlarmListener; +import android.app.IAlarmManager; +import android.app.PendingIntent; import android.app.usage.NetworkStatsManager; import android.content.Context; import android.content.Intent; @@ -66,7 +63,6 @@ import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsSession; import android.net.LinkProperties; -import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkState; @@ -84,10 +80,11 @@ import android.os.MessageQueue; import android.os.MessageQueue.IdleHandler; import android.os.Message; import android.os.PowerManager; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; +import android.os.WorkSource; import android.telephony.TelephonyManager; import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.Suppress; import android.util.TrustedTime; import com.android.internal.net.VpnInfo; @@ -98,14 +95,8 @@ import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; import libcore.io.IoUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.easymock.Capture; +import org.easymock.EasyMock; import java.io.File; import java.util.ArrayList; @@ -115,11 +106,11 @@ import java.util.List; /** * Tests for {@link NetworkStatsService}. * - * TODO: This test used to be really brittle because it used Easymock - it uses Mockito now, but - * still uses the Easymock structure, which could be simplified. + * TODO: This test is really brittle, largely due to overly-strict use of Easymock. + * Rewrite w/ Mockito. */ -@RunWith(AndroidJUnit4.class) -public class NetworkStatsServiceTest { +@LargeTest +public class NetworkStatsServiceTest extends AndroidTestCase { private static final String TAG = "NetworkStatsServiceTest"; private static final String TEST_IFACE = "test0"; @@ -146,12 +137,10 @@ public class NetworkStatsServiceTest { private BroadcastInterceptingContext mServiceContext; private File mStatsDir; - private @Mock INetworkManagementService mNetManager; - private @Mock TrustedTime mTime; - private @Mock NetworkStatsSettings mSettings; - private @Mock IConnectivityManager mConnManager; - private @Mock IBinder mBinder; - private @Mock AlarmManager mAlarmManager; + private INetworkManagementService mNetManager; + private TrustedTime mTime; + private NetworkStatsSettings mSettings; + private IConnectivityManager mConnManager; private IdleableHandlerThread mHandlerThread; private Handler mHandler; @@ -159,24 +148,32 @@ public class NetworkStatsServiceTest { private INetworkStatsSession mSession; private INetworkManagementEventObserver mNetworkObserver; - @Before + @Override public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - final Context context = InstrumentationRegistry.getContext(); + super.setUp(); - mServiceContext = new BroadcastInterceptingContext(context); - mStatsDir = context.getFilesDir(); + mServiceContext = new BroadcastInterceptingContext(getContext()); + mStatsDir = getContext().getFilesDir(); if (mStatsDir.exists()) { IoUtils.deleteContents(mStatsDir); } + mNetManager = createMock(INetworkManagementService.class); + + // TODO: Mock AlarmManager when migrating this test to Mockito. + AlarmManager alarmManager = (AlarmManager) mServiceContext + .getSystemService(Context.ALARM_SERVICE); + mTime = createMock(TrustedTime.class); + mSettings = createMock(NetworkStatsSettings.class); + mConnManager = createMock(IConnectivityManager.class); + PowerManager powerManager = (PowerManager) mServiceContext.getSystemService( Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mService = new NetworkStatsService( - mServiceContext, mNetManager, mAlarmManager, wakeLock, mTime, + mServiceContext, mNetManager, alarmManager, wakeLock, mTime, TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); mHandlerThread = new IdleableHandlerThread("HandlerThread"); @@ -193,20 +190,22 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(buildEmptyStats()); expectSystemReady(); + // catch INetworkManagementEventObserver during systemReady() + final Capture networkObserver = new Capture< + INetworkManagementEventObserver>(); + mNetManager.registerObserver(capture(networkObserver)); + expectLastCall().atLeastOnce(); + + replay(); mService.systemReady(); mSession = mService.openSession(); - assertNotNull("openSession() failed", mSession); + verifyAndReset(); - - // catch INetworkManagementEventObserver during systemReady() - ArgumentCaptor networkObserver = - ArgumentCaptor.forClass(INetworkManagementEventObserver.class); - verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); } - @After + @Override public void tearDown() throws Exception { IoUtils.deleteContents(mStatsDir); @@ -220,9 +219,10 @@ public class NetworkStatsServiceTest { mSession.close(); mService = null; + + super.tearDown(); } - @Test public void testNetworkStatsWifi() throws Exception { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. @@ -231,13 +231,15 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); // verify service has empty history for wifi assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - + verifyAndReset(); // modify some number on wifi, and trigger poll event incrementCurrentTime(HOUR_IN_MILLIS); @@ -246,11 +248,14 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); - + verifyAndReset(); // and bump forward again, with counters going higher. this is // important, since polling should correctly subtract last snapshot. @@ -260,14 +265,17 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); + verifyAndReset(); } - @Test public void testStatsRebootPersist() throws Exception { assertStatsFilesExist(false); @@ -278,13 +286,15 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); // verify service has empty history for wifi assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - + verifyAndReset(); // modify some number on wifi, and trigger poll event incrementCurrentTime(HOUR_IN_MILLIS); @@ -298,28 +308,33 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); + expectNetworkStatsPoll(); + mService.setUidForeground(UID_RED, false); mService.incrementOperationCount(UID_RED, 0xFAAD, 4); mService.setUidForeground(UID_RED, true); mService.incrementOperationCount(UID_RED, 0xFAAD, 6); + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, 512L, 4L, 256L, - 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, 512L, 4L, - 256L, 2L, 6); + assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4); + assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, + 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); - + verifyAndReset(); // graceful shutdown system, which should trigger persist of stats, and // clear any values in memory. expectCurrentTime(); expectDefaultSettings(); + replay(); mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN)); + verifyAndReset(); + assertStatsFilesExist(true); // boot through serviceReady() again @@ -328,22 +343,30 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(buildEmptyStats()); expectSystemReady(); + // catch INetworkManagementEventObserver during systemReady() + final Capture networkObserver = new Capture< + INetworkManagementEventObserver>(); + mNetManager.registerObserver(capture(networkObserver)); + expectLastCall().atLeastOnce(); + + replay(); mService.systemReady(); + mNetworkObserver = networkObserver.getValue(); + // after systemReady(), we should have historical stats loaded again assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, 512L, 4L, 256L, - 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, 512L, 4L, - 256L, 2L, 6); + assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4); + assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, + 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); + verifyAndReset(); } // TODO: simulate reboot to test bucket resize - @Test - @Ignore + @Suppress public void testStatsBucketResize() throws Exception { NetworkStatsHistory history = null; @@ -356,10 +379,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // modify some number on wifi, and trigger poll event incrementCurrentTime(2 * HOUR_IN_MILLIS); @@ -368,6 +393,9 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -375,7 +403,7 @@ public class NetworkStatsServiceTest { assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(2, history.size()); - + verifyAndReset(); // now change bucket duration setting and trigger another poll with // exact same values, which should resize existing buckets. @@ -383,6 +411,9 @@ public class NetworkStatsServiceTest { expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify identical stats, but spread across 4 buckets now @@ -390,10 +421,10 @@ public class NetworkStatsServiceTest { assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(4, history.size()); + verifyAndReset(); } - @Test public void testUidStatsAcrossNetworks() throws Exception { // pretend first mobile network comes online expectCurrentTime(); @@ -401,10 +432,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // create some traffic on first network incrementCurrentTime(HOUR_IN_MILLIS); @@ -416,8 +449,11 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_RED, 0xF00D, 10); + replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -425,7 +461,7 @@ public class NetworkStatsServiceTest { assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 10); assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 0); - + verifyAndReset(); // now switch networks; this also tests that we're okay with interfaces // disappearing, to verify we don't count backwards. @@ -439,11 +475,13 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); forcePollAndWaitForIdle(); - + verifyAndReset(); // create traffic on second network incrementCurrentTime(HOUR_IN_MILLIS); @@ -456,8 +494,11 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10); + replay(); forcePollAndWaitForIdle(); // verify original history still intact @@ -470,10 +511,10 @@ public class NetworkStatsServiceTest { assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); + verifyAndReset(); } - @Test public void testUidRemovedIsMoved() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -481,10 +522,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // create some traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -497,8 +540,11 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_RED, 0xFAAD, 10); + replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -506,7 +552,7 @@ public class NetworkStatsServiceTest { assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 0); assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); - + verifyAndReset(); // now pretend two UIDs are uninstalled, which should migrate stats to // special "removed" bucket. @@ -519,6 +565,9 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); + expectNetworkStatsPoll(); + + replay(); final Intent intent = new Intent(ACTION_UID_REMOVED); intent.putExtra(EXTRA_UID, UID_BLUE); mServiceContext.sendBroadcast(intent); @@ -532,10 +581,10 @@ public class NetworkStatsServiceTest { assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 10); + verifyAndReset(); } - @Test public void testUid3g4gCombinedByTemplate() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -543,10 +592,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // create some traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -556,13 +607,16 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_RED, 0xF00D, 5); + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5); - + verifyAndReset(); // now switch over to 4g network incrementCurrentTime(HOUR_IN_MILLIS); @@ -573,11 +627,13 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); forcePollAndWaitForIdle(); - + verifyAndReset(); // create traffic on second network incrementCurrentTime(HOUR_IN_MILLIS); @@ -589,15 +645,19 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_RED, 0xFAAD, 5); + replay(); forcePollAndWaitForIdle(); // verify that ALL_MOBILE template combines both assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 10); + + verifyAndReset(); } - @Test public void testSummaryForAllUid() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -605,10 +665,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // create some traffic for two apps incrementCurrentTime(HOUR_IN_MILLIS); @@ -619,14 +681,17 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_RED, 0xF00D, 1); + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 1); assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 0); - + verifyAndReset(); // now create more traffic in next hour, but only for one app incrementCurrentTime(HOUR_IN_MILLIS); @@ -637,29 +702,33 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L)); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // first verify entire history present NetworkStats stats = mSession.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50L, - 5L, 50L, 5L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 10L, - 1L, 10L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 2048L, 16L, 1024L, 8L, 0); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 50L, 5L, + 50L, 5L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 10L, 1L, 10L, + 1L, 1); + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2048L, 16L, + 1024L, 8L, 0); // now verify that recent history only contains one uid final long currentTime = currentTimeMillis(); stats = mSession.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 1024L, 8L, 512L, 4L, 0); + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, + 512L, 4L, 0); + + verifyAndReset(); } - @Test public void testForegroundBackground() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -667,10 +736,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // create some initial traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -680,13 +751,16 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); + expectNetworkStatsPoll(); + mService.incrementOperationCount(UID_RED, 0xF00D, 1); + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); - + verifyAndReset(); // now switch to foreground incrementCurrentTime(HOUR_IN_MILLIS); @@ -698,9 +772,12 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); + expectNetworkStatsPoll(); + mService.setUidForeground(UID_RED, true); mService.incrementOperationCount(UID_RED, 0xFAAD, 1); + replay(); forcePollAndWaitForIdle(); // test that we combined correctly @@ -710,59 +787,18 @@ public class NetworkStatsServiceTest { final NetworkStats stats = mSession.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(4, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, - 2L, 128L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, - 1L, 64L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - 32L, 2L, 32L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, METERED_NO, ROAMING_NO, 1L, - 1L, 1L, 1L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L, + 128L, 2L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, + 1L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 2L, + 32L, 2L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L, + 1L, 1); + + verifyAndReset(); } - @Test - public void testMetered() throws Exception { - // pretend that network comes online - expectCurrentTime(); - expectDefaultSettings(); - expectNetworkState(buildWifiState(true /* isMetered */)); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); - - mService.forceUpdateIfaces(); - - - // create some initial traffic - incrementCurrentTime(HOUR_IN_MILLIS); - expectCurrentTime(); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - // Note that all traffic from NetworkManagementService is tagged as METERED_NO and - // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it - // on top by inspecting the iface properties. - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, - 2L, 128L, 2L, 0L) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, - 1L, 64L, 1L, 0L)); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); - // verify entire history present - final NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - 128L, 2L, 128L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 64L, - 1L, 64L, 1L, 1); - } - - @Test public void testRoaming() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -770,24 +806,29 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // Create some traffic incrementCurrentTime(HOUR_IN_MILLIS); expectCurrentTime(); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); - // Note that all traffic from NetworkManagementService is tagged as METERED_NO and - // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it - // on top by inspecting the iface properties. + // Note that all traffic from NetworkManagementService is tagged as ROAMING_NO, because + // roaming isn't tracked at that layer. We layer it on top by inspecting the iface + // properties. expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO, - 128L, 2L, 128L, 2L, 0L) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO, 64L, - 1L, 64L, 1L, 0L)); + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L, + 128L, 2L, 0L) + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, + 1L, 0L)); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -797,13 +838,14 @@ public class NetworkStatsServiceTest { final NetworkStats stats = mSession.getSummaryForAllUid( sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_YES, - 128L, 2L, 128L, 2L, 0); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_YES, 64L, - 1L, 64L, 1L, 0); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L, + 128L, 2L, 0); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L, + 1L, 0); + + verifyAndReset(); } - @Test public void testTethering() throws Exception { // pretend first mobile network comes online expectCurrentTime(); @@ -811,10 +853,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); - + verifyAndReset(); // create some tethering traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -827,20 +871,22 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L); final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" }; final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1) - .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, - 0L); + .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L); expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0); assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0); + verifyAndReset(); } - @Test public void testRegisterUsageCallback() throws Exception { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. @@ -849,12 +895,16 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); expectBandwidthControlCheck(); + replay(); mService.forceUpdateIfaces(); // verify service has empty history for wifi assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + verifyAndReset(); + String callingPackage = "the.calling.package"; long thresholdInBytes = 1L; // very small; should be overriden by framework DataUsageRequest inputRequest = new DataUsageRequest( @@ -865,18 +915,23 @@ public class NetworkStatsServiceTest { LatchedHandler latchedHandler = new LatchedHandler(Looper.getMainLooper(), cv); Messenger messenger = new Messenger(latchedHandler); + // Allow binder to connect + IBinder mockBinder = createMock(IBinder.class); + mockBinder.linkToDeath((IBinder.DeathRecipient) anyObject(), anyInt()); + EasyMock.replay(mockBinder); + // Force poll expectCurrentTime(); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - - + expectNetworkStatsPoll(); + replay(); // Register and verify request and that binder was called DataUsageRequest request = mService.registerUsageCallback(callingPackage, inputRequest, - messenger, mBinder); + messenger, mockBinder); assertTrue(request.requestId > 0); assertTrue(Objects.equals(sTemplateWifi, request.template)); long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB @@ -886,11 +941,11 @@ public class NetworkStatsServiceTest { mHandler.sendMessage(mHandler.obtainMessage(-1)); mHandlerThread.waitForIdle(WAIT_TIMEOUT); - + verifyAndReset(); // Make sure that the caller binder gets connected - verify(mBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - + EasyMock.verify(mockBinder); + EasyMock.reset(mockBinder); // modify some number on wifi, and trigger poll event // not enough traffic to call data usage callback @@ -900,9 +955,13 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history + verifyAndReset(); assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); // make sure callback has not being called @@ -916,11 +975,14 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + + replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 4096000L, 4L, 8192000L, 8L, 0); - + verifyAndReset(); // Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED assertTrue(cv.block(WAIT_TIMEOUT)); @@ -928,7 +990,9 @@ public class NetworkStatsServiceTest { cv.close(); // Allow binder to disconnect - when(mBinder.unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt())).thenReturn(true); + expect(mockBinder.unlinkToDeath((IBinder.DeathRecipient) anyObject(), anyInt())) + .andReturn(true); + EasyMock.replay(mockBinder); // Unregister request mService.unregisterUsageRequest(request); @@ -938,10 +1002,9 @@ public class NetworkStatsServiceTest { assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType); // Make sure that the caller binder gets disconnected - verify(mBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); + EasyMock.verify(mockBinder); } - @Test public void testUnregisterUsageCallback_unknown_noop() throws Exception { String callingPackage = "the.calling.package"; long thresholdInBytes = 10 * 1024 * 1024; // 10 MB @@ -971,18 +1034,18 @@ public class NetworkStatsServiceTest { // verify summary API final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end); - assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO, - rxBytes, rxPackets, txBytes, txPackets, operations); + assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, rxBytes, + rxPackets, txBytes, txPackets, operations); } private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) throws Exception { - assertUidTotal(template, uid, SET_ALL, METERED_ALL, ROAMING_ALL, rxBytes, rxPackets, - txBytes, txPackets, operations); + assertUidTotal(template, uid, SET_ALL, ROAMING_ALL, rxBytes, rxPackets, txBytes, txPackets, + operations); } - private void assertUidTotal(NetworkTemplate template, int uid, int set, int metered, - int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) + private void assertUidTotal(NetworkTemplate template, int uid, int set, int roaming, + long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) throws Exception { // verify history API final NetworkStatsHistory history = mSession.getHistoryForUid( @@ -993,35 +1056,38 @@ public class NetworkStatsServiceTest { // verify summary API final NetworkStats stats = mSession.getSummaryForAllUid( template, Long.MIN_VALUE, Long.MAX_VALUE, false); - assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, metered, roaming, rxBytes, rxPackets, - txBytes, txPackets, operations); + assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, roaming, rxBytes, rxPackets, txBytes, + txPackets, operations); } private void expectSystemReady() throws Exception { + mNetManager.setGlobalAlert(anyLong()); + expectLastCall().atLeastOnce(); + expectNetworkStatsSummary(buildEmptyStats()); expectBandwidthControlCheck(); } private void expectNetworkState(NetworkState... state) throws Exception { - when(mConnManager.getAllNetworkState()).thenReturn(state); + expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); final LinkProperties linkProp = state.length > 0 ? state[0].linkProperties : null; - when(mConnManager.getActiveLinkProperties()).thenReturn(linkProp); + expect(mConnManager.getActiveLinkProperties()).andReturn(linkProp).atLeastOnce(); } private void expectNetworkStatsSummary(NetworkStats summary) throws Exception { - when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]); + expect(mConnManager.getAllVpnInfo()).andReturn(new VpnInfo[0]).atLeastOnce(); expectNetworkStatsSummaryDev(summary); expectNetworkStatsSummaryXt(summary); } private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception { - when(mNetManager.getNetworkStatsSummaryDev()).thenReturn(summary); + expect(mNetManager.getNetworkStatsSummaryDev()).andReturn(summary).atLeastOnce(); } private void expectNetworkStatsSummaryXt(NetworkStats summary) throws Exception { - when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary); + expect(mNetManager.getNetworkStatsSummaryXt()).andReturn(summary).atLeastOnce(); } private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { @@ -1031,10 +1097,11 @@ public class NetworkStatsServiceTest { private void expectNetworkStatsUidDetail( NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats) throws Exception { - when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail); + expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce(); // also include tethering details, since they are folded into UID - when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats); + expect(mNetManager.getNetworkStatsTethering()) + .andReturn(tetherStats).atLeastOnce(); } private void expectDefaultSettings() throws Exception { @@ -1043,33 +1110,38 @@ public class NetworkStatsServiceTest { private void expectSettings(long persistBytes, long bucketDuration, long deleteAge) throws Exception { - when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS); - when(mSettings.getTimeCacheMaxAge()).thenReturn(DAY_IN_MILLIS); - when(mSettings.getSampleEnabled()).thenReturn(true); + expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes(); + expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes(); + expect(mSettings.getSampleEnabled()).andReturn(true).anyTimes(); final Config config = new Config(bucketDuration, deleteAge, deleteAge); - when(mSettings.getDevConfig()).thenReturn(config); - when(mSettings.getXtConfig()).thenReturn(config); - when(mSettings.getUidConfig()).thenReturn(config); - when(mSettings.getUidTagConfig()).thenReturn(config); + expect(mSettings.getDevConfig()).andReturn(config).anyTimes(); + expect(mSettings.getXtConfig()).andReturn(config).anyTimes(); + expect(mSettings.getUidConfig()).andReturn(config).anyTimes(); + expect(mSettings.getUidTagConfig()).andReturn(config).anyTimes(); - when(mSettings.getGlobalAlertBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getDevPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getXtPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getUidPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getUidTagPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); + expect(mSettings.getGlobalAlertBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); + expect(mSettings.getDevPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); + expect(mSettings.getXtPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); + expect(mSettings.getUidPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); + expect(mSettings.getUidTagPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); } private void expectCurrentTime() throws Exception { - when(mTime.forceRefresh()).thenReturn(false); - when(mTime.hasCache()).thenReturn(true); - when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis()); - when(mTime.getCacheAge()).thenReturn(0L); - when(mTime.getCacheCertainty()).thenReturn(0L); + expect(mTime.forceRefresh()).andReturn(false).anyTimes(); + expect(mTime.hasCache()).andReturn(true).anyTimes(); + expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes(); + expect(mTime.getCacheAge()).andReturn(0L).anyTimes(); + expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); + } + + private void expectNetworkStatsPoll() throws Exception { + mNetManager.setGlobalAlert(anyLong()); + expectLastCall().anyTimes(); } private void expectBandwidthControlCheck() throws Exception { - when(mNetManager.isBandwidthControlEnabled()).thenReturn(true); + expect(mNetManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce(); } private void assertStatsFilesExist(boolean exist) { @@ -1082,8 +1154,8 @@ public class NetworkStatsServiceTest { } private static void assertValues(NetworkStats stats, String iface, int uid, int set, - int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes, - long txPackets, int operations) { + int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, + int operations) { final NetworkStats.Entry entry = new NetworkStats.Entry(); List sets = new ArrayList<>(); if (set == SET_DEFAULT || set == SET_ALL) { @@ -1101,21 +1173,11 @@ public class NetworkStatsServiceTest { roamings.add(ROAMING_YES); } - List meterings = new ArrayList<>(); - if (metered == METERED_NO || metered == METERED_ALL) { - meterings.add(METERED_NO); - } - if (metered == METERED_YES || metered == METERED_ALL) { - meterings.add(METERED_YES); - } - for (int s : sets) { for (int r : roamings) { - for (int m : meterings) { - final int i = stats.findIndex(iface, uid, s, tag, m, r); - if (i != -1) { - entry.add(stats.getValues(i, null)); - } + final int i = stats.findIndex(iface, uid, s, tag, r); + if (i != -1) { + entry.add(stats.getValues(i, null)); } } } @@ -1138,19 +1200,11 @@ public class NetworkStatsServiceTest { } private static NetworkState buildWifiState() { - return buildWifiState(false); - } - - private static NetworkState buildWifiState(boolean isMetered) { final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null); info.setDetailedState(DetailedState.CONNECTED, null, null); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - if (!isMetered) { - capabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } - return new NetworkState(info, prop, capabilities, null, null, TEST_SSID); + return new NetworkState(info, prop, null, null, null, TEST_SSID); } private static NetworkState buildMobile3gState(String subscriberId) { @@ -1164,8 +1218,7 @@ public class NetworkStatsServiceTest { info.setRoaming(isRoaming); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - return new NetworkState(info, prop, capabilities, null, subscriberId, null); + return new NetworkState(info, prop, null, null, subscriberId, null); } private static NetworkState buildMobile4gState(String iface) { @@ -1173,8 +1226,7 @@ public class NetworkStatsServiceTest { info.setDetailedState(DetailedState.CONNECTED, null, null); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(iface); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - return new NetworkState(info, prop, capabilities, null, null, null); + return new NetworkState(info, prop, null, null, null, null); } private NetworkStats buildEmptyStats() { @@ -1197,6 +1249,15 @@ public class NetworkStatsServiceTest { mElapsedRealtime += duration; } + private void replay() { + EasyMock.replay(mNetManager, mTime, mSettings, mConnManager); + } + + private void verifyAndReset() { + EasyMock.verify(mNetManager, mTime, mSettings, mConnManager); + EasyMock.reset(mNetManager, mTime, mSettings, mConnManager); + } + private void forcePollAndWaitForIdle() { mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // Send dummy message to make sure that any previous message has been handled From ebc2b946ee4fe58d5d3467bdc558cdd69dbd83a3 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 28 Oct 2016 12:48:36 +0900 Subject: [PATCH 07/19] Move the connectivity tests to frameworks/base/tests/net. This will give us a good place to put all the networking tests. Fix: 31479480 Test: adb shell am instrument -w -e notClass com.android.server.connectivity.tethering.TetherInterfaceStateMachineTest 'com.android.frameworks.tests.net/android.support.test.runner.AndroidJUnitRunner' # PASS (cherry picked from commit 5a7c486d70cd6a540a3f87ab51bd243ea0225cf1) Change-Id: I993eeaa5dec001c39389023f355f506129b356e7 --- .../server/ConnectivityServiceTest.java | 2791 ----------------- .../server/ConnectivityServiceTest.java | 254 +- .../IpConnectivityEventBuilderTest.java | 33 +- .../IpConnectivityMetricsTest.java | 27 +- .../connectivity/LingerMonitorTest.java | 16 - .../NetdEventListenerServiceTest.java | 17 +- .../android/server/connectivity/VpnTest.java | 91 +- 7 files changed, 149 insertions(+), 3080 deletions(-) delete mode 100644 services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java 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)); + } } } From 0aa0f341bafe77926b5f71fbfd893c63261c518e Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Thu, 27 Oct 2016 15:05:50 -0700 Subject: [PATCH 08/19] [CS] Remove timeout event after first available Guarantees that timeouts are only delivered if a network never becomes available. Once a network is available the timeout is canceled. Bug: 31402633 Test: all timeout related unit tests pass (new one added) (cherry picked from commit 5eba9d7061e8bc555a1e7c62b541cb1895371899) Change-Id: I7cd3086544c881915fc6dbf14b87a24ab0cd8748 --- .../android/server/ConnectivityService.java | 1 + .../server/ConnectivityServiceTest.java | 47 ++++++++++++++----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index eae4bc7822..8c38ed63e6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5319,6 +5319,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // notify only this one new request of the current state protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) { int notifyType = ConnectivityManager.CALLBACK_AVAILABLE; + mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri); if (nri.mPendingIntent == null) { callCallbackForRequest(nri, nai, notifyType, 0); } else { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index f95a8c6de5..a06577e6da 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -727,10 +727,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { static private void waitFor(Criteria criteria) { int delays = 0; while (!criteria.get()) { - try { - Thread.sleep(50); - } catch (InterruptedException e) { - } + sleepFor(50); if (++delays == 10) fail(); } } @@ -2327,10 +2324,30 @@ public class ConnectivityServiceTest extends AndroidTestCase { networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); // pass timeout and validate that UNAVAILABLE is not called - try { - Thread.sleep(15); - } catch (InterruptedException e) { - } + 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); networkCallback.assertNoCallback(); } @@ -2372,10 +2389,7 @@ 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! - try { - Thread.sleep(15); - } catch (InterruptedException e) { - } + sleepFor(15); networkCallback.assertNoCallback(); // create a network satisfying request - validate that request not triggered @@ -2788,4 +2802,13 @@ public class ConnectivityServiceTest extends AndroidTestCase { mCm.unregisterNetworkCallback(pendingIntent); } } + + /* test utilities */ + static private void sleepFor(int ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + } + + } } From deebea61361d7a6e8effade982bc1651dd611f3f Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 13 Oct 2016 13:16:16 +0900 Subject: [PATCH 09/19] IpConnectivity metrics: add version number This patch adds a version field to ipconnectivity.proto and populates it to 2, which is the logical version number for NYC-MR2. Test: IpConnectivity{EventBuilder,Metrics}Test pass Bug: 32127906 (cherry picked from commit f04b01f0a0ab2ca3faa3ac73e2973dfa02e65d13) Change-Id: If8f167c0dc4c1abe0e235e2adfd131168a4ddc52 --- .../IpConnectivityEventBuilderTest.java | 33 ++++++++++++------- .../IpConnectivityMetricsTest.java | 3 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index aed3635245..84f0f9040b 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java @@ -71,7 +71,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " transport_types: 3", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -93,7 +94,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " state_transition: \"SomeState\"", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -114,7 +116,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " state_transition: \"\"", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -160,7 +163,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " return_codes: 178", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -181,7 +185,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " latency_ms: 5678", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -200,7 +205,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"wlan0\"", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -223,7 +229,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " >", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -248,7 +255,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " probe_result: 204", " probe_type: 1", " >", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -274,7 +282,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " program_length: 2048", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -305,7 +314,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " zero_lifetime_ras: 1", " >", " time_ms: 1", - ">"); + ">", + "version: 2"); verifySerialization(want, ev); } @@ -332,7 +342,8 @@ 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 3fc89b9ff1..8bdc829f7b 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -204,7 +204,8 @@ public class IpConnectivityMetricsTest extends TestCase { " router_lifetime: 2000", " >", " time_ms: 700", - ">"); + ">", + "version: 2"); verifySerialization(want, getdump("flush")); } From ce2cfa545d1b05d013c94e13e6849a264a3d353d Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 19 Oct 2016 11:17:28 +0900 Subject: [PATCH 10/19] IpConnectivityMetrics reads buffer size in settings Test: IpConnectivityMetricsTest passes. Also manually changed the new setting and verified the buffer size is as expected after flushing the buffer. Bug: 32198637 (cherry picked from commit 6d8c1dfe4bff0d0f78c1dbde9520b3a7da26f220) Change-Id: Iefbeac3a688b260fb3f92dfe0bfd9db28e26749d --- .../android/server/connectivity/IpConnectivityMetricsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index 8bdc829f7b..14b5cbeb92 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -57,7 +57,7 @@ public class IpConnectivityMetricsTest extends TestCase { public void setUp() { MockitoAnnotations.initMocks(this); - mService = new IpConnectivityMetrics(mCtx); + mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000); } public void testLoggingEvents() throws Exception { From d6114b0eda2c026f20a2d2f24de7992935e38ce0 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 12 Mar 2016 16:29:54 -0800 Subject: [PATCH 11/19] Add a null check for the OnStartTetheringCallback. This avoids a NullPointerException when trying to call the callback and gives a more readable error message. (cherry picked from commit 35e99ea8ef62482b81c0ce043fcd5acc96ad257d) Change-Id: Ia419ff68ef10f308f9e44be47420e27099ee6070 --- core/java/android/net/ConnectivityManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 43c8c81da2..772a2ccc57 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2079,6 +2079,8 @@ public class ConnectivityManager { @SystemApi public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { + checkNotNull(callback, "OnStartTetheringCallback cannot be null."); + ResultReceiver wrappedCallback = new ResultReceiver(handler) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -2089,6 +2091,7 @@ public class ConnectivityManager { } } }; + try { mService.startTethering(type, wrappedCallback, showProvisioningUi); } catch (RemoteException e) { From 03eeaae5f0c611db021f6368eb2e24cc7d8d91db Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 6 Jul 2016 22:53:17 +0900 Subject: [PATCH 12/19] ConnectivityManager: a simpler CallbackHandler This patch simplifies CallbackHandler in the following way: - CallbackHandler directly uses the static references to sNetworkCallback and sCallbackRefCount. This allows to remove instance fields in CallbackHandler. - CallbackHandler does not have a reference to ConnectivityManager anymore - CallbackHandler.getObject() is now generic in a type-safe way. Test: ConnectivityServiceTest passes Bug: 28537383 Bug: 32130437 (cherry picked from commit 0b42baf68a7e52e1924277d8e2361bd93975a0ba) Change-Id: I1b5fe2a361b5f623a8310ae698497c83d72f3034 --- .../java/android/net/ConnectivityManager.java | 68 +++++++++---------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 772a2ccc57..780a9c8acf 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2690,24 +2690,17 @@ public class ConnectivityManager { } private class CallbackHandler extends Handler { - private final HashMapmCallbackMap; - private final AtomicInteger mRefCount; private static final String TAG = "ConnectivityManager.CallbackHandler"; - private final ConnectivityManager mCm; private static final boolean DBG = false; - CallbackHandler(Looper looper, HashMapcallbackMap, - AtomicInteger refCount, ConnectivityManager cm) { + CallbackHandler(Looper looper) { super(looper); - mCallbackMap = callbackMap; - mRefCount = refCount; - mCm = cm; } @Override public void handleMessage(Message message) { - NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class); - Network network = (Network) getObject(message, Network.class); + NetworkRequest request = getObject(message, NetworkRequest.class); + Network network = getObject(message, Network.class); if (DBG) { Log.d(TAG, whatToString(message.what) + " for network " + network); } @@ -2750,9 +2743,7 @@ public class ConnectivityManager { case CALLBACK_CAP_CHANGED: { NetworkCallback callback = getCallback(request, "CAP_CHANGED"); if (callback != null) { - NetworkCapabilities cap = (NetworkCapabilities)getObject(message, - NetworkCapabilities.class); - + NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); callback.onCapabilitiesChanged(network, cap); } break; @@ -2760,9 +2751,7 @@ public class ConnectivityManager { case CALLBACK_IP_CHANGED: { NetworkCallback callback = getCallback(request, "IP_CHANGED"); if (callback != null) { - LinkProperties lp = (LinkProperties)getObject(message, - LinkProperties.class); - + LinkProperties lp = getObject(message, LinkProperties.class); callback.onLinkPropertiesChanged(network, lp); } break; @@ -2783,12 +2772,12 @@ public class ConnectivityManager { } case CALLBACK_RELEASED: { NetworkCallback callback = null; - synchronized(mCallbackMap) { - callback = mCallbackMap.remove(request); + synchronized(sCallbacks) { + callback = sCallbacks.remove(request); } if (callback != null) { - synchronized(mRefCount) { - if (mRefCount.decrementAndGet() == 0) { + synchronized(sCallbackRefCount) { + if (sCallbackRefCount.decrementAndGet() == 0) { getLooper().quit(); } } @@ -2809,14 +2798,14 @@ public class ConnectivityManager { } } - private Object getObject(Message msg, Class c) { - return msg.getData().getParcelable(c.getSimpleName()); + private T getObject(Message msg, Class c) { + return (T) msg.getData().getParcelable(c.getSimpleName()); } private NetworkCallback getCallback(NetworkRequest req, String name) { NetworkCallback callback; - synchronized(mCallbackMap) { - callback = mCallbackMap.get(req); + synchronized(sCallbacks) { + callback = sCallbacks.get(req); } if (callback == null) { Log.e(TAG, "callback not found for " + name + " message"); @@ -2831,8 +2820,7 @@ public class ConnectivityManager { // TODO: switch this to ConnectivityThread HandlerThread callbackThread = new HandlerThread("ConnectivityManager"); callbackThread.start(); - sCallbackHandler = new CallbackHandler(callbackThread.getLooper(), - sNetworkCallback, sCallbackRefCount, this); + sCallbackHandler = new CallbackHandler(callbackThread.getLooper()); } } } @@ -2846,8 +2834,7 @@ public class ConnectivityManager { } } - static final HashMap sNetworkCallback = - new HashMap(); + static final HashMap sCallbacks = new HashMap<>(); static final AtomicInteger sCallbackRefCount = new AtomicInteger(0); static CallbackHandler sCallbackHandler = null; @@ -2863,25 +2850,32 @@ public class ConnectivityManager { if (need == null && action != REQUEST) { throw new IllegalArgumentException("null NetworkCapabilities"); } + // TODO: throw an exception if networkCallback.networkRequest is not null. + // http://b/20701525 + final NetworkRequest request; try { incCallbackHandlerRefCount(); - synchronized(sNetworkCallback) { + synchronized(sCallbacks) { + Messenger messenger = new Messenger(sCallbackHandler); + Binder binder = new Binder(); if (action == LISTEN) { - networkCallback.networkRequest = mService.listenForNetwork(need, - new Messenger(sCallbackHandler), new Binder()); + request = mService.listenForNetwork(need, messenger, binder); } else { - networkCallback.networkRequest = mService.requestNetwork(need, - new Messenger(sCallbackHandler), timeoutMs, new Binder(), legacyType); + request = mService.requestNetwork( + need, messenger, timeoutMs, binder, legacyType); } - if (networkCallback.networkRequest != null) { - sNetworkCallback.put(networkCallback.networkRequest, networkCallback); + if (request != null) { + sCallbacks.put(request, networkCallback); } + networkCallback.networkRequest = request; } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (networkCallback.networkRequest == null) decCallbackHandlerRefCount(); - return networkCallback.networkRequest; + if (request == null) { + decCallbackHandlerRefCount(); + } + return request; } /** From eba4b5b0bdde291245270b63040ce5dcdeea3116 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 7 Jul 2016 10:15:56 +0900 Subject: [PATCH 13/19] ConnectivityManager: use ConnectivityThread looper This patch removes the static singleton looper used by ConnectivityManager and instead uses the common ConnectivityThread. This allows to removes the static atomic counter used to track the number of registered NetworkCallback in ConnectivityManager, because the looper is not turned off anymore when no callbacks are registered. Also an overloaded version of sendRequestForNetwork is added taking as a new parameter a Handler. This will allow to overload various callback and request related API calls with user provided Handlers. Test: ConnectivityServiceTest passes Bug: 26749700 Bug: 28537383 Bug: 32130437 (cherry picked from commit 3b41f05d6803679795ba4fe1e1f5aea86dfd93b6) Change-Id: If956addbf8e7b11b36a4b966de7fca00e8f362c1 --- .../java/android/net/ConnectivityManager.java | 59 +++++++------------ 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 780a9c8acf..51431ebfaf 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2660,6 +2660,7 @@ public class ConnectivityManager { public static final int CALLBACK_IP_CHANGED = BASE + 7; /** @hide */ public static final int CALLBACK_RELEASED = BASE + 8; + // TODO: consider deleting CALLBACK_EXIT and shifting following enum codes down by 1. /** @hide */ public static final int CALLBACK_EXIT = BASE + 9; /** @hide obj = NetworkCapabilities, arg1 = seq number */ @@ -2771,24 +2772,16 @@ public class ConnectivityManager { break; } case CALLBACK_RELEASED: { - NetworkCallback callback = null; + final NetworkCallback callback; synchronized(sCallbacks) { callback = sCallbacks.remove(request); } - if (callback != null) { - synchronized(sCallbackRefCount) { - if (sCallbackRefCount.decrementAndGet() == 0) { - getLooper().quit(); - } - } - } else { + if (callback == null) { Log.e(TAG, "callback not found for RELEASED message"); } break; } case CALLBACK_EXIT: { - Log.d(TAG, "Listener quitting"); - getLooper().quit(); break; } case EXPIRE_LEGACY_REQUEST: { @@ -2814,49 +2807,40 @@ public class ConnectivityManager { } } - private void incCallbackHandlerRefCount() { - synchronized(sCallbackRefCount) { - if (sCallbackRefCount.incrementAndGet() == 1) { - // TODO: switch this to ConnectivityThread - HandlerThread callbackThread = new HandlerThread("ConnectivityManager"); - callbackThread.start(); - sCallbackHandler = new CallbackHandler(callbackThread.getLooper()); - } - } - } - - private void decCallbackHandlerRefCount() { - synchronized(sCallbackRefCount) { - if (sCallbackRefCount.decrementAndGet() == 0) { - sCallbackHandler.obtainMessage(CALLBACK_EXIT).sendToTarget(); - sCallbackHandler = null; + private CallbackHandler getHandler() { + synchronized (sCallbacks) { + if (sCallbackHandler == null) { + sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper()); } + return sCallbackHandler; } } static final HashMap sCallbacks = new HashMap<>(); - static final AtomicInteger sCallbackRefCount = new AtomicInteger(0); - static CallbackHandler sCallbackHandler = null; + static CallbackHandler sCallbackHandler; private final static int LISTEN = 1; private final static int REQUEST = 2; private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, - NetworkCallback networkCallback, int timeoutMs, int action, - int legacyType) { - if (networkCallback == null) { + NetworkCallback callback, int timeoutMs, int action, int legacyType) { + return sendRequestForNetwork(need, callback, getHandler(), timeoutMs, action, legacyType); + } + + private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, + NetworkCallback callback, Handler handler, int timeoutMs, int action, int legacyType) { + if (callback == null) { throw new IllegalArgumentException("null NetworkCallback"); } if (need == null && action != REQUEST) { throw new IllegalArgumentException("null NetworkCapabilities"); } - // TODO: throw an exception if networkCallback.networkRequest is not null. + // TODO: throw an exception if callback.networkRequest is not null. // http://b/20701525 final NetworkRequest request; try { - incCallbackHandlerRefCount(); synchronized(sCallbacks) { - Messenger messenger = new Messenger(sCallbackHandler); + Messenger messenger = new Messenger(handler); Binder binder = new Binder(); if (action == LISTEN) { request = mService.listenForNetwork(need, messenger, binder); @@ -2865,16 +2849,13 @@ public class ConnectivityManager { need, messenger, timeoutMs, binder, legacyType); } if (request != null) { - sCallbacks.put(request, networkCallback); + sCallbacks.put(request, callback); } - networkCallback.networkRequest = request; + callback.networkRequest = request; } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (request == null) { - decCallbackHandlerRefCount(); - } return request; } From 232e75c65bc09cfe5d39e79ae1633b24f2aec67f Mon Sep 17 00:00:00 2001 From: Jeremy Joslin Date: Mon, 8 Aug 2016 16:07:37 -0700 Subject: [PATCH 14/19] VPN network stat accounting changes. Properly account for VPN apps that make heavy use of the tun interface. Prior to this change a VPN app could be incorrectly charged for more data than it actually used if it sent more traffic through the tun interface than the underlying interface. This change excludes VPN app traffic on the tun interface from the adjustment pool and doesn't redistribute traffic to the VPN app. Instead all of the redistributed traffic is deducted from the VPN app which effectively represents any overhead incurred by the VPN app. BUG: 30557871 (cherry picked from commit 13dd0e99ba3a435dc59502ec06022958546f12be) Change-Id: I06f01aa8fe5fdc06b2d36cfb9c68feb244c2e5de --- .../src/android/net/NetworkStatsTest.java | 528 ++++++++---------- 1 file changed, 239 insertions(+), 289 deletions(-) diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index eb85eb445c..d48a67a4c7 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -16,9 +16,6 @@ package android.net; -import static android.net.NetworkStats.METERED_ALL; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; @@ -48,124 +45,103 @@ public class NetworkStatsTest extends TestCase { private static final long TEST_START = 1194220800000L; public void testFindIndex() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 5) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L, - 8L, 0L, 0L, 10) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L, - 1024L, 8L, 11) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 0L, 0L, - 1024L, 8L, 11) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L, - 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 1024L, - 8L, 1024L, 8L, 12); + final NetworkStats stats = new NetworkStats(TEST_START, 4) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L, + 0L, 10) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L, + 8L, 11) + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, + 1024L, 8L, 12) + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L, + 1024L, 8L, 12); - assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_YES)); - assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO)); - assertEquals(2, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_NO)); - assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO)); - assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO)); - assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO)); + assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES)); + assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO)); + assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO)); + assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO)); + assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_NO)); } public void testFindIndexHinted() { final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L, - 8L, 0L, 0L, 10) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L, - 1024L, 8L, 11) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L, - 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 0L, 0L, - 1024L, 8L, 11) - .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 0L, 0L, - 1024L, 8L, 11) - .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L, - 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 1024L, - 8L, 1024L, 8L, 12); + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L, + 0L, 10) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L, + 8L, 11) + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, + 1024L, 8L, 12) + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 1024L, 8L, + 0L, 0L, 10) + .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 0L, 0L, 1024L, + 8L, 11) + .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, + 1024L, 8L, 12) + .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L, + 1024L, 8L, 12); // verify that we correctly find across regardless of hinting for (int hint = 0; hint < stats.size(); hint++) { assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, hint)); + ROAMING_NO, hint)); assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, hint)); + ROAMING_NO, hint)); assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, hint)); + ROAMING_NO, hint)); assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, hint)); + ROAMING_NO, hint)); assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, - METERED_NO, ROAMING_NO, hint)); - assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, - METERED_YES, ROAMING_NO, hint)); + ROAMING_NO, hint)); + assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, + ROAMING_NO, hint)); assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, hint)); - assertEquals(7, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_YES, hint)); + ROAMING_YES, hint)); assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, hint)); + ROAMING_NO, hint)); } } public void testAddEntryGrow() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 4); + final NetworkStats stats = new NetworkStats(TEST_START, 3); assertEquals(0, stats.size()); - assertEquals(4, stats.internalSize()); + assertEquals(3, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1L, 1L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L, + 2L, 3); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L, 2L, + 2L, 4); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L, 2L, + 2L, 5); + + assertEquals(3, stats.size()); + assertEquals(3, stats.internalSize()); + + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, 40L, 4L, + 40L, 7); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, 50L, 4L, + 40L, 8); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, 60L, 5L, + 50L, 10); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, 70L, 5L, + 50L, 11); + + assertEquals(7, stats.size()); + assertTrue(stats.internalSize() >= 7); + + assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L, 2L, 3); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 2L, 2L, + assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L, 2L, 2L, 4); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 3L, - 3L, 2L, 2L, 5); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 3L, - 3L, 2L, 2L, 5); - - assertEquals(4, stats.size()); - assertEquals(4, stats.internalSize()); - - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4L, + assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L, + 2L, 2L, 5); + assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, 40L, 4L, 40L, 7); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5L, + assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, 50L, 4L, 40L, 8); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 6L, + assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, 60L, 5L, 50L, 10); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 7L, + assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, 70L, 5L, 50L, 11); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 7L, - 70L, 5L, 50L, 11); - - assertEquals(9, stats.size()); - assertTrue(stats.internalSize() >= 9); - - assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 1L, 1L, 2L, 2L, 3); - assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 2L, 2L, 2L, 2L, 4); - assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - 3L, 3L, 2L, 2L, 5); - assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_YES, 3L, 3L, 2L, 2L, 5); - assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 4L, 40L, 4L, 40L, 7); - assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 5L, 50L, 4L, 40L, 8); - assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 6L, 60L, 5L, 50L, 10); - assertValues(stats, 7, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - 7L, 70L, 5L, 50L, 11); - assertValues(stats, 8, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_YES, 7L, 70L, 5L, 50L, 11); } public void testCombineExisting() throws Exception { @@ -176,18 +152,20 @@ public class NetworkStatsTest extends TestCase { stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L, -128L, -1L, -1); - assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 384L, 3L, 128L, 1L, 9); - assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, METERED_NO, ROAMING_NO, 128L, - 1L, 128L, 1L, 2); + assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_NO, 384L, 3L, + 128L, 1L, 9); + assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_NO, 128L, 1L, 128L, + 1L, 2); // now try combining that should create row - stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 128L, 1L, 128L, 1L, 3); - stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 256L, 2L, 256L, 2L, 6); + stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, + 128L, 1L, 3); + assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 1L, + 128L, 1L, 3); + stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, + 128L, 1L, 3); + assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 256L, 2L, + 256L, 2L, 6); } public void testSubtractIdenticalData() throws Exception { @@ -202,10 +180,10 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // identical data should result in zero delta - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, - 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, - 0L, 0L, 0L, 0); + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, + 0L, 0); + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, + 0L, 0); } public void testSubtractIdenticalRows() throws Exception { @@ -220,10 +198,10 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // expect delta between measurements - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1L, - 1L, 2L, 1L, 4); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 3L, - 1L, 4L, 1L, 8); + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L, + 1L, 4); + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 3L, 1L, 4L, + 1L, 8); } public void testSubtractNewRows() throws Exception { @@ -239,12 +217,12 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // its okay to have new rows - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, - 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, - 0L, 0L, 0L, 0); - assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 1024L, 8L, 1024L, 8L, 20); + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, + 0L, 0); + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, + 0L, 0); + assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, + 1024L, 8L, 20); } public void testSubtractMissingRows() throws Exception { @@ -259,8 +237,8 @@ public class NetworkStatsTest extends TestCase { // should silently drop omitted rows assertEquals(1, result.size()); - assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 1L, 2L, 3L, 4L, 0); + assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, + 2L, 3L, 4L, 0); assertEquals(4L, result.getTotalBytes()); } @@ -285,22 +263,13 @@ public class NetworkStatsTest extends TestCase { .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L); assertEquals(64L, uidTag.getTotalBytes()); - final NetworkStats uidMetered = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, 0L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L, - 0L, 0L, 0L); - assertEquals(96L, uidMetered.getTotalBytes()); - final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, 0L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 32L, 0L, - 0L, 0L, 0L); + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, 0L, + 0L); assertEquals(96L, uidRoaming.getTotalBytes()); } @@ -314,95 +283,95 @@ public class NetworkStatsTest extends TestCase { public void testGroupedByIfaceAll() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 3) - .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, 0L, + .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L, + 20L) + .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L, 20L) - .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO, 128L, - 8L, 0L, 2L, 20L) - .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES, 128L, 8L, 0L, - 2L, 20L); + .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, 2L, + 20L); final NetworkStats grouped = uidStats.groupedByIface(); assertEquals(3, uidStats.size()); assertEquals(1, grouped.size()); - assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - 384L, 24L, 0L, 6L, 0L); + assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L, + 6L, 0L); } public void testGroupedByIface() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 7) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, - 0L, 2L, 20L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 512L, - 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, 4L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, + 2L, 20L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, + 0L, 0L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L, + 0L) + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 512L, - 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 128L, 8L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 128L, - 8L, 0L, 0L, 0L); + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, + 0L, 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, + 0L, 0L); final NetworkStats grouped = uidStats.groupedByIface(); assertEquals(7, uidStats.size()); assertEquals(2, grouped.size()); - assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - 384L, 24L, 0L, 2L, 0L); - assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - 1024L, 64L, 0L, 0L, 0L); + assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L, + 2L, 0L); + assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 1024L, 64L, + 0L, 0L, 0L); } public void testAddAllValues() { final NetworkStats first = new NetworkStats(TEST_START, 5) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 32L, - 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, 32L, - 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, + 0L, 0L) + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, + 0L, 0L); final NetworkStats second = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, - 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, 32L, - 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, + 0L, 0L); first.combineAllValues(second); assertEquals(4, first.size()); - assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 64L, + assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 64L, 0L, 0L, + 0L, 0L); + assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L, + 0L, 0L, 0L); + assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 64L, 0L, + 0L, 0L, 0L); + assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L); - assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - 32L, 0L, 0L, 0L, 0L); - assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, - 64L, 0L, 0L, 0L, 0L); - assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 32L, 0L, 0L, 0L, 0L); } public void testGetTotal() { final NetworkStats stats = new NetworkStats(TEST_START, 7) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, - 0L, 2L, 20L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 512L, - 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, 4L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, + 2L, 20L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, + 0L, 0L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L, + 0L) + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 512L, - 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 128L, - 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 128L, 8L, - 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 128L, - 8L, 0L, 0L, 0L); + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, + 0L, 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, + 0L, 0L); assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L); assertValues(stats.getTotal(null, 100), 1280L, 80L, 0L, 2L, 20L); @@ -427,10 +396,10 @@ public class NetworkStatsTest extends TestCase { final NetworkStats after = before.withoutUids(new int[] { 100 }); assertEquals(6, before.size()); assertEquals(2, after.size()); - assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 128L, 8L, 0L, 0L, 0L); - assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 128L, - 8L, 0L, 0L, 0L); + assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, + 0L, 0L, 0L); + assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, + 0L, 0L); } public void testClone() throws Exception { @@ -465,90 +434,77 @@ public class NetworkStatsTest extends TestCase { final String underlyingIface = "wlan0"; final int testTag1 = 8888; NetworkStats delta = new NetworkStats(TEST_START, 17) - .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 39605L, 46L, - 12259L, 55L, 0L) - .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L, - 0L, 0L, 0L) - .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 72667L, 197L, - 43909L, 241L, 0L) - .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 9297L, - 17L, 4128L, 21L, 0L) + .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, 39605L, 46L, 12259L, 55L, 0L) + .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) + .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, 72667L, 197L, 43909L, 241L, 0L) + .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, 9297L, 17L, 4128L, 21L, 0L) // VPN package also uses some traffic through unprotected network. - .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4983L, 10L, - 1801L, 12L, 0L) - .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L, - 0L, 0L, 0L) + .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 4983L, 10L, 1801L, 12L, 0L) + .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) // Tag entries - .addValues(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, 21691L, 41L, - 13820L, 51L, 0L) - .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, 1281L, 2L, - 665L, 2L, 0L) + .addValues(tunIface, 10120, SET_DEFAULT, testTag1, 21691L, 41L, 13820L, 51L, 0L) + .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 665L, 2L, 0L) // Irrelevant entries - .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1685L, 5L, - 2070L, 6L, 0L) + .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, 1685L, 5L, 2070L, 6L, 0L) // Underlying Iface entries - .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5178L, - 8L, 2139L, 11L, 0L) - .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, - 0L, 0L, 0L, 0L) - .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 149873L, 287L, 59217L /* smaller than sum(tun0) */, - 299L /* smaller than sum(tun0) */, 0L) - .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - 0L, 0L, 0L, 0L, 0L); + .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, 5178L, 8L, 2139L, 11L, 0L) + .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) + .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, 149873L, 287L, + 59217L /* smaller than sum(tun0) */, 299L /* smaller than sum(tun0) */, 0L) + .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface)); assertEquals(20, delta.size()); // tunIface and TEST_IFACE entries are not changed. - assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 39605L, 46L, 12259L, 55L, 0L); - assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L, + 0L, 0L, 0L); + assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO, 72667L, 197L, 43909L, 241L, 0L); - assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 9297L, 17L, 4128L, 21L, 0L); - assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4983L, 10L, 1801L, 12L, 0L); - assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, + assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L, + 0L, 0L, 0L); + assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO, 21691L, 41L, 13820L, 51L, 0L); - assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, - 1281L, 2L, 665L, 2L, 0L); - assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - 1685L, 5L, 2070L, 6L, 0L); + assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, 1281L, + 2L, 665L, 2L, 0L); + assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1685L, 5L, + 2070L, 6L, 0L); // Existing underlying Iface entries are updated - assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 44783L, 54L, 14178L, 62L, 0L); - assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, 0L, 0L, 0L, 0L, 0L); + assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, + 44783L, 54L, 14178L, 62L, 0L); + assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, + 0L, 0L, 0L, 0L, 0L); // VPN underlying Iface entries are updated - assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 28304L, 27L, 1L, 2L, 0L); - assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, 0L, 0L, 0L, 0L, 0L); + assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, + 28304L, 27L, 1L, 2L, 0L); + assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO, + 0L, 0L, 0L, 0L, 0L); // New entries are added for new application's underlying Iface traffic - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 72667L, 197L, 43123L, 227L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, 9297L, 17L, 4054, 19L, 0L); - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, METERED_NO, - ROAMING_NO, 21691L, 41L, 13572L, 48L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, - ROAMING_NO, 1281L, 2L, 653L, 1L, 0L); + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO, + 72667L, 197L, 43123L, 227L, 0L); + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO, + 9297L, 17L, 4054, 19L, 0L); + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO, + 21691L, 41L, 13572L, 48L, 0L); + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, + 1281L, 2L, 653L, 1L, 0L); // New entries are added for debug purpose - assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, 39605L, 46L, 12039, 51, 0); - assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, 81964, 214, 47177, 246, 0); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL, - ROAMING_ALL, 121569, 260, 59216, 297, 0); + assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, + 39605L, 46L, 12039, 51, 0); + assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, + 81964, 214, 47177, 246, 0); + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL, + 121569, 260, 59216, 297, 0); } @@ -562,78 +518,72 @@ public class NetworkStatsTest extends TestCase { final String underlyingIface = "wlan0"; NetworkStats delta = new NetworkStats(TEST_START, 9) // 2 different apps sent/receive data via tun0. - .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50000L, 25L, - 100000L, 50L, 0L) - .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 500L, 2L, - 200L, 5L, 0L) + .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, 50000L, 25L, 100000L, 50L, 0L) + .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, 500L, 2L, 200L, 5L, 0L) // VPN package resends data through the tunnel (with exaggerated overhead) - .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 240000, - 100L, 120000L, 60L, 0L) + .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 240000, 100L, 120000L, 60L, 0L) // 1 app already has some traffic on the underlying interface, the other doesn't yet - .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1000L, - 10L, 2000L, 20L, 0L) + .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, 1000L, 10L, 2000L, 20L, 0L) // Traffic through the underlying interface via the vpn app. // This test should redistribute this data correctly. - .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, 75500L, 37L, 130000L, 70L, 0L); assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface)); assertEquals(9, delta.size()); // tunIface entries should not be changed. - assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 50000L, 25L, 100000L, 50L, 0L); - assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 500L, 2L, 200L, 5L, 0L); - assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, 240000L, 100L, 120000L, 60L, 0L); // Existing underlying Iface entries are updated - assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 51000L, 35L, 102000L, 70L, 0L); + assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, + 51000L, 35L, 102000L, 70L, 0L); // VPN underlying Iface entries are updated - assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 25000L, 10L, 29800L, 15L, 0L); + assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, + 25000L, 10L, 29800L, 15L, 0L); // New entries are added for new application's underlying Iface traffic - assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, 500L, 2L, 200L, 5L, 0L); + assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, ROAMING_NO, + 500L, 2L, 200L, 5L, 0L); // New entries are added for debug purpose - assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, 50000L, 25L, 100000L, 50L, 0L); - assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, 500, 2L, 200L, 5L, 0L); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL, - ROAMING_ALL, 50500L, 27L, 100200L, 55, 0); + assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, + 50000L, 25L, 100000L, 50L, 0L); + assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, + 500, 2L, 200L, 5L, 0L); + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL, + 50500L, 27L, 100200L, 55, 0); } private static void assertContains(NetworkStats stats, String iface, int uid, int set, - int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes, - long txPackets, long operations) { - int index = stats.findIndex(iface, uid, set, tag, metered, roaming); + int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { + int index = stats.findIndex(iface, uid, set, tag, roaming); assertTrue(index != -1); - assertValues(stats, index, iface, uid, set, tag, metered, roaming, + assertValues(stats, index, iface, uid, set, tag, roaming, rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, - int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes, - long txPackets, long operations) { + int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { final NetworkStats.Entry entry = stats.getValues(index, null); - assertValues(entry, iface, uid, set, tag, metered, roaming); + assertValues(entry, iface, uid, set, tag, roaming); assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues( - NetworkStats.Entry entry, String iface, int uid, int set, int tag, int metered, - int roaming) { + NetworkStats.Entry entry, String iface, int uid, int set, int tag, int roaming) { assertEquals(iface, entry.iface); assertEquals(uid, entry.uid); assertEquals(set, entry.set); assertEquals(tag, entry.tag); - assertEquals(metered, entry.metered); assertEquals(roaming, entry.roaming); } From ed1e28dfadca03e167926e52b08a800a4172cd66 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 18 Aug 2016 15:31:45 -0700 Subject: [PATCH 15/19] Fixed NetworkStatsServiceTest and converted it to JUnit4. Most tests were failing because due to a null NetworkCapabilities. Example: 1) testNetworkStatsWifi(com.android.server.net.NetworkStatsServiceTest) java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.net.NetworkCapabilities.hasCapability(int)' on a null object reference at com.android.server.net.NetworkStatsService.updateIfacesLocked(NetworkStatsService.java:983) BUG: 30839080 (cherry picked from commit f96df4b2984d7b2aa2e532c9a2d4ce5200ee0f5e) Change-Id: Ie09b2f43cf6ec745e404d5ec98bd0b072d211ea3 --- .../server/net/NetworkStatsServiceTest.java | 58 ++++++++++++------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java index 4b69eb3ac3..9176675c4d 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java @@ -40,7 +40,9 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; + import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; + import static org.easymock.EasyMock.anyInt; import static org.easymock.EasyMock.anyLong; import static org.easymock.EasyMock.anyObject; @@ -49,12 +51,12 @@ import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.isA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import android.app.AlarmManager; -import android.app.IAlarmListener; -import android.app.IAlarmManager; -import android.app.PendingIntent; import android.app.usage.NetworkStatsManager; import android.content.Context; import android.content.Intent; @@ -63,6 +65,7 @@ import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsSession; import android.net.LinkProperties; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkState; @@ -80,11 +83,10 @@ import android.os.MessageQueue; import android.os.MessageQueue.IdleHandler; import android.os.Message; import android.os.PowerManager; -import android.os.WorkSource; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; import android.telephony.TelephonyManager; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.Suppress; import android.util.TrustedTime; import com.android.internal.net.VpnInfo; @@ -97,6 +99,10 @@ import libcore.io.IoUtils; import org.easymock.Capture; import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; import java.io.File; import java.util.ArrayList; @@ -109,8 +115,8 @@ import java.util.List; * TODO: This test is really brittle, largely due to overly-strict use of Easymock. * Rewrite w/ Mockito. */ -@LargeTest -public class NetworkStatsServiceTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +public class NetworkStatsServiceTest { private static final String TAG = "NetworkStatsServiceTest"; private static final String TEST_IFACE = "test0"; @@ -148,12 +154,12 @@ public class NetworkStatsServiceTest extends AndroidTestCase { private INetworkStatsSession mSession; private INetworkManagementEventObserver mNetworkObserver; - @Override + @Before public void setUp() throws Exception { - super.setUp(); + final Context context = InstrumentationRegistry.getContext(); - mServiceContext = new BroadcastInterceptingContext(getContext()); - mStatsDir = getContext().getFilesDir(); + mServiceContext = new BroadcastInterceptingContext(context); + mStatsDir = context.getFilesDir(); if (mStatsDir.exists()) { IoUtils.deleteContents(mStatsDir); } @@ -205,7 +211,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } - @Override + @After public void tearDown() throws Exception { IoUtils.deleteContents(mStatsDir); @@ -219,10 +225,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mSession.close(); mService = null; - - super.tearDown(); } + @Test public void testNetworkStatsWifi() throws Exception { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. @@ -276,6 +281,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } + @Test public void testStatsRebootPersist() throws Exception { assertStatsFilesExist(false); @@ -366,7 +372,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } // TODO: simulate reboot to test bucket resize - @Suppress + // @Test public void testStatsBucketResize() throws Exception { NetworkStatsHistory history = null; @@ -425,6 +431,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } + @Test public void testUidStatsAcrossNetworks() throws Exception { // pretend first mobile network comes online expectCurrentTime(); @@ -515,6 +522,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } + @Test public void testUidRemovedIsMoved() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -585,6 +593,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } + @Test public void testUid3g4gCombinedByTemplate() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -658,6 +667,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { verifyAndReset(); } + @Test public void testSummaryForAllUid() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -729,6 +739,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { verifyAndReset(); } + @Test public void testForegroundBackground() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -799,6 +810,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { verifyAndReset(); } + @Test public void testRoaming() throws Exception { // pretend that network comes online expectCurrentTime(); @@ -846,6 +858,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { verifyAndReset(); } + @Test public void testTethering() throws Exception { // pretend first mobile network comes online expectCurrentTime(); @@ -887,6 +900,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } + @Test public void testRegisterUsageCallback() throws Exception { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. @@ -1005,6 +1019,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { EasyMock.verify(mockBinder); } + @Test public void testUnregisterUsageCallback_unknown_noop() throws Exception { String callingPackage = "the.calling.package"; long thresholdInBytes = 10 * 1024 * 1024; // 10 MB @@ -1204,7 +1219,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { info.setDetailedState(DetailedState.CONNECTED, null, null); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); - return new NetworkState(info, prop, null, null, null, TEST_SSID); + final NetworkCapabilities capabilities = new NetworkCapabilities(); + return new NetworkState(info, prop, capabilities, null, null, TEST_SSID); } private static NetworkState buildMobile3gState(String subscriberId) { @@ -1218,7 +1234,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { info.setRoaming(isRoaming); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); - return new NetworkState(info, prop, null, null, subscriberId, null); + final NetworkCapabilities capabilities = new NetworkCapabilities(); + return new NetworkState(info, prop, capabilities, null, subscriberId, null); } private static NetworkState buildMobile4gState(String iface) { @@ -1226,7 +1243,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { info.setDetailedState(DetailedState.CONNECTED, null, null); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(iface); - return new NetworkState(info, prop, null, null, null, null); + final NetworkCapabilities capabilities = new NetworkCapabilities(); + return new NetworkState(info, prop, capabilities, null, null, null); } private NetworkStats buildEmptyStats() { From ab6ab9bd3672eed293e4b11ab579c3e93fc17a50 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Mon, 22 Aug 2016 08:50:43 -0700 Subject: [PATCH 16/19] Use @Ignore to explicitly disable a @Test method. BUG: 30839080 BUG: 31007021 (cherry picked from commit a4dc2a71290dc053d34c5a276b08785d4c58f565) Change-Id: I35942e60493adebb22871541a34240368c691ee7 --- .../src/com/android/server/net/NetworkStatsServiceTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java index 9176675c4d..a810f440d0 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java @@ -101,6 +101,7 @@ import org.easymock.Capture; import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -372,7 +373,8 @@ public class NetworkStatsServiceTest { } // TODO: simulate reboot to test bucket resize - // @Test + @Test + @Ignore public void testStatsBucketResize() throws Exception { NetworkStatsHistory history = null; From d67fae88b66af47128d55e10d1ee95d3d1df41de Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 18 Aug 2016 16:20:01 -0700 Subject: [PATCH 17/19] Refactored NetworkStatsServiceTest to use Mockito instead of EasyMock. Test: m -j32 FrameworksServicesTests && adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && adb shell am instrument -e class "com.android.server.net.NetworkStatsServiceTest" -w "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner" BUG: 30943463 (cherry picked from commit de2a6f1b1d71725866579c9e2531a55ec7b532ce) Change-Id: Ia9929295ab2396a7ebb133e65d157f98414e4dfa --- .../server/net/NetworkStatsServiceTest.java | 304 +++++------------- 1 file changed, 79 insertions(+), 225 deletions(-) diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java index a810f440d0..f2cf90ca91 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java @@ -43,18 +43,16 @@ import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; -import static org.easymock.EasyMock.anyInt; -import static org.easymock.EasyMock.anyLong; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.capture; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; @@ -97,13 +95,14 @@ import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; import libcore.io.IoUtils; -import org.easymock.Capture; -import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.io.File; import java.util.ArrayList; @@ -113,8 +112,8 @@ import java.util.List; /** * Tests for {@link NetworkStatsService}. * - * TODO: This test is really brittle, largely due to overly-strict use of Easymock. - * Rewrite w/ Mockito. + * TODO: This test used to be really brittle because it used Easymock - it uses Mockito now, but + * still uses the Easymock structure, which could be simplified. */ @RunWith(AndroidJUnit4.class) public class NetworkStatsServiceTest { @@ -144,10 +143,12 @@ public class NetworkStatsServiceTest { private BroadcastInterceptingContext mServiceContext; private File mStatsDir; - private INetworkManagementService mNetManager; - private TrustedTime mTime; - private NetworkStatsSettings mSettings; - private IConnectivityManager mConnManager; + private @Mock INetworkManagementService mNetManager; + private @Mock TrustedTime mTime; + private @Mock NetworkStatsSettings mSettings; + private @Mock IConnectivityManager mConnManager; + private @Mock IBinder mBinder; + private @Mock AlarmManager mAlarmManager; private IdleableHandlerThread mHandlerThread; private Handler mHandler; @@ -157,6 +158,7 @@ public class NetworkStatsServiceTest { @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); final Context context = InstrumentationRegistry.getContext(); mServiceContext = new BroadcastInterceptingContext(context); @@ -165,22 +167,13 @@ public class NetworkStatsServiceTest { IoUtils.deleteContents(mStatsDir); } - mNetManager = createMock(INetworkManagementService.class); - - // TODO: Mock AlarmManager when migrating this test to Mockito. - AlarmManager alarmManager = (AlarmManager) mServiceContext - .getSystemService(Context.ALARM_SERVICE); - mTime = createMock(TrustedTime.class); - mSettings = createMock(NetworkStatsSettings.class); - mConnManager = createMock(IConnectivityManager.class); - PowerManager powerManager = (PowerManager) mServiceContext.getSystemService( Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mService = new NetworkStatsService( - mServiceContext, mNetManager, alarmManager, wakeLock, mTime, + mServiceContext, mNetManager, mAlarmManager, wakeLock, mTime, TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); mHandlerThread = new IdleableHandlerThread("HandlerThread"); @@ -197,17 +190,15 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(buildEmptyStats()); expectSystemReady(); - // catch INetworkManagementEventObserver during systemReady() - final Capture networkObserver = new Capture< - INetworkManagementEventObserver>(); - mNetManager.registerObserver(capture(networkObserver)); - expectLastCall().atLeastOnce(); - - replay(); mService.systemReady(); mSession = mService.openSession(); - verifyAndReset(); + assertNotNull("openSession() failed", mSession); + + // catch INetworkManagementEventObserver during systemReady() + ArgumentCaptor networkObserver = + ArgumentCaptor.forClass(INetworkManagementEventObserver.class); + verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); } @@ -237,15 +228,13 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); // verify service has empty history for wifi assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - verifyAndReset(); + // modify some number on wifi, and trigger poll event incrementCurrentTime(HOUR_IN_MILLIS); @@ -254,14 +243,11 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); - verifyAndReset(); + // and bump forward again, with counters going higher. this is // important, since polling should correctly subtract last snapshot. @@ -271,14 +257,10 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); - verifyAndReset(); } @@ -293,15 +275,13 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); // verify service has empty history for wifi assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - verifyAndReset(); + // modify some number on wifi, and trigger poll event incrementCurrentTime(HOUR_IN_MILLIS); @@ -315,14 +295,11 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); - expectNetworkStatsPoll(); - mService.setUidForeground(UID_RED, false); mService.incrementOperationCount(UID_RED, 0xFAAD, 4); mService.setUidForeground(UID_RED, true); mService.incrementOperationCount(UID_RED, 0xFAAD, 6); - replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -332,16 +309,13 @@ public class NetworkStatsServiceTest { assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); - verifyAndReset(); + // graceful shutdown system, which should trigger persist of stats, and // clear any values in memory. expectCurrentTime(); expectDefaultSettings(); - replay(); mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN)); - verifyAndReset(); - assertStatsFilesExist(true); // boot through serviceReady() again @@ -350,17 +324,8 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(buildEmptyStats()); expectSystemReady(); - // catch INetworkManagementEventObserver during systemReady() - final Capture networkObserver = new Capture< - INetworkManagementEventObserver>(); - mNetManager.registerObserver(capture(networkObserver)); - expectLastCall().atLeastOnce(); - - replay(); mService.systemReady(); - mNetworkObserver = networkObserver.getValue(); - // after systemReady(), we should have historical stats loaded again assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); @@ -368,7 +333,6 @@ public class NetworkStatsServiceTest { assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); - verifyAndReset(); } @@ -387,12 +351,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // modify some number on wifi, and trigger poll event incrementCurrentTime(2 * HOUR_IN_MILLIS); @@ -401,9 +363,6 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L)); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -411,7 +370,7 @@ public class NetworkStatsServiceTest { assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(2, history.size()); - verifyAndReset(); + // now change bucket duration setting and trigger another poll with // exact same values, which should resize existing buckets. @@ -419,9 +378,6 @@ public class NetworkStatsServiceTest { expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify identical stats, but spread across 4 buckets now @@ -429,7 +385,6 @@ public class NetworkStatsServiceTest { assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(4, history.size()); - verifyAndReset(); } @@ -441,12 +396,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // create some traffic on first network incrementCurrentTime(HOUR_IN_MILLIS); @@ -458,11 +411,8 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_RED, 0xF00D, 10); - replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -470,7 +420,7 @@ public class NetworkStatsServiceTest { assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 10); assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 0); - verifyAndReset(); + // now switch networks; this also tests that we're okay with interfaces // disappearing, to verify we don't count backwards. @@ -484,13 +434,11 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); forcePollAndWaitForIdle(); - verifyAndReset(); + // create traffic on second network incrementCurrentTime(HOUR_IN_MILLIS); @@ -503,11 +451,8 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10); - replay(); forcePollAndWaitForIdle(); // verify original history still intact @@ -520,7 +465,6 @@ public class NetworkStatsServiceTest { assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); - verifyAndReset(); } @@ -532,12 +476,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // create some traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -550,11 +492,8 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_RED, 0xFAAD, 10); - replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -562,7 +501,7 @@ public class NetworkStatsServiceTest { assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 0); assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); - verifyAndReset(); + // now pretend two UIDs are uninstalled, which should migrate stats to // special "removed" bucket. @@ -575,9 +514,6 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); - expectNetworkStatsPoll(); - - replay(); final Intent intent = new Intent(ACTION_UID_REMOVED); intent.putExtra(EXTRA_UID, UID_BLUE); mServiceContext.sendBroadcast(intent); @@ -591,7 +527,6 @@ public class NetworkStatsServiceTest { assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 10); - verifyAndReset(); } @@ -603,12 +538,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // create some traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -618,16 +551,13 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_RED, 0xF00D, 5); - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5); - verifyAndReset(); + // now switch over to 4g network incrementCurrentTime(HOUR_IN_MILLIS); @@ -638,13 +568,11 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); forcePollAndWaitForIdle(); - verifyAndReset(); + // create traffic on second network incrementCurrentTime(HOUR_IN_MILLIS); @@ -656,17 +584,12 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_RED, 0xFAAD, 5); - replay(); forcePollAndWaitForIdle(); // verify that ALL_MOBILE template combines both assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 10); - - verifyAndReset(); } @Test @@ -677,12 +600,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // create some traffic for two apps incrementCurrentTime(HOUR_IN_MILLIS); @@ -693,17 +614,14 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 1); assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 0); - verifyAndReset(); + // now create more traffic in next hour, but only for one app incrementCurrentTime(HOUR_IN_MILLIS); @@ -714,9 +632,6 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L)); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // first verify entire history present @@ -737,8 +652,6 @@ public class NetworkStatsServiceTest { assertEquals(1, stats.size()); assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 512L, 4L, 0); - - verifyAndReset(); } @Test @@ -749,12 +662,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // create some initial traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -764,16 +675,13 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); - expectNetworkStatsPoll(); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); - verifyAndReset(); + // now switch to foreground incrementCurrentTime(HOUR_IN_MILLIS); @@ -785,12 +693,9 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); - expectNetworkStatsPoll(); - mService.setUidForeground(UID_RED, true); mService.incrementOperationCount(UID_RED, 0xFAAD, 1); - replay(); forcePollAndWaitForIdle(); // test that we combined correctly @@ -808,8 +713,6 @@ public class NetworkStatsServiceTest { 32L, 2L, 1); assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L, 1L, 1); - - verifyAndReset(); } @Test @@ -820,12 +723,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // Create some traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -840,9 +741,6 @@ public class NetworkStatsServiceTest { 128L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, 1L, 0L)); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history @@ -856,8 +754,6 @@ public class NetworkStatsServiceTest { 128L, 2L, 0); assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L, 1L, 0); - - verifyAndReset(); } @Test @@ -868,12 +764,10 @@ public class NetworkStatsServiceTest { expectNetworkState(buildMobile3gState(IMSI_1)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); - verifyAndReset(); + // create some tethering traffic incrementCurrentTime(HOUR_IN_MILLIS); @@ -889,16 +783,12 @@ public class NetworkStatsServiceTest { .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L); expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0); assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0); - verifyAndReset(); } @@ -911,16 +801,12 @@ public class NetworkStatsServiceTest { expectNetworkState(buildWifiState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); expectBandwidthControlCheck(); - replay(); mService.forceUpdateIfaces(); // verify service has empty history for wifi assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - verifyAndReset(); - String callingPackage = "the.calling.package"; long thresholdInBytes = 1L; // very small; should be overriden by framework DataUsageRequest inputRequest = new DataUsageRequest( @@ -931,23 +817,18 @@ public class NetworkStatsServiceTest { LatchedHandler latchedHandler = new LatchedHandler(Looper.getMainLooper(), cv); Messenger messenger = new Messenger(latchedHandler); - // Allow binder to connect - IBinder mockBinder = createMock(IBinder.class); - mockBinder.linkToDeath((IBinder.DeathRecipient) anyObject(), anyInt()); - EasyMock.replay(mockBinder); - // Force poll expectCurrentTime(); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - replay(); + + // Register and verify request and that binder was called DataUsageRequest request = mService.registerUsageCallback(callingPackage, inputRequest, - messenger, mockBinder); + messenger, mBinder); assertTrue(request.requestId > 0); assertTrue(Objects.equals(sTemplateWifi, request.template)); long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB @@ -957,11 +838,11 @@ public class NetworkStatsServiceTest { mHandler.sendMessage(mHandler.obtainMessage(-1)); mHandlerThread.waitForIdle(WAIT_TIMEOUT); - verifyAndReset(); + // Make sure that the caller binder gets connected - EasyMock.verify(mockBinder); - EasyMock.reset(mockBinder); + verify(mBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); + // modify some number on wifi, and trigger poll event // not enough traffic to call data usage callback @@ -971,13 +852,9 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history - verifyAndReset(); assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); // make sure callback has not being called @@ -991,14 +868,11 @@ public class NetworkStatsServiceTest { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); - expectNetworkStatsPoll(); - - replay(); forcePollAndWaitForIdle(); // verify service recorded history assertNetworkTotal(sTemplateWifi, 4096000L, 4L, 8192000L, 8L, 0); - verifyAndReset(); + // Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED assertTrue(cv.block(WAIT_TIMEOUT)); @@ -1006,9 +880,7 @@ public class NetworkStatsServiceTest { cv.close(); // Allow binder to disconnect - expect(mockBinder.unlinkToDeath((IBinder.DeathRecipient) anyObject(), anyInt())) - .andReturn(true); - EasyMock.replay(mockBinder); + when(mBinder.unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt())).thenReturn(true); // Unregister request mService.unregisterUsageRequest(request); @@ -1018,7 +890,7 @@ public class NetworkStatsServiceTest { assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType); // Make sure that the caller binder gets disconnected - EasyMock.verify(mockBinder); + verify(mBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); } @Test @@ -1078,33 +950,30 @@ public class NetworkStatsServiceTest { } private void expectSystemReady() throws Exception { - mNetManager.setGlobalAlert(anyLong()); - expectLastCall().atLeastOnce(); - expectNetworkStatsSummary(buildEmptyStats()); expectBandwidthControlCheck(); } private void expectNetworkState(NetworkState... state) throws Exception { - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); + when(mConnManager.getAllNetworkState()).thenReturn(state); final LinkProperties linkProp = state.length > 0 ? state[0].linkProperties : null; - expect(mConnManager.getActiveLinkProperties()).andReturn(linkProp).atLeastOnce(); + when(mConnManager.getActiveLinkProperties()).thenReturn(linkProp); } private void expectNetworkStatsSummary(NetworkStats summary) throws Exception { - expect(mConnManager.getAllVpnInfo()).andReturn(new VpnInfo[0]).atLeastOnce(); + when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]); expectNetworkStatsSummaryDev(summary); expectNetworkStatsSummaryXt(summary); } private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception { - expect(mNetManager.getNetworkStatsSummaryDev()).andReturn(summary).atLeastOnce(); + when(mNetManager.getNetworkStatsSummaryDev()).thenReturn(summary); } private void expectNetworkStatsSummaryXt(NetworkStats summary) throws Exception { - expect(mNetManager.getNetworkStatsSummaryXt()).andReturn(summary).atLeastOnce(); + when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary); } private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { @@ -1114,11 +983,10 @@ public class NetworkStatsServiceTest { private void expectNetworkStatsUidDetail( NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats) throws Exception { - expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce(); + when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail); // also include tethering details, since they are folded into UID - expect(mNetManager.getNetworkStatsTethering()) - .andReturn(tetherStats).atLeastOnce(); + when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats); } private void expectDefaultSettings() throws Exception { @@ -1127,38 +995,33 @@ public class NetworkStatsServiceTest { private void expectSettings(long persistBytes, long bucketDuration, long deleteAge) throws Exception { - expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes(); - expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes(); - expect(mSettings.getSampleEnabled()).andReturn(true).anyTimes(); + when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS); + when(mSettings.getTimeCacheMaxAge()).thenReturn(DAY_IN_MILLIS); + when(mSettings.getSampleEnabled()).thenReturn(true); final Config config = new Config(bucketDuration, deleteAge, deleteAge); - expect(mSettings.getDevConfig()).andReturn(config).anyTimes(); - expect(mSettings.getXtConfig()).andReturn(config).anyTimes(); - expect(mSettings.getUidConfig()).andReturn(config).anyTimes(); - expect(mSettings.getUidTagConfig()).andReturn(config).anyTimes(); + when(mSettings.getDevConfig()).thenReturn(config); + when(mSettings.getXtConfig()).thenReturn(config); + when(mSettings.getUidConfig()).thenReturn(config); + when(mSettings.getUidTagConfig()).thenReturn(config); - expect(mSettings.getGlobalAlertBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); - expect(mSettings.getDevPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); - expect(mSettings.getXtPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); - expect(mSettings.getUidPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); - expect(mSettings.getUidTagPersistBytes(anyLong())).andReturn(MB_IN_BYTES).anyTimes(); + when(mSettings.getGlobalAlertBytes(anyLong())).thenReturn(MB_IN_BYTES); + when(mSettings.getDevPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); + when(mSettings.getXtPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); + when(mSettings.getUidPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); + when(mSettings.getUidTagPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); } private void expectCurrentTime() throws Exception { - expect(mTime.forceRefresh()).andReturn(false).anyTimes(); - expect(mTime.hasCache()).andReturn(true).anyTimes(); - expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes(); - expect(mTime.getCacheAge()).andReturn(0L).anyTimes(); - expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); - } - - private void expectNetworkStatsPoll() throws Exception { - mNetManager.setGlobalAlert(anyLong()); - expectLastCall().anyTimes(); + when(mTime.forceRefresh()).thenReturn(false); + when(mTime.hasCache()).thenReturn(true); + when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis()); + when(mTime.getCacheAge()).thenReturn(0L); + when(mTime.getCacheCertainty()).thenReturn(0L); } private void expectBandwidthControlCheck() throws Exception { - expect(mNetManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce(); + when(mNetManager.isBandwidthControlEnabled()).thenReturn(true); } private void assertStatsFilesExist(boolean exist) { @@ -1269,15 +1132,6 @@ public class NetworkStatsServiceTest { mElapsedRealtime += duration; } - private void replay() { - EasyMock.replay(mNetManager, mTime, mSettings, mConnManager); - } - - private void verifyAndReset() { - EasyMock.verify(mNetManager, mTime, mSettings, mConnManager); - EasyMock.reset(mNetManager, mTime, mSettings, mConnManager); - } - private void forcePollAndWaitForIdle() { mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // Send dummy message to make sure that any previous message has been handled From d748276a7045747c6e541ae6cbbc679d47f6064f Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 15 Nov 2016 11:25:52 +0900 Subject: [PATCH 18/19] Fix ConnectivityServiceTest testRequestBenchmark This patch fixes flakyness of testRequestBenchmark by adjusting time limit for callback registration from 100ms to 180ms, and time limits for onAvailable and onLost triggers from 30ms to 40ms. With these timeouts the test succeeds 100% over 5000 iterations. When using 150ms for registration timeout, running the test 5000 times fails 2 times. When using 30ms for onLost timeout, running the test 5000 times fails 1 times. In addition, this patch also cleans testRequestBenchmark and uses the more stable SystemClock.elapsedRealtime() for duration measurements. Test: $ runtest frameworks-net Bug: 32561414 (cherry picked from commit 766e5646478a1fc52b9ea41810a6532d298e1cc0) Change-Id: I196ab9ef7f5abe456a783eed65db09279d2ecb8c --- .../server/ConnectivityServiceTest.java | 88 ++++++++++++------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a06577e6da..bc685f27bf 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2012,6 +2012,7 @@ 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. @@ -2025,61 +2026,80 @@ 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 CONNECT_TIME_LIMIT_MS = 30; + 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; 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; + 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)); + } + }); + Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms", + NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS)); + + final int SWITCH_TIME_LIMIT_MS = 40; 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; + + 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)); + } + }); Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms", - NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS)); + NUM_REQUESTS, onLostDispatchingDuration, 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); + 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); Log.d(TAG, msg); - assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS); + 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; } @SmallTest From cb2a3a3bcaaf55a1be2f37d9b575e579460c17a6 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 15 Nov 2016 13:42:34 +0900 Subject: [PATCH 19/19] ConnectivityServiceTest: fix testAvoidBadWifiSettings This patch introduces an assertEventuallyThat helper function in ConnectivityServiceTest which given a boolean function retries until the function returns true or until a maximum retry time is reached. This function is used to fix flakyness of testAvoidBadWifiSetting where the Message posted by reevaluate() could reach the Handler's MessageQueue after waitForIdle takes effect, resulting in the test to fail. Instead of fixing the flakyness by introdcing hard sleep times, assertEventuallyThat is used to reduce the overall test time. With this change the test has been observed to pass with 100% success rate over 50000 invocations. Test: $ runtest frameworks-net Bug: 32561414 (cherry picked from commit b54c8cffa889a9c0debbb7f05c47ede670babd45) Change-Id: If41a24989d5f65aeb439f68741f511b5eb53b18d --- .../server/ConnectivityServiceTest.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index bc685f27bf..4b3f99277e 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -91,6 +91,7 @@ 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}. @@ -622,7 +623,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker { - public boolean configRestrictsAvoidBadWifi; + public volatile boolean configRestrictsAvoidBadWifi; public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) { super(c, h, r); @@ -2180,7 +2181,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { tracker.reevaluate(); mService.waitForIdle(); String msg = String.format("config=false, setting=%s", values[i]); - assertTrue(msg, mService.avoidBadWifi()); + assertEventuallyTrue(() -> mService.avoidBadWifi(), 50); assertFalse(msg, tracker.shouldNotifyWifiUnvalidated()); } @@ -2189,19 +2190,19 @@ public class ConnectivityServiceTest extends AndroidTestCase { Settings.Global.putInt(cr, settingName, 0); tracker.reevaluate(); mService.waitForIdle(); - assertFalse(mService.avoidBadWifi()); + assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50); assertFalse(tracker.shouldNotifyWifiUnvalidated()); Settings.Global.putInt(cr, settingName, 1); tracker.reevaluate(); mService.waitForIdle(); - assertTrue(mService.avoidBadWifi()); + assertEventuallyTrue(() -> mService.avoidBadWifi(), 50); assertFalse(tracker.shouldNotifyWifiUnvalidated()); Settings.Global.putString(cr, settingName, null); tracker.reevaluate(); mService.waitForIdle(); - assertFalse(mService.avoidBadWifi()); + assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50); assertTrue(tracker.shouldNotifyWifiUnvalidated()); } @@ -2418,6 +2419,17 @@ 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 };