From c8e4cc8e9919260dac5f2f8a76b693e8a29bfcc1 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 12 Mar 2016 16:29:54 -0800 Subject: [PATCH 01/21] DO NOT MERGE: 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 5f277e1667b49976a77c9fa79b9a04d775f3b49e) 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 43c8c81da2668..772a2ccc57a56 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 29154b000f1dfa6d7bd6a12359f439770463ce3e Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Mon, 18 Apr 2016 16:23:06 -0700 Subject: [PATCH 02/21] DO NOT MERGE: Indicate the NsdServiceInfo attributes are only filled in for a resolved service. Fixes: 28530428 (cherry picked from commit 7d5da4b044183826ac8388c8bdb94ac979a81797) Change-Id: If2bfc06589adb361f11b89cd5923cb5c255cb680 --- core/java/android/net/nsd/NsdManager.java | 10 +++++----- core/java/android/net/nsd/NsdServiceInfo.java | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 86bd5028266bc..33d12a3a3fb84 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -103,11 +103,11 @@ import com.android.internal.util.Protocol; * to {@link DiscoveryListener#onServiceFound} and a service lost is notified on * {@link DiscoveryListener#onServiceLost}. * - *

Once the peer application discovers the "Example" http srevice, and needs to receive data - * from the "Example" application, it can initiate a resolve with {@link #resolveService} to - * resolve the host and port details for the purpose of establishing a connection. A successful - * resolve is notified on {@link ResolveListener#onServiceResolved} and a failure is notified - * on {@link ResolveListener#onResolveFailed}. + *

Once the peer application discovers the "Example" http service, and either needs to read the + * attributes of the service or wants to receive data from the "Example" application, it can + * initiate a resolve with {@link #resolveService} to resolve the attributes, host, and port + * details. A successful resolve is notified on {@link ResolveListener#onServiceResolved} and a + * failure is notified on {@link ResolveListener#onResolveFailed}. * * Applications can reserve for a service type at * http://www.iana.org/form/ports-service. Existing services can be found at diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java index 4a06fb1220a71..7b845be749216 100644 --- a/core/java/android/net/nsd/NsdServiceInfo.java +++ b/core/java/android/net/nsd/NsdServiceInfo.java @@ -250,7 +250,8 @@ public final class NsdServiceInfo implements Parcelable { } /** - * Retrive attributes as a map of String keys to byte[] values. + * Retrieve attributes as a map of String keys to byte[] values. The attributes map is only + * valid for a resolved service. * *

The returned map is unmodifiable; changes must be made through {@link #setAttribute} and * {@link #removeAttribute}. From 4983e55853db9f9d1cc5720970c439b976480c52 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 6 Jul 2016 22:53:17 +0900 Subject: [PATCH 03/21] DO NOT MERGE: 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 d42650faaa33ec6274278c65a6042228555ddd4f) 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 772a2ccc57a56..780a9c8acf30b 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 1853f78d768dc44efdc8576302b382ff81a0ffac Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 7 Jul 2016 10:15:56 +0900 Subject: [PATCH 04/21] DO NOT MERGE: 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 7724cdd8b90006c852644d06cf6c8a28450c71c6) 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 780a9c8acf30b..51431ebfaf146 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 ce765b7a51d9452aaa32e43bedeefb7ad200df52 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 13 Oct 2016 16:48:42 +0900 Subject: [PATCH 05/21] DO NOT MERGE: ConnectivityThread: use lazy holder idiom This patch changes the way that the ConnectivityThread is lazily instantiated by using the "lazy initialization holder class idiom". The first code point that tries to obtain a reference to the unique ConnectivityThread instance will trigger the creation of the Singleton class, which will guarantee a thread-safe initialization of the static INSTANCE field inside Singleton according to the language specs. This is the Item #71 of Effective Java. The unique static instance of ConnectivityThread is not stored directly inside ConnectivityThread class but is stored in a static nested class. This is to avoid triggering the creation of that unique instance when Zygote does class preloading at phone startup. Otherwise this would lead to Zygote creating a new OS thread during preloading, which is a fatal error. Test: frameworks-wifi tests pass Bug: 26749700 Bug: 28537383 Bug: 32130437 (cherry picked from commit c4fe5d373caa9f53686e4d58e61394dd40558957) Change-Id: If13b363889a8e9396273a90c3d9f9421a48aecbc --- core/java/android/net/ConnectivityThread.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/ConnectivityThread.java b/core/java/android/net/ConnectivityThread.java index 55c3402bf39db..0b218e738b779 100644 --- a/core/java/android/net/ConnectivityThread.java +++ b/core/java/android/net/ConnectivityThread.java @@ -27,25 +27,30 @@ import android.os.Looper; * @hide */ public final class ConnectivityThread extends HandlerThread { - private static ConnectivityThread sInstance; + + // A class implementing the lazy holder idiom: the unique static instance + // of ConnectivityThread is instantiated in a thread-safe way (guaranteed by + // the language specs) the first time that Singleton is referenced in get() + // or getInstanceLooper(). + private static class Singleton { + private static final ConnectivityThread INSTANCE = createInstance(); + } private ConnectivityThread() { super("ConnectivityThread"); } - private static synchronized ConnectivityThread getInstance() { - if (sInstance == null) { - sInstance = new ConnectivityThread(); - sInstance.start(); - } - return sInstance; + private static ConnectivityThread createInstance() { + ConnectivityThread t = new ConnectivityThread(); + t.start(); + return t; } public static ConnectivityThread get() { - return getInstance(); + return Singleton.INSTANCE; } public static Looper getInstanceLooper() { - return getInstance().getLooper(); + return Singleton.INSTANCE.getLooper(); } } From ffe5a46b3e65389722333482a959f98767c4c74c Mon Sep 17 00:00:00 2001 From: Jeremy Joslin Date: Mon, 8 Aug 2016 16:07:37 -0700 Subject: [PATCH 06/21] DO NOT MERGE: 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 8b436d865c9f287e9ae491e5278cd8874f4a865b) Change-Id: I06f01aa8fe5fdc06b2d36cfb9c68feb244c2e5de --- core/java/android/net/NetworkStats.java | 18 +++-- .../src/android/net/NetworkStatsTest.java | 75 ++++++++++++++++--- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 25806fa776740..f65a50f02df32 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -904,7 +904,8 @@ public class NetworkStats implements Parcelable { if (pool.isEmpty()) { return true; } - Entry moved = addTrafficToApplications(tunIface, underlyingIface, tunIfaceTotal, pool); + Entry moved = + addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); deductTrafficFromVpnApp(tunUid, underlyingIface, moved); if (!moved.isEmpty()) { @@ -919,9 +920,9 @@ public class NetworkStats implements Parcelable { * Initializes the data used by the migrateTun() method. * * This is the first pass iteration which does the following work: - * (1) Adds up all the traffic through tun0. - * (2) Adds up all the traffic through the tunUid's underlyingIface + * (1) Adds up all the traffic through the tunUid's underlyingIface * (both foreground and background). + * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. */ private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, Entry tunIfaceTotal, Entry underlyingIfaceTotal) { @@ -941,8 +942,9 @@ public class NetworkStats implements Parcelable { underlyingIfaceTotal.add(recycle); } - if (recycle.tag == TAG_NONE && Objects.equals(tunIface, recycle.iface)) { - // Add up all tunIface traffic. + if (recycle.uid != tunUid && recycle.tag == TAG_NONE + && Objects.equals(tunIface, recycle.iface)) { + // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } @@ -958,13 +960,15 @@ public class NetworkStats implements Parcelable { return pool; } - private Entry addTrafficToApplications(String tunIface, String underlyingIface, + private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, Entry tunIfaceTotal, Entry pool) { Entry moved = new Entry(); Entry tmpEntry = new Entry(); tmpEntry.iface = underlyingIface; for (int i = 0; i < size; i++) { - if (Objects.equals(iface[i], tunIface)) { + // the vpn app is excluded from the redistribution but all moved traffic will be + // deducted from the vpn app (see deductTrafficFromVpnApp below). + if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { if (tunIfaceTotal.rxBytes > 0) { tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; } else { diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index 9074f8a97132e..d48a67a4c72f7 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -454,7 +454,7 @@ public class NetworkStatsTest extends TestCase { .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface)); - assertEquals(21, delta.size()); + assertEquals(20, delta.size()); // tunIface and TEST_IFACE entries are not changed. assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, @@ -478,38 +478,89 @@ public class NetworkStatsTest extends TestCase { // Existing underlying Iface entries are updated assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, - 44783L, 54L, 13829L, 60L, 0L); + 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, ROAMING_NO, - 28304L, 27L, 1719L, 12L, 0L); + 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, ROAMING_NO, - 72667L, 197L, 41872L, 219L, 0L); + 72667L, 197L, 43123L, 227L, 0L); assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO, - 9297L, 17L, 3936, 19L, 0L); + 9297L, 17L, 4054, 19L, 0L); assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO, - 21691L, 41L, 13179L, 46L, 0L); + 21691L, 41L, 13572L, 48L, 0L); assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, - 1281L, 2L, 634L, 1L, 0L); + 1281L, 2L, 653L, 1L, 0L); // New entries are added for debug purpose assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, - 39605L, 46L, 11690, 49, 0); + 39605L, 46L, 12039, 51, 0); assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, - 81964, 214, 45808, 238, 0); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, - 4983, 10, 1717, 10, 0); + 81964, 214, 47177, 246, 0); assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL, - 126552, 270, 59215, 297, 0); + 121569, 260, 59216, 297, 0); } + // Tests a case where all of the data received by the tun0 interface is echo back into the tun0 + // interface by the vpn app before it's sent out of the underlying interface. The VPN app should + // not be charged for the echoed data but it should still be charged for any extra data it sends + // via the underlying interface. + public void testMigrateTun_VpnAsLoopback() { + final int tunUid = 10030; + final String tunIface = "tun0"; + 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, 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, 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, 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, + 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, ROAMING_NO, + 50000L, 25L, 100000L, 50L, 0L); + 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, ROAMING_NO, + 240000L, 100L, 120000L, 60L, 0L); + + // Existing underlying Iface entries are updated + 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, 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, ROAMING_NO, + 500L, 2L, 200L, 5L, 0L); + + // New entries are added for debug purpose + 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 roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { From 77cba4bdf6de8aec02efe0da7e84f17603912b21 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 18 Aug 2016 15:31:45 -0700 Subject: [PATCH 07/21] DO NOT MERGE: 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 574f370c6da52eeffe747248d68ef044617c7bcf) 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 4b69eb3ac35b3..9176675c4dd49 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 2026ca147b6460807b19c997600315806ecb3197 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Mon, 22 Aug 2016 08:50:43 -0700 Subject: [PATCH 08/21] DO NOT MERGE: Use @Ignore to explicitly disable a @Test method. BUG: 30839080 BUG: 31007021 (cherry picked from commit fc7d7a359f800d7320d29055ef3b4b75157aaf13) 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 9176675c4dd49..a810f440d002e 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 e4c029918f32f9dacc7e6a1e8102b71f3ca1018c Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 18 Aug 2016 16:20:01 -0700 Subject: [PATCH 09/21] DO NOT MERGE: 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 b8f946dc4b24998f14e28573e452ab13ed533347) Change-Id: Ia9929295ab2396a7ebb133e65d157f98414e4dfa --- services/tests/servicestests/Android.mk | 1 - .../server/net/NetworkStatsServiceTest.java | 304 +++++------------- 2 files changed, 79 insertions(+), 226 deletions(-) diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index 3183930b08ced..c36462bfac1e8 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -17,7 +17,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ services.devicepolicy \ services.net \ services.usage \ - easymocklib \ guava \ android-support-test \ mockito-target \ 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 a810f440d002e..f2cf90ca916f0 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 dadf6caf9f2a8c360203a3f141a8c1366159ec4d Mon Sep 17 00:00:00 2001 From: Stephen Chen Date: Tue, 18 Oct 2016 16:41:47 -0700 Subject: [PATCH 10/21] DO NOT MERGE: Define API for metering network stats buckets. This is a continuation of b/26545374, since now we can also set the metered bit with NetworkScorer. The tracking of metered state changes will be implemented in a seperate CL. Bug: 31015360 Bug: 26545374 Test: N/A (cherry picked from commit 9ac251d1169639c7b955d63b21e80cbc5c394090) Change-Id: I6a2fcc8577d62daa8823dff9e0128a5cf39ede7b --- api/current.txt | 4 ++ api/system-current.txt | 4 ++ api/test-current.txt | 4 ++ core/java/android/app/usage/NetworkStats.java | 42 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/api/current.txt b/api/current.txt index 2788f3648eb66..92443f30d7d12 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6447,6 +6447,7 @@ package android.app.usage { public static class NetworkStats.Bucket { ctor public NetworkStats.Bucket(); method public long getEndTimeStamp(); + method public int getMetered(); method public int getRoaming(); method public long getRxBytes(); method public long getRxPackets(); @@ -6456,6 +6457,9 @@ package android.app.usage { method public long getTxBytes(); method public long getTxPackets(); method public int getUid(); + field public static final int METERED_ALL = -1; // 0xffffffff + field public static final int METERED_NO = 1; // 0x1 + field public static final int METERED_YES = 2; // 0x2 field public static final int ROAMING_ALL = -1; // 0xffffffff field public static final int ROAMING_NO = 1; // 0x1 field public static final int ROAMING_YES = 2; // 0x2 diff --git a/api/system-current.txt b/api/system-current.txt index 74b1af306657f..f1d295cbefc27 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6739,6 +6739,7 @@ package android.app.usage { public static class NetworkStats.Bucket { ctor public NetworkStats.Bucket(); method public long getEndTimeStamp(); + method public int getMetered(); method public int getRoaming(); method public long getRxBytes(); method public long getRxPackets(); @@ -6748,6 +6749,9 @@ package android.app.usage { method public long getTxBytes(); method public long getTxPackets(); method public int getUid(); + field public static final int METERED_ALL = -1; // 0xffffffff + field public static final int METERED_NO = 1; // 0x1 + field public static final int METERED_YES = 2; // 0x2 field public static final int ROAMING_ALL = -1; // 0xffffffff field public static final int ROAMING_NO = 1; // 0x1 field public static final int ROAMING_YES = 2; // 0x2 diff --git a/api/test-current.txt b/api/test-current.txt index 8e3d4ef6cbadc..28c5bdb536343 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -6456,6 +6456,7 @@ package android.app.usage { public static class NetworkStats.Bucket { ctor public NetworkStats.Bucket(); method public long getEndTimeStamp(); + method public int getMetered(); method public int getRoaming(); method public long getRxBytes(); method public long getRxPackets(); @@ -6465,6 +6466,9 @@ package android.app.usage { method public long getTxBytes(); method public long getTxPackets(); method public int getUid(); + field public static final int METERED_ALL = -1; // 0xffffffff + field public static final int METERED_NO = 1; // 0x1 + field public static final int METERED_YES = 2; // 0x2 field public static final int ROAMING_ALL = -1; // 0xffffffff field public static final int ROAMING_NO = 1; // 0x1 field public static final int ROAMING_YES = 2; // 0x2 diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 226aa8f2706da..f64bec73e4c8f 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -163,6 +163,29 @@ public final class NetworkStats implements AutoCloseable { */ public static final int UID_TETHERING = TrafficStats.UID_TETHERING; + /** @hide */ + @IntDef({METERED_ALL, METERED_NO, METERED_YES}) + @Retention(RetentionPolicy.SOURCE) + public @interface Metered {} + + /** + * Combined usage across all metered states. Covers metered and unmetered usage. + */ + public static final int METERED_ALL = -1; + + /** + * Usage that occurs on an unmetered network. + */ + public static final int METERED_NO = 0x1; + + /** + * Usage that occurs on a metered network. + * + *

A network is classified as metered when the user is sensitive to heavy data usage on + * that connection. + */ + public static final int METERED_YES = 0x2; + /** @hide */ @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES}) @Retention(RetentionPolicy.SOURCE) @@ -200,6 +223,7 @@ public final class NetworkStats implements AutoCloseable { private int mUid; private int mTag; private int mState; + private int mMetered; private int mRoaming; private long mBeginTimeStamp; private long mEndTimeStamp; @@ -278,6 +302,21 @@ public final class NetworkStats implements AutoCloseable { return mState; } + /** + * Metered state. One of the following values:

+ *

+ *

A network is classified as metered when the user is sensitive to heavy data usage on + * that connection. Apps may warn before using these networks for large downloads. The + * metered state can be set by the user within data usage network restrictions. + */ + public @Metered int getMetered() { + return mMetered; + } + /** * Roaming state. One of the following values:

*

diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java index 81f66a5bc95af..f41ea922305b4 100644 --- a/tests/net/java/android/net/apf/ApfTest.java +++ b/tests/net/java/android/net/apf/ApfTest.java @@ -662,9 +662,13 @@ public class ApfTest extends AndroidTestCase { // The IPv6 all nodes address ff02::1 private static final byte[] IPV6_ALL_NODES_ADDRESS = { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + private static final byte[] IPV6_ALL_ROUTERS_ADDRESS = + { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN; + private static final int ICMP6_ROUTER_SOLICITATION = 133; private static final int ICMP6_ROUTER_ADVERTISEMENT = 134; + private static final int ICMP6_NEIGHBOR_SOLICITATION = 135; private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; private static final int ICMP6_RA_HEADER_LEN = 16; @@ -799,6 +803,12 @@ public class ApfTest extends AndroidTestCase { put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS); assertDrop(program, packet.array()); + // Verify ICMPv6 RS to any is dropped + packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION); + assertDrop(program, packet.array()); + put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS); + assertDrop(program, packet.array()); + apfFilter.shutdown(); } From 21680fd25df1e088f87b3a947460268b4eb8cbbb Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 15 Nov 2016 23:23:24 +0900 Subject: [PATCH 15/21] DO NOT MERGE: NetworkMonitor metrics: add first validation information This patch adds first validation information to: - ValidationProbeEvent, by extending the probe_type int field of to also include a bit indicating if the probe was part of a first validation attempt or not. - NetworkMonitorEvent, by defining new contants for the event_type field. Test: $ runtest frameworks-net + manually generating events and inspecting the output of $ adb shell dumpsys connmetrics list Bug: b/32198726 (cherry picked from commit 147aa6d53bc1e9f8a3632553abcf936023806e1d) Change-Id: Ie7a62c4f62a13ce52806d3adaa9e627cb246073c --- ] | 12 +++++ .../android/net/metrics/NetworkEvent.java | 13 +++++ .../net/metrics/ValidationProbeEvent.java | 34 +++++++++---- .../server/connectivity/NetworkMonitor.java | 50 ++++++++++++++++++- 4 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 ] diff --git a/] b/] new file mode 100644 index 0000000000000..5619151c7ee3e --- /dev/null +++ b/] @@ -0,0 +1,12 @@ +NetworkNotificationManager: logging improvements + +TODO: squash me +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# On branch notification_tagging +# Your branch is ahead of 'goog/master' by 2 commits. +# (use "git push" to publish your local commits) +# +# Changes to be committed: +# modified: services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +# diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java index 3b3fa6976fc98..06674950a044d 100644 --- a/core/java/android/net/metrics/NetworkEvent.java +++ b/core/java/android/net/metrics/NetworkEvent.java @@ -41,6 +41,15 @@ public final class NetworkEvent implements Parcelable { public static final int NETWORK_UNLINGER = 6; public static final int NETWORK_DISCONNECTED = 7; + /** {@hide} */ + public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; + /** {@hide} */ + public static final int NETWORK_REVALIDATION_SUCCESS = 9; + /** {@hide} */ + public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; + /** {@hide} */ + public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; + /** {@hide} */ @IntDef(value = { NETWORK_CONNECTED, @@ -50,6 +59,10 @@ public final class NetworkEvent implements Parcelable { NETWORK_LINGER, NETWORK_UNLINGER, NETWORK_DISCONNECTED, + NETWORK_FIRST_VALIDATION_SUCCESS, + NETWORK_REVALIDATION_SUCCESS, + NETWORK_FIRST_VALIDATION_PORTAL_FOUND, + NETWORK_REVALIDATION_PORTAL_FOUND, }) @Retention(RetentionPolicy.SOURCE) public @interface EventType {} diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java index 1a31b56f1ffb6..a724ec12ed324 100644 --- a/core/java/android/net/metrics/ValidationProbeEvent.java +++ b/core/java/android/net/metrics/ValidationProbeEvent.java @@ -44,10 +44,8 @@ public final class ValidationProbeEvent implements Parcelable { public static final int DNS_FAILURE = 0; public static final int DNS_SUCCESS = 1; - /** {@hide} */ - @IntDef(value = {PROBE_DNS, PROBE_HTTP, PROBE_HTTPS, PROBE_PAC}) - @Retention(RetentionPolicy.SOURCE) - public @interface ProbeType {} + private static final int FIRST_VALIDATION = 1 << 8; + private static final int REVALIDATION = 2 << 8; /** {@hide} */ @IntDef(value = {DNS_FAILURE, DNS_SUCCESS}) @@ -56,12 +54,17 @@ public final class ValidationProbeEvent implements Parcelable { public final int netId; public final long durationMs; - public final @ProbeType int probeType; + // probeType byte format (MSB to LSB): + // byte 0: unused + // byte 1: unused + // byte 2: 0 = UNKNOWN, 1 = FIRST_VALIDATION, 2 = REVALIDATION + // byte 3: PROBE_* constant + public final int probeType; public final @ReturnCode int returnCode; /** {@hide} */ public ValidationProbeEvent( - int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) { + int netId, long durationMs, int probeType, @ReturnCode int returnCode) { this.netId = netId; this.durationMs = durationMs; this.probeType = probeType; @@ -99,9 +102,19 @@ public final class ValidationProbeEvent implements Parcelable { } }; + /** @hide */ + public static int makeProbeType(int probeType, boolean firstValidation) { + return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION); + } + /** @hide */ public static String getProbeName(int probeType) { - return Decoder.constants.get(probeType, "PROBE_???"); + return Decoder.constants.get(probeType & 0xff, "PROBE_???"); + } + + /** @hide */ + public static String getValidationStage(int probeType) { + return Decoder.constants.get(probeType & 0xff00, "UNKNOWN"); } public static void logEvent(int netId, long durationMs, int probeType, int returnCode) { @@ -109,12 +122,13 @@ public final class ValidationProbeEvent implements Parcelable { @Override public String toString() { - return String.format("ValidationProbeEvent(%d, %s:%d, %dms)", - netId, getProbeName(probeType), returnCode, durationMs); + return String.format("ValidationProbeEvent(%d, %s:%d %s, %dms)", netId, + getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs); } final static class Decoder { static final SparseArray constants = MessageUtils.findMessageNames( - new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"}); + new Class[]{ValidationProbeEvent.class}, + new String[]{"PROBE_", "FIRST_", "REVALIDATION"}); } } diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index c73d1dd954375..d6173cb9a3122 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -96,6 +96,24 @@ public class NetworkMonitor extends StateMachine { private static final int SOCKET_TIMEOUT_MS = 10000; private static final int PROBE_TIMEOUT_MS = 3000; + static enum EvaluationResult { + VALIDATED(true), + CAPTIVE_PORTAL(false); + final boolean isValidated; + EvaluationResult(boolean isValidated) { + this.isValidated = isValidated; + } + } + + static enum ValidationStage { + FIRST_VALIDATION(true), + REVALIDATION(false); + final boolean isFirstValidation; + ValidationStage(boolean isFirstValidation) { + this.isFirstValidation = isFirstValidation; + } + } + public static final String ACTION_NETWORK_CONDITIONS_MEASURED = "android.net.conn.NETWORK_CONDITIONS_MEASURED"; public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type"; @@ -215,6 +233,8 @@ public class NetworkMonitor extends StateMachine { protected boolean mIsCaptivePortalCheckEnabled; private boolean mUseHttps; + // The total number of captive portal detection attempts for this NetworkMonitor instance. + private int mValidations = 0; // Set if the user explicitly selected "Do not use this network" in captive portal sign-in app. private boolean mUserDoesNotWant = false; @@ -289,6 +309,10 @@ public class NetworkMonitor extends StateMachine { return validationLogs.readOnlyLocalLog(); } + private ValidationStage validationStage() { + return 0 == mValidations ? ValidationStage.FIRST_VALIDATION : ValidationStage.REVALIDATION; + } + // DefaultState is the parent of all States. It exists only to handle CMD_* messages but // does not entail any real state (hence no enter() or exit() routines). private class DefaultState extends State { @@ -365,9 +389,11 @@ public class NetworkMonitor extends StateMachine { private class ValidatedState extends State { @Override public void enter() { - maybeLogEvaluationResult(NetworkEvent.NETWORK_VALIDATED); + maybeLogEvaluationResult( + networkEventType(validationStage(), EvaluationResult.VALIDATED)); mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null)); + mValidations++; } @Override @@ -583,7 +609,8 @@ public class NetworkMonitor extends StateMachine { @Override public void enter() { - maybeLogEvaluationResult(NetworkEvent.NETWORK_CAPTIVE_PORTAL_FOUND); + maybeLogEvaluationResult( + networkEventType(validationStage(), EvaluationResult.CAPTIVE_PORTAL)); // Don't annoy user with sign-in notifications. if (mDontDisplaySigninNotification) return; // Create a CustomIntentReceiver that sends us a @@ -603,6 +630,7 @@ public class NetworkMonitor extends StateMachine { // Retest for captive portal occasionally. sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */, CAPTIVE_PORTAL_REEVALUATE_DELAY_MS); + mValidations++; } @Override @@ -973,6 +1001,22 @@ public class NetworkMonitor extends StateMachine { mMetricsLog.log(new NetworkEvent(mNetId, evtype)); } + private int networkEventType(ValidationStage s, EvaluationResult r) { + if (s.isFirstValidation) { + if (r.isValidated) { + return NetworkEvent.NETWORK_FIRST_VALIDATION_SUCCESS; + } else { + return NetworkEvent.NETWORK_FIRST_VALIDATION_PORTAL_FOUND; + } + } else { + if (r.isValidated) { + return NetworkEvent.NETWORK_REVALIDATION_SUCCESS; + } else { + return NetworkEvent.NETWORK_REVALIDATION_PORTAL_FOUND; + } + } + } + private void maybeLogEvaluationResult(int evtype) { if (mEvaluationTimer.isRunning()) { mMetricsLog.log(new NetworkEvent(mNetId, evtype, mEvaluationTimer.stop())); @@ -981,6 +1025,8 @@ public class NetworkMonitor extends StateMachine { } private void logValidationProbe(long durationMs, int probeType, int probeResult) { + probeType = + ValidationProbeEvent.makeProbeType(probeType, validationStage().isFirstValidation); mMetricsLog.log(new ValidationProbeEvent(mNetId, durationMs, probeType, probeResult)); } } From 2a43b208ccda994b0be8722d7785fc669603cdaa Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 16 Nov 2016 18:18:08 +0900 Subject: [PATCH 16/21] DO NOT MERGE: NetworkMonitor: send one DNS probe per web probe This patch changes sligthly the two web probes mechanism for captive portal detection and network validation so that DNS resolution is always done for both probes. In general the target web servers of the two parallel HTTP and HTTPS probes are now different. This introduces a bias in the latency measurement of th HTTPS probe since this latency will also include DNS resolution in general. Test: manual verification + $ runtest frameworks-net Bug: 32198726 (cherry picked from commit ab61e7c324b24e46829495bc2597e42ea907c53d) Change-Id: I3b32ae451f2241849fffe24956758a9f571b1ef1 --- .../server/connectivity/NetworkMonitor.java | 96 ++++++++++--------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index d6173cb9a3122..ea2cf5fb4a7ef 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -706,48 +706,13 @@ public class NetworkMonitor extends StateMachine { long startTime = SystemClock.elapsedRealtime(); - // Pre-resolve the captive portal server host so we can log it. - // Only do this if HttpURLConnection is about to, to avoid any potentially - // unnecessary resolution. - String hostToResolve = null; + final CaptivePortalProbeResult result; if (pacUrl != null) { - hostToResolve = pacUrl.getHost(); - } else if (proxyInfo != null) { - hostToResolve = proxyInfo.getHost(); - } else { - hostToResolve = httpUrl.getHost(); - } - - if (!TextUtils.isEmpty(hostToResolve)) { - String probeName = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS); - final Stopwatch dnsTimer = new Stopwatch().start(); - int dnsResult; - long dnsLatency; - try { - InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(hostToResolve); - dnsResult = ValidationProbeEvent.DNS_SUCCESS; - dnsLatency = dnsTimer.stop(); - final StringBuffer connectInfo = new StringBuffer(", " + hostToResolve + "="); - for (InetAddress address : addresses) { - connectInfo.append(address.getHostAddress()); - if (address != addresses[addresses.length-1]) connectInfo.append(","); - } - validationLog(probeName + " OK " + dnsLatency + "ms" + connectInfo); - } catch (UnknownHostException e) { - dnsResult = ValidationProbeEvent.DNS_FAILURE; - dnsLatency = dnsTimer.stop(); - validationLog(probeName + " FAIL " + dnsLatency + "ms, " + hostToResolve); - } - logValidationProbe(dnsLatency, ValidationProbeEvent.PROBE_DNS, dnsResult); - } - - CaptivePortalProbeResult result; - if (pacUrl != null) { - result = sendHttpProbe(pacUrl, ValidationProbeEvent.PROBE_PAC); + result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC); } else if (mUseHttps) { - result = sendParallelHttpProbes(httpsUrl, httpUrl, fallbackUrl); + result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl); } else { - result = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP); + result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); } long endTime = SystemClock.elapsedRealtime(); @@ -760,8 +725,50 @@ public class NetworkMonitor extends StateMachine { } /** - * Do a URL fetch on a known server to see if we get the data we expect. - * Returns HTTP response code. + * Do a DNS resolution and URL fetch on a known web server to see if we get the data we expect. + * @return a CaptivePortalProbeResult inferred from the HTTP response. + */ + private CaptivePortalProbeResult sendDnsAndHttpProbes(ProxyInfo proxy, URL url, int probeType) { + // Pre-resolve the captive portal server host so we can log it. + // Only do this if HttpURLConnection is about to, to avoid any potentially + // unnecessary resolution. + final String host = (proxy != null) ? proxy.getHost() : url.getHost(); + sendDnsProbe(host); + return sendHttpProbe(url, probeType); + } + + /** Do a DNS resolution of the given server. */ + private void sendDnsProbe(String host) { + if (TextUtils.isEmpty(host)) { + return; + } + + final String name = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS); + final Stopwatch watch = new Stopwatch().start(); + int result; + String connectInfo; + try { + InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host); + result = ValidationProbeEvent.DNS_SUCCESS; + StringBuffer buffer = new StringBuffer(host).append("="); + for (InetAddress address : addresses) { + buffer.append(address.getHostAddress()); + if (address != addresses[addresses.length-1]) buffer.append(","); + } + connectInfo = buffer.toString(); + } catch (UnknownHostException e) { + result = ValidationProbeEvent.DNS_FAILURE; + connectInfo = host; + } + final long latency = watch.stop(); + String resultString = (ValidationProbeEvent.DNS_SUCCESS == result) ? "OK" : "FAIL"; + validationLog(String.format("%s %s %dms, %s", name, resultString, latency, connectInfo)); + logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result); + } + + /** + * Do a URL fetch on a known web server to see if we get the data we expect. + * @return a CaptivePortalProbeResult inferred from the HTTP response. */ @VisibleForTesting protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) { @@ -828,7 +835,7 @@ public class NetworkMonitor extends StateMachine { } private CaptivePortalProbeResult sendParallelHttpProbes( - URL httpsUrl, URL httpUrl, URL fallbackUrl) { + ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) { // Number of probes to wait for. If a probe completes with a conclusive answer // it shortcuts the latch immediately by forcing the count to 0. final CountDownLatch latch = new CountDownLatch(2); @@ -848,9 +855,10 @@ public class NetworkMonitor extends StateMachine { @Override public void run() { if (mIsHttps) { - mResult = sendHttpProbe(httpsUrl, ValidationProbeEvent.PROBE_HTTPS); + mResult = + sendDnsAndHttpProbes(proxy, httpsUrl, ValidationProbeEvent.PROBE_HTTPS); } else { - mResult = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP); + mResult = sendDnsAndHttpProbes(proxy, httpUrl, ValidationProbeEvent.PROBE_HTTP); } if ((mIsHttps && mResult.isSuccessful()) || (!mIsHttps && mResult.isPortal())) { // Stop waiting immediately if https succeeds or if http finds a portal. From 963e8ddf6d5ea3bc34216fa03fe24402bf13940a Mon Sep 17 00:00:00 2001 From: Stephen Chen Date: Fri, 21 Oct 2016 12:44:26 -0700 Subject: [PATCH 17/21] DO NOT MERGE: Implement metered tracking for NetworkStats summary queries. Dependent on ag/1550196 where API is defined. Bug: 31015360 Bug: 26545374 Test: runtest --path frameworks/base/core/tests/coretests/src/android/net/NetworkStatsTest.java, other test classes. (cherry picked from commit 25147878974f82f875062e99cdee85dd33f3f078) Change-Id: I46da93ba4afa968facf98f7c3d844fd0c469095a --- core/java/android/app/usage/NetworkStats.java | 12 +- .../app/usage/NetworkStatsManager.java | 43 +- core/java/android/net/NetworkIdentity.java | 6 +- core/java/android/net/NetworkStats.java | 103 +++- ...droid_internal_net_NetworkStatsFactory.cpp | 8 +- .../src/android/net/NetworkStatsTest.java | 528 ++++++++++-------- .../internal/net/NetworkStatsFactoryTest.java | 14 +- .../server/net/NetworkIdentitySet.java | 13 + .../server/net/NetworkStatsCollection.java | 3 + .../server/net/NetworkStatsObserversTest.java | 22 +- .../server/net/NetworkStatsServiceTest.java | 159 ++++-- 11 files changed, 561 insertions(+), 350 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index f64bec73e4c8f..3670b914ecf37 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -256,6 +256,15 @@ public final class NetworkStats implements AutoCloseable { return tag; } + private static @Metered int convertMetered(int metered) { + switch (metered) { + case android.net.NetworkStats.METERED_ALL : return METERED_ALL; + case android.net.NetworkStats.METERED_NO: return METERED_NO; + case android.net.NetworkStats.METERED_YES: return METERED_YES; + } + return 0; + } + private static @Roaming int convertRoaming(int roaming) { switch (roaming) { case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL; @@ -530,8 +539,7 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid); bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag); bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set); - // TODO: Implement metered tracking. - bucketOut.mMetered = Bucket.METERED_ALL; + bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered); bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming); bucketOut.mBeginTimeStamp = mStartTimeStamp; bucketOut.mEndTimeStamp = mEndTimeStamp; diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 7961a72a12e44..840413a1151e8 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -51,16 +51,17 @@ import android.util.Log; * {@link #querySummaryForUser}

* {@link #querySummary}

* These queries aggregate network usage across the whole interval. Therefore there will be only one - * bucket for a particular key and state and roaming combination. In case of the user-wide and - * device-wide summaries a single bucket containing the totalised network usage is returned. + * bucket for a particular key, state, metered and roaming combination. In case of the user-wide + * and device-wide summaries a single bucket containing the totalised network usage is returned. *

* History queries *

* {@link #queryDetailsForUid}

* {@link #queryDetails}

- * These queries do not aggregate over time but do aggregate over state and roaming. Therefore there - * can be multiple buckets for a particular key but all Bucket's state is going to be - * {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be + * These queries do not aggregate over time but do aggregate over state, metered and roaming. + * Therefore there can be multiple buckets for a particular key but all Bucket's state is going to + * be {@link NetworkStats.Bucket#STATE_ALL}, all Bucket's metered is going to be + * {@link NetworkStats.Bucket#METERED_ALL}, and all Bucket's roaming is going to be * {@link NetworkStats.Bucket#ROAMING_ALL}. *

* NOTE: Calling {@link #querySummaryForDevice} or accessing stats for apps other than the @@ -103,10 +104,11 @@ public class NetworkStatsManager { /** * Query network usage statistics summaries. Result is summarised data usage for the whole - * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This - * means the bucket's start and end timestamp are going to be the same as the 'startTime' and - * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid - * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE} + * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and + * roaming. This means the bucket's start and end timestamp are going to be the same as the + * 'startTime' and 'endTime' parameters. State is going to be + * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL}, + * tag {@link NetworkStats.Bucket#TAG_NONE}, metered {@link NetworkStats.Bucket#METERED_ALL}, * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. @@ -142,8 +144,10 @@ public class NetworkStatsManager { * Query network usage statistics summaries. Result is summarised data usage for all uids * belonging to calling user. Result is a single Bucket aggregated over time, state and uid. * This means the bucket's start and end timestamp are going to be the same as the 'startTime' - * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid - * {@link NetworkStats.Bucket#UID_ALL}. + * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, + * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}, + * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming + * {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -177,9 +181,10 @@ public class NetworkStatsManager { /** * Query network usage statistics summaries. Result filtered to include only uids belonging to * calling user. Result is aggregated over time, hence all buckets will have the same start and - * end timestamps. Not aggregated over state or uid. This means buckets' start and end - * timestamps are going to be the same as the 'startTime' and 'endTime' parameters. - * State and uid are going to vary, and tag is going to be the same. + * end timestamps. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, + * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}, + * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming + * {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -262,10 +267,12 @@ public class NetworkStatsManager { /** * Query network usage statistics details. Result filtered to include only uids belonging to - * calling user. Result is aggregated over state but not aggregated over time or uid. This means - * buckets' start and end timestamps are going to be between 'startTime' and 'endTime' - * parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary, - * tag {@link NetworkStats.Bucket#TAG_NONE} and roaming is going to be + * calling user. Result is aggregated over state but not aggregated over time, uid, tag, + * metered, nor roaming. This means buckets' start and end timestamps are going to be between + * 'startTime' and 'endTime' parameters. State is going to be + * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary, + * tag {@link NetworkStats.Bucket#TAG_NONE}, metered is going to be + * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be * {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index d570e66a24357..c704ef0c9ca7c 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -171,7 +171,8 @@ public class NetworkIdentity implements Comparable { String subscriberId = null; String networkId = null; boolean roaming = false; - boolean metered = false; + boolean metered = !state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_METERED); if (isNetworkTypeMobile(type)) { if (state.subscriberId == null) { @@ -185,9 +186,6 @@ public class NetworkIdentity implements Comparable { subscriberId = state.subscriberId; roaming = state.networkInfo.isRoaming(); - metered = !state.networkCapabilities.hasCapability( - NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } else if (type == TYPE_WIFI) { if (state.networkId != null) { networkId = state.networkId; diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index f65a50f02df32..77ce65b0815a5 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -68,11 +68,18 @@ public class NetworkStats implements Parcelable { // TODO: Rename TAG_NONE to TAG_ALL. public static final int TAG_NONE = 0; - /** {@link #set} value for all roaming values. */ + /** {@link #metered} value to account for all metered states. */ + public static final int METERED_ALL = -1; + /** {@link #metered} value where native, unmetered data is accounted. */ + public static final int METERED_NO = 0; + /** {@link #metered} value where metered data is accounted. */ + public static final int METERED_YES = 1; + + /** {@link #roaming} value to account for all roaming states. */ public static final int ROAMING_ALL = -1; - /** {@link #set} value where native, non-roaming data is accounted. */ + /** {@link #roaming} value where native, non-roaming data is accounted. */ public static final int ROAMING_NO = 0; - /** {@link #set} value where roaming data is accounted. */ + /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; // TODO: move fields to "mVariable" notation @@ -88,6 +95,7 @@ public class NetworkStats implements Parcelable { private int[] uid; private int[] set; private int[] tag; + private int[] metered; private int[] roaming; private long[] rxBytes; private long[] rxPackets; @@ -100,6 +108,12 @@ public class NetworkStats implements Parcelable { public int uid; public int set; public int tag; + /** + * Note that this is only populated w/ the default value when read from /proc or written + * to disk. We merge in the correct value when reporting this value to clients of + * getSummary(). + */ + public int metered; /** * Note that this is only populated w/ the default value when read from /proc or written * to disk. We merge in the correct value when reporting this value to clients of @@ -123,16 +137,17 @@ public class NetworkStats implements Parcelable { public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - this(iface, uid, set, tag, ROAMING_NO, rxBytes, rxPackets, txBytes, txPackets, - operations); + this(iface, uid, set, tag, METERED_NO, ROAMING_NO, rxBytes, rxPackets, txBytes, + txPackets, operations); } - public Entry(String iface, int uid, int set, int tag, int roaming, long rxBytes, - long rxPackets, long txBytes, long txPackets, long operations) { + public Entry(String iface, int uid, int set, int tag, int metered, int roaming, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { this.iface = iface; this.uid = uid; this.set = set; this.tag = tag; + this.metered = metered; this.roaming = roaming; this.rxBytes = rxBytes; this.rxPackets = rxPackets; @@ -165,6 +180,7 @@ public class NetworkStats implements Parcelable { builder.append(" uid=").append(uid); builder.append(" set=").append(setToString(set)); builder.append(" tag=").append(tagToString(tag)); + builder.append(" metered=").append(meteredToString(metered)); builder.append(" roaming=").append(roamingToString(roaming)); builder.append(" rxBytes=").append(rxBytes); builder.append(" rxPackets=").append(rxPackets); @@ -178,13 +194,18 @@ public class NetworkStats implements Parcelable { public boolean equals(Object o) { if (o instanceof Entry) { final Entry e = (Entry) o; - return uid == e.uid && set == e.set && tag == e.tag && roaming == e.roaming - && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes - && txPackets == e.txPackets && operations == e.operations - && iface.equals(e.iface); + return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered + && roaming == e.roaming && rxBytes == e.rxBytes && rxPackets == e.rxPackets + && txBytes == e.txBytes && txPackets == e.txPackets + && operations == e.operations && iface.equals(e.iface); } return false; } + + @Override + public int hashCode() { + return Objects.hash(uid, set, tag, metered, roaming, iface); + } } public NetworkStats(long elapsedRealtime, int initialSize) { @@ -196,6 +217,7 @@ public class NetworkStats implements Parcelable { this.uid = new int[initialSize]; this.set = new int[initialSize]; this.tag = new int[initialSize]; + this.metered = new int[initialSize]; this.roaming = new int[initialSize]; this.rxBytes = new long[initialSize]; this.rxPackets = new long[initialSize]; @@ -209,6 +231,7 @@ public class NetworkStats implements Parcelable { this.uid = EmptyArray.INT; this.set = EmptyArray.INT; this.tag = EmptyArray.INT; + this.metered = EmptyArray.INT; this.roaming = EmptyArray.INT; this.rxBytes = EmptyArray.LONG; this.rxPackets = EmptyArray.LONG; @@ -226,6 +249,7 @@ public class NetworkStats implements Parcelable { uid = parcel.createIntArray(); set = parcel.createIntArray(); tag = parcel.createIntArray(); + metered = parcel.createIntArray(); roaming = parcel.createIntArray(); rxBytes = parcel.createLongArray(); rxPackets = parcel.createLongArray(); @@ -243,6 +267,7 @@ public class NetworkStats implements Parcelable { dest.writeIntArray(uid); dest.writeIntArray(set); dest.writeIntArray(tag); + dest.writeIntArray(metered); dest.writeIntArray(roaming); dest.writeLongArray(rxBytes); dest.writeLongArray(rxPackets); @@ -277,10 +302,11 @@ public class NetworkStats implements Parcelable { } @VisibleForTesting - public NetworkStats addValues(String iface, int uid, int set, int tag, int roaming, + public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { return addValues(new Entry( - iface, uid, set, tag, roaming, rxBytes, rxPackets, txBytes, txPackets, operations)); + iface, uid, set, tag, metered, roaming, rxBytes, rxPackets, txBytes, txPackets, + operations)); } /** @@ -294,6 +320,7 @@ public class NetworkStats implements Parcelable { uid = Arrays.copyOf(uid, newLength); set = Arrays.copyOf(set, newLength); tag = Arrays.copyOf(tag, newLength); + metered = Arrays.copyOf(metered, newLength); roaming = Arrays.copyOf(roaming, newLength); rxBytes = Arrays.copyOf(rxBytes, newLength); rxPackets = Arrays.copyOf(rxPackets, newLength); @@ -307,6 +334,7 @@ public class NetworkStats implements Parcelable { uid[size] = entry.uid; set[size] = entry.set; tag[size] = entry.tag; + metered[size] = entry.metered; roaming[size] = entry.roaming; rxBytes[size] = entry.rxBytes; rxPackets[size] = entry.rxPackets; @@ -327,6 +355,7 @@ public class NetworkStats implements Parcelable { entry.uid = uid[i]; entry.set = set[i]; entry.tag = tag[i]; + entry.metered = metered[i]; entry.roaming = roaming[i]; entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; @@ -381,7 +410,8 @@ public class NetworkStats implements Parcelable { * also be used to subtract values from existing rows. */ public NetworkStats combineValues(Entry entry) { - final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.roaming); + final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, + entry.roaming); if (i == -1) { // only create new entry when positive contribution addValues(entry); @@ -409,10 +439,11 @@ public class NetworkStats implements Parcelable { /** * Find first stats index that matches the requested parameters. */ - public int findIndex(String iface, int uid, int set, int tag, int roaming) { + public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming) { for (int i = 0; i < size; i++) { if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] - && roaming == this.roaming[i] && Objects.equals(iface, this.iface[i])) { + && metered == this.metered[i] && roaming == this.roaming[i] + && Objects.equals(iface, this.iface[i])) { return i; } } @@ -424,7 +455,7 @@ public class NetworkStats implements Parcelable { * search around the hinted index as an optimization. */ @VisibleForTesting - public int findIndexHinted(String iface, int uid, int set, int tag, int roaming, + public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming, int hintIndex) { for (int offset = 0; offset < size; offset++) { final int halfOffset = offset / 2; @@ -438,7 +469,8 @@ public class NetworkStats implements Parcelable { } if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] - && roaming == this.roaming[i] && Objects.equals(iface, this.iface[i])) { + && metered == this.metered[i] && roaming == this.roaming[i] + && Objects.equals(iface, this.iface[i])) { return i; } } @@ -452,7 +484,7 @@ public class NetworkStats implements Parcelable { */ public void spliceOperationsFrom(NetworkStats stats) { for (int i = 0; i < size; i++) { - final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], roaming[i]); + final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i]); if (j == -1) { operations[i] = 0; } else { @@ -542,6 +574,7 @@ public class NetworkStats implements Parcelable { entry.uid = limitUid; entry.set = SET_ALL; entry.tag = TAG_NONE; + entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; entry.rxBytes = 0; entry.rxPackets = 0; @@ -637,11 +670,12 @@ public class NetworkStats implements Parcelable { entry.uid = left.uid[i]; entry.set = left.set[i]; entry.tag = left.tag[i]; + entry.metered = left.metered[i]; entry.roaming = left.roaming[i]; // find remote row that matches, and subtract final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, - entry.roaming, i); + entry.metered, entry.roaming, i); if (j == -1) { // newly appearing row, return entire value entry.rxBytes = left.rxBytes[i]; @@ -687,6 +721,7 @@ public class NetworkStats implements Parcelable { entry.uid = UID_ALL; entry.set = SET_ALL; entry.tag = TAG_NONE; + entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; entry.operations = 0L; @@ -716,6 +751,7 @@ public class NetworkStats implements Parcelable { entry.iface = IFACE_ALL; entry.set = SET_ALL; entry.tag = TAG_NONE; + entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; for (int i = 0; i < size; i++) { @@ -762,6 +798,7 @@ public class NetworkStats implements Parcelable { pw.print(" uid="); pw.print(uid[i]); pw.print(" set="); pw.print(setToString(set[i])); pw.print(" tag="); pw.print(tagToString(tag[i])); + pw.print(" metered="); pw.print(meteredToString(metered[i])); pw.print(" roaming="); pw.print(roamingToString(roaming[i])); pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); @@ -829,6 +866,22 @@ public class NetworkStats implements Parcelable { return "0x" + Integer.toHexString(tag); } + /** + * Return text description of {@link #metered} value. + */ + public static String meteredToString(int metered) { + switch (metered) { + case METERED_ALL: + return "ALL"; + case METERED_NO: + return "NO"; + case METERED_YES: + return "YES"; + default: + return "UNKNOWN"; + } + } + /** * Return text description of {@link #roaming} value. */ @@ -998,6 +1051,7 @@ public class NetworkStats implements Parcelable { tmpEntry.uid = uid[i]; tmpEntry.tag = tag[i]; tmpEntry.set = set[i]; + tmpEntry.metered = metered[i]; tmpEntry.roaming = roaming[i]; combineValues(tmpEntry); if (tag[i] == TAG_NONE) { @@ -1017,24 +1071,25 @@ public class NetworkStats implements Parcelable { moved.set = SET_DBG_VPN_OUT; moved.tag = TAG_NONE; moved.iface = underlyingIface; + moved.metered = METERED_ALL; moved.roaming = ROAMING_ALL; combineValues(moved); // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than // the TAG_NONE traffic. // - // Relies on the fact that the underlying traffic only has state ROAMING_NO, which - // should be the case as it comes directly from the /proc file. We only blend in the + // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, + // which should be the case as it comes directly from the /proc file. We only blend in the // roaming data after applying these adjustments, by checking the NetworkIdentity of the // underlying iface. int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - ROAMING_NO); + METERED_NO, ROAMING_NO); if (idxVpnBackground != -1) { tunSubtract(idxVpnBackground, this, moved); } int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - ROAMING_NO); + METERED_NO, ROAMING_NO); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved); } diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 9fa90acc02a43..4a2b88142e788 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -43,6 +43,7 @@ static struct { jfieldID uid; jfieldID set; jfieldID tag; + jfieldID metered; jfieldID roaming; jfieldID rxBytes; jfieldID rxPackets; @@ -239,6 +240,9 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, ScopedIntArrayRW tag(env, get_int_array(env, stats, gNetworkStatsClassInfo.tag, size, grow)); if (tag.get() == NULL) return -1; + ScopedIntArrayRW metered(env, get_int_array(env, stats, + gNetworkStatsClassInfo.metered, size, grow)); + if (metered.get() == NULL) return -1; ScopedIntArrayRW roaming(env, get_int_array(env, stats, gNetworkStatsClassInfo.roaming, size, grow)); if (roaming.get() == NULL) return -1; @@ -265,7 +269,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, uid[i] = lines[i].uid; set[i] = lines[i].set; tag[i] = lines[i].tag; - // Roaming is populated in Java-land by inspecting the iface properties. + // Metered and Roaming are populated in Java-land by inspecting the iface properties. rxBytes[i] = lines[i].rxBytes; rxPackets[i] = lines[i].rxPackets; txBytes[i] = lines[i].txBytes; @@ -279,6 +283,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray()); + env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray()); @@ -311,6 +316,7 @@ int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { gNetworkStatsClassInfo.uid = GetFieldIDOrDie(env, clazz, "uid", "[I"); gNetworkStatsClassInfo.set = GetFieldIDOrDie(env, clazz, "set", "[I"); gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I"); + gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I"); gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I"); gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J"); gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J"); diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index d48a67a4c72f7..eb85eb445cbcd 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -16,6 +16,9 @@ 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; @@ -45,103 +48,124 @@ public class NetworkStatsTest extends TestCase { private static final long TEST_START = 1194220800000L; public void testFindIndex() throws Exception { - 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); + 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); - 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)); + 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)); } public void testFindIndexHinted() { final NetworkStats stats = new NetworkStats(TEST_START, 3) - .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); + .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); // 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, - ROAMING_NO, hint)); + METERED_NO, ROAMING_NO, hint)); assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, - ROAMING_NO, hint)); + METERED_NO, ROAMING_NO, hint)); assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, - ROAMING_NO, hint)); + METERED_NO, ROAMING_NO, hint)); assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, - ROAMING_NO, hint)); + METERED_NO, ROAMING_NO, hint)); assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, - ROAMING_NO, hint)); - assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - ROAMING_NO, hint)); + METERED_NO, ROAMING_NO, hint)); + assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, + METERED_YES, ROAMING_NO, hint)); assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - ROAMING_YES, hint)); + METERED_NO, ROAMING_NO, hint)); + assertEquals(7, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, + METERED_YES, ROAMING_YES, hint)); assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, - ROAMING_NO, hint)); + METERED_NO, ROAMING_NO, hint)); } } public void testAddEntryGrow() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 3); + final NetworkStats stats = new NetworkStats(TEST_START, 4); assertEquals(0, stats.size()); - assertEquals(3, stats.internalSize()); + assertEquals(4, stats.internalSize()); - 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, + stats.addValues(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, ROAMING_NO, 2L, 2L, + stats.addValues(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, ROAMING_YES, 3L, 3L, - 2L, 2L, 5); - assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, + 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, 40L, 4L, 40L, 7); - assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5L, 50L, 4L, 40L, 8); - assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 6L, 60L, 5L, 50L, 10); - assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, 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 { @@ -152,20 +176,18 @@ 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, ROAMING_NO, 384L, 3L, - 128L, 1L, 9); - assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_NO, 128L, 1L, 128L, - 1L, 2); + 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); // 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, 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); + 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); } public void testSubtractIdenticalData() throws Exception { @@ -180,10 +202,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, 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, 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); } public void testSubtractIdenticalRows() throws Exception { @@ -198,10 +220,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, ROAMING_NO, 1L, 1L, 2L, - 1L, 4); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 3L, 1L, 4L, - 1L, 8); + 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); } public void testSubtractNewRows() throws Exception { @@ -217,12 +239,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, 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); + 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); } public void testSubtractMissingRows() throws Exception { @@ -237,8 +259,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, ROAMING_NO, 1L, - 2L, 3L, 4L, 0); + assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, 1L, 2L, 3L, 4L, 0); assertEquals(4L, result.getTotalBytes()); } @@ -263,13 +285,22 @@ 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, 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); + .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); assertEquals(96L, uidRoaming.getTotalBytes()); } @@ -283,95 +314,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, ROAMING_NO, 128L, 8L, 0L, 2L, - 20L) - .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, + .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, 0L, 2L, 20L) - .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_YES, 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); final NetworkStats grouped = uidStats.groupedByIface(); assertEquals(3, uidStats.size()); assertEquals(1, grouped.size()); - assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L, - 6L, 0L); + assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, 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, 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, + .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, 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); + .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); final NetworkStats grouped = uidStats.groupedByIface(); assertEquals(7, uidStats.size()); assertEquals(2, grouped.size()); - 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); + 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); } public void testAddAllValues() { final NetworkStats first = new NetworkStats(TEST_START, 5) - .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); + .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); final NetworkStats second = new NetworkStats(TEST_START, 2) - .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, + .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, ROAMING_YES, 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); first.combineAllValues(second); assertEquals(4, first.size()); - 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, + assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 64L, 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, 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, + .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, 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); + .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); assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L); assertValues(stats.getTotal(null, 100), 1280L, 80L, 0L, 2L, 20L); @@ -396,10 +427,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, ROAMING_NO, 128L, 8L, - 0L, 0L, 0L); - assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, - 0L, 0L); + 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); } public void testClone() throws Exception { @@ -434,77 +465,90 @@ 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, 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) + .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) // VPN package also uses some traffic through unprotected network. - .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 4983L, 10L, 1801L, 12L, 0L) - .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) + .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) // Tag entries - .addValues(tunIface, 10120, SET_DEFAULT, testTag1, 21691L, 41L, 13820L, 51L, 0L) - .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 665L, 2L, 0L) + .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) // Irrelevant entries - .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, 1685L, 5L, 2070L, 6L, 0L) + .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1685L, 5L, + 2070L, 6L, 0L) // Underlying Iface entries - .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); + .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); 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, ROAMING_NO, + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 39605L, 46L, 12259L, 55L, 0L); - 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, + 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, 72667L, 197L, 43909L, 241L, 0L); - assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO, + assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 9297L, 17L, 4128L, 21L, 0L); - assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, + assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4983L, 10L, 1801L, 12L, 0L); - 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, + 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, 21691L, 41L, 13820L, 51L, 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); + 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); // Existing underlying Iface entries are updated - 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); + 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); // VPN underlying Iface entries are updated - 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); + 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); // New entries are added for new application's underlying Iface traffic - 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); + 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); // New entries are added for debug purpose - 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); + 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); } @@ -518,72 +562,78 @@ 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, 50000L, 25L, 100000L, 50L, 0L) - .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, 500L, 2L, 200L, 5L, 0L) + .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) // VPN package resends data through the tunnel (with exaggerated overhead) - .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 240000, 100L, 120000L, 60L, 0L) + .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 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, 1000L, 10L, 2000L, 20L, 0L) + .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 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, + .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 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, ROAMING_NO, + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50000L, 25L, 100000L, 50L, 0L); - assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, ROAMING_NO, + assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 500L, 2L, 200L, 5L, 0L); - assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, + assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 240000L, 100L, 120000L, 60L, 0L); // Existing underlying Iface entries are updated - assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, - 51000L, 35L, 102000L, 70L, 0L); + assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, 51000L, 35L, 102000L, 70L, 0L); // VPN underlying Iface entries are updated - assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, - 25000L, 10L, 29800L, 15L, 0L); + assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, + 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, ROAMING_NO, - 500L, 2L, 200L, 5L, 0L); + assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, 500L, 2L, 200L, 5L, 0L); // New entries are added for debug purpose - 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); + 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); } private static void assertContains(NetworkStats stats, String iface, int uid, int set, - int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, - long operations) { - int index = stats.findIndex(iface, uid, set, tag, roaming); + 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); assertTrue(index != -1); - assertValues(stats, index, iface, uid, set, tag, roaming, + assertValues(stats, index, iface, uid, set, tag, metered, roaming, rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, - int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, - long operations) { + int tag, int metered, 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, roaming); + assertValues(entry, iface, uid, set, tag, metered, roaming); assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues( - NetworkStats.Entry entry, String iface, int uid, int set, int tag, int roaming) { + NetworkStats.Entry entry, String iface, int uid, int set, int tag, int metered, + 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); } diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java index 327f3fda3f340..7f13abc6d2c5c 100644 --- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java +++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java @@ -16,6 +16,7 @@ package com.android.internal.net; +import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; @@ -101,12 +102,14 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { final NetworkStats stats = mFactory.readNetworkStatsDetail(); assertEquals(70, stats.size()); - assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L, 676L); + assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L, + 676L); assertStatsEntry(stats, "rmnet1", 10021, SET_FOREGROUND, 0x30100000, 742L, 3L, 1265L, 3L); } public void testNetworkStatsSingle() throws Exception { - stageFile(R.raw.xt_qtaguid_iface_typical, new File(mTestProc, "net/xt_qtaguid/iface_stat_all")); + stageFile(R.raw.xt_qtaguid_iface_typical, + new File(mTestProc, "net/xt_qtaguid/iface_stat_all")); final NetworkStats stats = mFactory.readNetworkStatsSummaryDev(); assertEquals(6, stats.size()); @@ -122,7 +125,8 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { final NetworkStats stats = mFactory.readNetworkStatsSummaryXt(); assertEquals(3, stats.size()); assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 6824L, 16L, 5692L, 10L); - assertStatsEntry(stats, "rmnet1", UID_ALL, SET_ALL, TAG_NONE, 11153922L, 8051L, 190226L, 2468L); + assertStatsEntry(stats, "rmnet1", UID_ALL, SET_ALL, TAG_NONE, 11153922L, 8051L, 190226L, + 2468L); assertStatsEntry(stats, "rmnet2", UID_ALL, SET_ALL, TAG_NONE, 4968L, 35L, 3081L, 39L); } @@ -157,7 +161,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, int tag, long rxBytes, long txBytes) { - final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO); + final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO); final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected txBytes", txBytes, entry.txBytes); @@ -165,7 +169,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { - final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO); + final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO); final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index 959a823290014..c48f43058fca7 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -91,6 +91,19 @@ public class NetworkIdentitySet extends HashSet implements } } + /** @return whether any {@link NetworkIdentity} in this set is considered metered. */ + public boolean isAnyMemberMetered() { + if (isEmpty()) { + return false; + } + for (NetworkIdentity ident : this) { + if (ident.getMetered()) { + return true; + } + } + return false; + } + /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */ public boolean isAnyMemberRoaming() { if (isEmpty()) { diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 673dd8fbbd664..c45b4169f575b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.METERED_NO; +import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.NetworkStats.SET_ALL; @@ -242,6 +244,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; + entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; entry.rxPackets = historyEntry.rxPackets; diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java index 21560acbf3bb8..5eee7b948cd0c 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java @@ -25,6 +25,7 @@ import static org.mockito.Matchers.isA; import static org.mockito.Mockito.when; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkTemplate.buildTemplateMobileAll; @@ -336,7 +337,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -344,7 +345,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -374,7 +375,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -382,7 +383,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -412,7 +413,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -420,7 +421,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -450,16 +451,17 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO, - BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); + .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, VPN_INFO, TEST_START); // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO, - BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); + .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, + 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, VPN_INFO, TEST_START); 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 f2cf90ca916f0..728eb734c52e6 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java @@ -22,6 +22,9 @@ 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; @@ -305,9 +308,10 @@ public class NetworkStatsServiceTest { // 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, ROAMING_NO, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, - 6); + 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_BLUE, 128L, 1L, 128L, 1L, 0); @@ -329,9 +333,10 @@ public class NetworkStatsServiceTest { // 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, ROAMING_NO, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, - 6); + 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_BLUE, 128L, 1L, 128L, 1L, 0); } @@ -638,20 +643,20 @@ public class NetworkStatsServiceTest { 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, 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); + 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); // 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, ROAMING_NO, 1024L, 8L, - 512L, 4L, 0); + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + 1024L, 8L, 512L, 4L, 0); } @Test @@ -705,14 +710,56 @@ 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, 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); + 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); + } + + @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 @@ -733,14 +780,14 @@ public class NetworkStatsServiceTest { expectCurrentTime(); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); - // 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. + // 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, ROAMING_NO, 128L, 2L, - 128L, 2L, 0L) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, - 1L, 0L)); + .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)); forcePollAndWaitForIdle(); // verify service recorded history @@ -750,10 +797,10 @@ 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, ROAMING_YES, 128L, 2L, - 128L, 2L, 0); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L, - 1L, 0); + 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); } @Test @@ -780,7 +827,8 @@ 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); forcePollAndWaitForIdle(); @@ -923,18 +971,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, ROAMING_NO, rxBytes, - rxPackets, txBytes, txPackets, operations); + assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_ALL, 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, ROAMING_ALL, rxBytes, rxPackets, txBytes, txPackets, - operations); + assertUidTotal(template, uid, SET_ALL, METERED_ALL, ROAMING_ALL, rxBytes, rxPackets, + txBytes, txPackets, operations); } - private void assertUidTotal(NetworkTemplate template, int uid, int set, int roaming, - long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) + private void assertUidTotal(NetworkTemplate template, int uid, int set, int metered, + int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) throws Exception { // verify history API final NetworkStatsHistory history = mSession.getHistoryForUid( @@ -945,8 +993,8 @@ 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, roaming, rxBytes, rxPackets, txBytes, - txPackets, operations); + assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, metered, roaming, rxBytes, rxPackets, + txBytes, txPackets, operations); } private void expectSystemReady() throws Exception { @@ -1034,8 +1082,8 @@ public class NetworkStatsServiceTest { } private static void assertValues(NetworkStats stats, String iface, int uid, int set, - int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, - int operations) { + int tag, int metered, 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) { @@ -1053,11 +1101,21 @@ 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) { - final int i = stats.findIndex(iface, uid, s, tag, r); - if (i != -1) { - entry.add(stats.getValues(i, null)); + for (int m : meterings) { + final int i = stats.findIndex(iface, uid, s, tag, m, r); + if (i != -1) { + entry.add(stats.getValues(i, null)); + } } } } @@ -1080,11 +1138,18 @@ 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); } From de7f7d195eec64802b7b6eee819c699f1a7d6951 Mon Sep 17 00:00:00 2001 From: Tony Mak Date: Thu, 30 Jun 2016 11:19:20 +0100 Subject: [PATCH 18/21] DO NOT MERGE: Show notification for always-on app VPN This is the same notification as the one shown during legacy lockdown mode, sans the 'reset' button. The notification is only shown during times when VPN has not yet established or has failed, for example during boot or after a crash. Bug: 29123115 (cherry picked from commit 1a405fe300950d6ceae2166fd074b596d8110dbe) Change-Id: I929a05c24df01e21415535a333bb14ac4b790a9d --- .../com/android/server/connectivity/Vpn.java | 64 ++++++++++--- .../android/server/connectivity/VpnTest.java | 91 +++++++++++++------ 2 files changed, 117 insertions(+), 38 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index ede3bda5bea27..afc6247d88cce 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -27,6 +27,8 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -76,6 +78,7 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.LegacyVpnInfo; @@ -241,12 +244,14 @@ public class Vpn { /** * Update current state, dispaching event to listeners. */ - private void updateState(DetailedState detailedState, String reason) { + @VisibleForTesting + protected void updateState(DetailedState detailedState, String reason) { if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); mNetworkInfo.setDetailedState(detailedState, reason, null); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); } + updateAlwaysOnNotification(detailedState); } /** @@ -280,7 +285,10 @@ public class Vpn { } mLockdown = (mAlwaysOn && lockdown); - if (!isCurrentPreparedPackage(packageName)) { + if (isCurrentPreparedPackage(packageName)) { + updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); + } else { + // Prepare this app. The notification will update as a side-effect of updateState(). prepareInternal(packageName); } maybeRegisterPackageChangeReceiverLocked(packageName); @@ -682,22 +690,19 @@ public class Vpn { } } - private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) { - networkInfo.setIsAvailable(false); - networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); + private void agentDisconnect(NetworkAgent networkAgent) { if (networkAgent != null) { + NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); + networkInfo.setIsAvailable(false); + networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); networkAgent.sendNetworkInfo(networkInfo); } } - private void agentDisconnect(NetworkAgent networkAgent) { - NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); - agentDisconnect(networkInfo, networkAgent); - } - private void agentDisconnect() { if (mNetworkInfo.isConnected()) { - agentDisconnect(mNetworkInfo, mNetworkAgent); + mNetworkInfo.setIsAvailable(false); + updateState(DetailedState.DISCONNECTED, "agentDisconnect"); mNetworkAgent = null; } } @@ -1250,6 +1255,43 @@ public class Vpn { } } + private void updateAlwaysOnNotification(DetailedState networkState) { + final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); + updateAlwaysOnNotificationInternal(visible); + } + + @VisibleForTesting + protected void updateAlwaysOnNotificationInternal(boolean visible) { + final UserHandle user = UserHandle.of(mUserHandle); + final long token = Binder.clearCallingIdentity(); + try { + final NotificationManager notificationManager = NotificationManager.from(mContext); + if (!visible) { + notificationManager.cancelAsUser(TAG, 0, user); + return; + } + final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS); + final PendingIntent configIntent = PendingIntent.getActivityAsUser( + mContext, /* request */ 0, intent, + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, + null, user); + final Notification.Builder builder = new Notification.Builder(mContext) + .setDefaults(0) + .setSmallIcon(R.drawable.vpn_connected) + .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected)) + .setContentText(mContext.getString(R.string.vpn_lockdown_config)) + .setContentIntent(configIntent) + .setCategory(Notification.CATEGORY_SYSTEM) + .setPriority(Notification.PRIORITY_LOW) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setOngoing(true) + .setColor(mContext.getColor(R.color.system_notification_accent_color)); + notificationManager.notifyAsUser(TAG, 0, builder.build(), user); + } finally { + Binder.restoreCallingIdentity(token); + } + } + private native int jniCreate(int mtu); private native String jniGetName(int tun); private native int jniSetAddresses(String interfaze, String addresses); diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 5d8b843bbc172..b51b2771db168 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -25,9 +25,11 @@ 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; @@ -43,6 +45,8 @@ 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; @@ -88,14 +92,18 @@ 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()); } @@ -103,7 +111,7 @@ public class VpnTest extends AndroidTestCase { public void testRestrictedProfilesAreAddedToVpn() { setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final Set ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); @@ -117,7 +125,7 @@ public class VpnTest extends AndroidTestCase { public void testManagedProfilesAreNotAddedToVpn() { setMockedUsers(primaryUser, managedProfileA); - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final Set ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); @@ -130,7 +138,7 @@ public class VpnTest extends AndroidTestCase { public void testAddUserToVpnOnlyAddsOneUser() { setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final Set ranges = new ArraySet<>(); vpn.addUserToRanges(ranges, primaryUser.id, null, null); @@ -141,7 +149,7 @@ public class VpnTest extends AndroidTestCase { @SmallTest public void testUidWhiteAndBlacklist() throws Exception { - final Vpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; @@ -166,15 +174,15 @@ public class VpnTest extends AndroidTestCase { @SmallTest public void testLockdownChangingPackage() throws Exception { - final MockVpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); final UidRange user = UidRange.createForUser(primaryUser.id); // Default state. - vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, 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)); - vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, 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)); @@ -182,8 +190,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) })); - vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); - vpn.assertUnblocked(user.start + PKG_UIDS[1]); + assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); @@ -195,13 +203,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) })); - vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - vpn.assertUnblocked(user.start + PKG_UIDS[3]); + assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); + assertUnblocked(vpn, user.start + PKG_UIDS[3]); } @SmallTest public void testLockdownAddingAProfile() throws Exception { - final MockVpn vpn = new MockVpn(primaryUser.id); + final Vpn vpn = spyVpn(primaryUser.id); setMockedUsers(primaryUser); // Make a copy of the restricted profile, as we're going to mark it deleted halfway through. @@ -220,7 +228,7 @@ public class VpnTest extends AndroidTestCase { })); // Verify restricted user isn't affected at first. - vpn.assertUnblocked(profile.start + PKG_UIDS[0]); + assertUnblocked(vpn, profile.start + PKG_UIDS[0]); // Add the restricted user. setMockedUsers(primaryUser, tempProfile); @@ -239,24 +247,53 @@ 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); + } + /** - * A subclass of {@link Vpn} with some of the fields pre-mocked. + * Mock some methods of vpn object. */ - private class MockVpn extends Vpn { - public MockVpn(@UserIdInt int userId) { - super(Looper.myLooper(), mContext, mNetService, userId); - } + private Vpn spyVpn(@UserIdInt int userId) { + final Vpn vpn = spy(new Vpn(Looper.myLooper(), mContext, mNetService, userId)); - public void assertBlocked(int... uids) { - for (int uid : uids) { - assertTrue("Uid " + uid + " should be blocked", isBlockingUid(uid)); - } - } + // Block calls to the NotificationManager or PendingIntent#getActivity. + doNothing().when(vpn).updateAlwaysOnNotificationInternal(anyBoolean()); + return vpn; + } - public void assertUnblocked(int... uids) { - for (int uid : uids) { - assertFalse("Uid " + uid + " should not be blocked", isBlockingUid(uid)); - } + private static void assertBlocked(Vpn vpn, int... uids) { + for (int uid : uids) { + assertTrue("Uid " + uid + " should be blocked", vpn.isBlockingUid(uid)); + } + } + + private static void assertUnblocked(Vpn vpn, int... uids) { + for (int uid : uids) { + assertFalse("Uid " + uid + " should not be blocked", vpn.isBlockingUid(uid)); } } From 744b02069d7589dc192b19fac6c3e7d62d02e88a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 9 Dec 2016 14:19:57 +0900 Subject: [PATCH 19/21] DO NOT MERGE: Add missing dependency. Change-Id: I5deb8e03eb368ab7003f9376f7b4459d2ef5e934 --- services/tests/servicestests/Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index c36462bfac1e8..2187c571d7baa 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -12,6 +12,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := \ + easymocklib \ frameworks-base-testutils \ services.core \ services.devicepolicy \ From 5d0f28c7fdd8432c41ed38659d920fa9fad291fb Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 31 Oct 2016 15:04:37 +0900 Subject: [PATCH 20/21] DO NOT MERGE: Netd events: record connect() success/errno Test: $ runtest frameworks-net pass Bug: 32198976 (cherry picked from commit 8b06bcdfd24100302818ae0e11ee751dd813d5cf) --- .../NetdEventListenerService.java | 25 ++++++++++--------- .../NetdEventListenerServiceTest.java | 11 +++++--- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index 4b175d7a5af80..f8638c544e8ef 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -24,6 +24,7 @@ import android.net.NetworkRequest; import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; +import android.os.RemoteException; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -44,7 +45,7 @@ public class NetdEventListenerService extends INetdEventListener.Stub { public static final String SERVICE_NAME = "netd_listener"; private static final String TAG = NetdEventListenerService.class.getSimpleName(); - private static final boolean DBG = true; + private static final boolean DBG = false; private static final boolean VDBG = false; // TODO: read this constant from system property @@ -86,7 +87,7 @@ public class NetdEventListenerService extends INetdEventListener.Stub { byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount); int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount); mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs)); - maybeLog(String.format("Logging %d results for netId %d", mEventCount, mNetId)); + maybeLog("Logging %d results for netId %d", mEventCount, mNetId); mEventCount = 0; } @@ -136,9 +137,9 @@ public class NetdEventListenerService extends INetdEventListener.Stub { // Called concurrently by multiple binder threads. // This method must not block or perform long-running operations. public synchronized void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs, - String hostname, String[] ipAddresses, int ipAddressesCount, int uid) { - maybeVerboseLog(String.format("onDnsEvent(%d, %d, %d, %d)", - netId, eventType, returnCode, latencyMs)); + String hostname, String[] ipAddresses, int ipAddressesCount, int uid) + throws RemoteException { + maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs); DnsEventBatch batch = mEventBatches.get(netId); if (batch == null) { @@ -151,9 +152,9 @@ public class NetdEventListenerService extends INetdEventListener.Stub { @Override // Called concurrently by multiple binder threads. // This method must not block or perform long-running operations. - public synchronized void onConnectEvent(int netId, int latencyMs, String ipAddr, int port, - int uid) { - maybeVerboseLog(String.format("onConnectEvent(%d, %d)", netId, latencyMs)); + public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr, int port, + int uid) throws RemoteException { + maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs); } public synchronized void dump(PrintWriter writer) { @@ -166,11 +167,11 @@ public class NetdEventListenerService extends INetdEventListener.Stub { pw.decreaseIndent(); } - private static void maybeLog(String s) { - if (DBG) Log.d(TAG, s); + private static void maybeLog(String s, Object... args) { + if (DBG) Log.d(TAG, String.format(s, args)); } - private static void maybeVerboseLog(String s) { - if (VDBG) Log.d(TAG, s); + private static void maybeVerboseLog(String s, Object... args) { + if (VDBG) Log.d(TAG, String.format(s, args)); } } diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 9e2fd6231ba9d..af4a374bffddf 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -22,6 +22,7 @@ import android.net.Network; import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; +import android.os.RemoteException; import junit.framework.TestCase; import org.junit.Before; @@ -157,9 +158,13 @@ public class NetdEventListenerServiceTest extends TestCase { } void log(int netId, int[] latencies) { - for (int l : latencies) { - mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, 0, - 0); + try { + for (int l : latencies) { + mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, + 0, 0); + } + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); } } From cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Fri, 4 Nov 2016 16:06:34 +0900 Subject: [PATCH 21/21] DO NOT MERGE: frameworks-test: adding missing @SmallTest This activates all frameworks-test tests in runs of the continuous platform tests. Test: $ runtest frameworks-net passes (expect Tether Bug: 32561414 (cherry picked from commit fa8a6f6220d1a0027ba7969c2d3f72690ddc6495) Change-Id: I7b0706a7e3368f971d508388e8ad4afc5de9d646 --- .../net/ConnectivityMetricsLoggerTest.java | 6 +++ tests/net/java/android/net/apf/ApfTest.java | 15 ++++---- .../java/android/net/dhcp/DhcpPacketTest.java | 2 + .../net/netlink/NetlinkErrorMessageTest.java | 2 + .../net/netlink/NetlinkSocketTest.java | 3 ++ .../netlink/RtNetlinkNeighborMessageTest.java | 7 +++- .../server/ConnectivityServiceTest.java | 38 ++++++++++--------- .../connectivity/LingerMonitorTest.java | 16 ++++++++ .../MetricsLoggerServiceTest.java | 7 ++++ .../NetdEventListenerServiceTest.java | 6 +++ 10 files changed, 75 insertions(+), 27 deletions(-) diff --git a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java index 6d42cce2e5027..f89603052213b 100644 --- a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java +++ b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java @@ -18,6 +18,7 @@ package android.net; import android.os.Bundle; import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; import java.util.List; import junit.framework.TestCase; import org.mockito.ArgumentCaptor; @@ -49,6 +50,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { mLog = new ConnectivityMetricsLogger(mService); } + @SmallTest public void testLogEvents() throws Exception { mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV); @@ -60,6 +62,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(3), gotEvents.get(2)); } + @SmallTest public void testLogEventTriggerThrottling() throws Exception { when(mService.logEvent(any())).thenReturn(1234L); @@ -70,6 +73,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(1), gotEvents.get(0)); } + @SmallTest public void testLogEventFails() throws Exception { when(mService.logEvent(any())).thenReturn(-1L); // Error. @@ -80,6 +84,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(1), gotEvents.get(0)); } + @SmallTest public void testLogEventWhenThrottling() throws Exception { when(mService.logEvent(any())).thenReturn(Long.MAX_VALUE); // Throttled @@ -92,6 +97,7 @@ public class ConnectivityMetricsLoggerTest extends TestCase { assertEventsEqual(expectedEvent(1), gotEvents.get(0)); } + @SmallTest public void testLogEventRecoverFromThrottling() throws Exception { final long throttleTimeout = System.currentTimeMillis() + 10; when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L); diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java index f41ea922305b4..ff6175427ce71 100644 --- a/tests/net/java/android/net/apf/ApfTest.java +++ b/tests/net/java/android/net/apf/ApfTest.java @@ -33,7 +33,6 @@ import android.system.ErrnoException; import android.system.Os; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; -import android.test.suitebuilder.annotation.MediumTest; import static android.system.OsConstants.*; import com.android.frameworks.tests.net.R; @@ -155,7 +154,7 @@ public class ApfTest extends AndroidTestCase { * generating bytecode for that program and running it through the * interpreter to verify it functions correctly. */ - @MediumTest + @SmallTest public void testApfInstructions() throws IllegalInstructionException { // Empty program should pass because having the program counter reach the // location immediately after the program indicates the packet should be @@ -563,7 +562,7 @@ public class ApfTest extends AndroidTestCase { * Generate some BPF programs, translate them to APF, then run APF and BPF programs * over packet traces and verify both programs filter out the same packets. */ - @MediumTest + @SmallTest public void testApfAgainstBpf() throws Exception { String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53", "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24", @@ -725,7 +724,7 @@ public class ApfTest extends AndroidTestCase { private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; - @MediumTest + @SmallTest public void testApfFilterIPv4() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); @@ -780,7 +779,7 @@ public class ApfTest extends AndroidTestCase { apfFilter.shutdown(); } - @MediumTest + @SmallTest public void testApfFilterIPv6() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog); @@ -812,7 +811,7 @@ public class ApfTest extends AndroidTestCase { apfFilter.shutdown(); } - @MediumTest + @SmallTest public void testApfFilterMulticast() throws Exception { final byte[] unicastIpv4Addr = {(byte)192,0,2,63}; final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; @@ -922,7 +921,7 @@ public class ApfTest extends AndroidTestCase { assertDrop(program, garpReply()); } - @MediumTest + @SmallTest public void testApfFilterArp() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog); @@ -1041,7 +1040,7 @@ public class ApfTest extends AndroidTestCase { ipManagerCallback.assertNoProgramUpdate(); } - @MediumTest + @SmallTest public void testApfFilterRa() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog); diff --git a/tests/net/java/android/net/dhcp/DhcpPacketTest.java b/tests/net/java/android/net/dhcp/DhcpPacketTest.java index bc8baa12a45b4..d79c312a9edd5 100644 --- a/tests/net/java/android/net/dhcp/DhcpPacketTest.java +++ b/tests/net/java/android/net/dhcp/DhcpPacketTest.java @@ -473,6 +473,7 @@ public class DhcpPacketTest extends TestCase { assertEquals(Integer.toHexString(expected), Integer.toHexString(got)); } + @SmallTest public void testTruncatedOfferPackets() throws Exception { final byte[] packet = HexDump.hexStringToByteArray( // IP header. @@ -506,6 +507,7 @@ public class DhcpPacketTest extends TestCase { } } + @SmallTest public void testRandomPackets() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java index e677475f5907b..5deba27d80dcd 100644 --- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java +++ b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java @@ -24,6 +24,7 @@ import android.net.netlink.NetlinkConstants; import android.net.netlink.NetlinkErrorMessage; import android.net.netlink.NetlinkMessage; import android.net.netlink.StructNlMsgErr; +import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -53,6 +54,7 @@ public class NetlinkErrorMessageTest extends TestCase { public static final byte[] NLM_ERROR_OK = HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false); + @SmallTest public void testParseNlmErrorOk() { final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java index c599fe3e5b762..78b3b704e7868 100644 --- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java +++ b/tests/net/java/android/net/netlink/NetlinkSocketTest.java @@ -20,6 +20,7 @@ import android.net.netlink.NetlinkSocket; import android.net.netlink.RtNetlinkNeighborMessage; import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlMsgHdr; +import android.test.suitebuilder.annotation.SmallTest; import android.system.ErrnoException; import android.system.NetlinkSocketAddress; import android.system.OsConstants; @@ -33,6 +34,7 @@ import junit.framework.TestCase; public class NetlinkSocketTest extends TestCase { private final String TAG = "NetlinkSocketTest"; + @SmallTest public void testBasicWorkingGetNeighborsQuery() throws Exception { NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE); assertNotNull(s); @@ -91,6 +93,7 @@ public class NetlinkSocketTest extends TestCase { s.close(); } + @SmallTest public void testRepeatedCloseCallsAreQuiet() throws Exception { // Create a working NetlinkSocket. NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE); diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java index 19ee00036b612..029758eb6e5b6 100644 --- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java +++ b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java @@ -21,12 +21,13 @@ import android.net.netlink.NetlinkMessage; import android.net.netlink.RtNetlinkNeighborMessage; import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlMsgHdr; +import android.test.suitebuilder.annotation.SmallTest; import android.system.OsConstants; import android.util.Log; import libcore.util.HexEncoding; -import java.net.InetAddress; import java.net.Inet4Address; +import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -135,6 +136,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { public static final byte[] RTM_GETNEIGH_RESPONSE = HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false); + @SmallTest public void testParseRtmDelNeigh() { final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. @@ -161,6 +163,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination); } + @SmallTest public void testParseRtmNewNeigh() { final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. @@ -187,6 +190,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination); } + @SmallTest public void testParseRtmGetNeighResponse() { final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. @@ -211,6 +215,7 @@ public class RtNetlinkNeighborMessageTest extends TestCase { assertEquals(14, messageCount); } + @SmallTest public void testCreateRtmNewNeighMessage() { final int seqNo = 2635; final int ifIndex = 14; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 3e552b41ad94c..d62c30da583d2 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -70,7 +70,6 @@ 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; @@ -196,6 +195,7 @@ 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,6 +220,7 @@ 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. @@ -840,7 +841,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { return cv; } - @LargeTest + @SmallTest public void testLingering() throws Exception { verifyNoNetwork(); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -880,7 +881,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @LargeTest + @SmallTest public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { // Test bringing up unvalidated WiFi mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -915,7 +916,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @LargeTest + @SmallTest public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { // Test bringing up unvalidated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -941,7 +942,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyNoNetwork(); } - @LargeTest + @SmallTest public void testUnlingeringDoesNotValidate() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -969,7 +970,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { NET_CAPABILITY_VALIDATED)); } - @LargeTest + @SmallTest public void testCellularOutscoresWeakWifi() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -995,7 +996,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @LargeTest + @SmallTest 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. @@ -1028,7 +1029,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { waitFor(cv); } - @LargeTest + @SmallTest public void testCellularFallback() throws Exception { // Test bringing up validated cellular. mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1066,7 +1067,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @LargeTest + @SmallTest public void testWiFiFallback() throws Exception { // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); @@ -1193,7 +1194,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @LargeTest + @SmallTest public void testStateChangeNetworkCallbacks() throws Exception { final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); @@ -1576,7 +1577,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { handlerThread.quit(); } - @LargeTest + @SmallTest public void testNetworkFactoryRequests() throws Exception { tryNetworkFactoryRequests(NET_CAPABILITY_MMS); tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); @@ -1596,7 +1597,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. } - @LargeTest + @SmallTest public void testNoMutableNetworkRequests() throws Exception { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); NetworkRequest.Builder builder = new NetworkRequest.Builder(); @@ -1621,7 +1622,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } catch (IllegalArgumentException expected) {} } - @LargeTest + @SmallTest public void testMMSonWiFi() throws Exception { // Test bringing up cellular without MMS NetworkRequest gets reaped mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1656,7 +1657,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_WIFI); } - @LargeTest + @SmallTest public void testMMSonCell() throws Exception { // Test bringing up cellular without MMS mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); @@ -1682,7 +1683,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { verifyActiveNetwork(TRANSPORT_CELLULAR); } - @LargeTest + @SmallTest public void testCaptivePortal() { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() @@ -1731,7 +1732,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); } - @LargeTest + @SmallTest public void testAvoidOrIgnoreCaptivePortals() { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() @@ -1802,7 +1803,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { execptionCalled); } - @LargeTest + @SmallTest public void testRegisterDefaultNetworkCallback() throws Exception { final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultNetworkCallback); @@ -1863,7 +1864,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } - @LargeTest + @SmallTest public void testRequestCallbackUpdates() throws Exception { // File a network request for mobile. final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback(); @@ -2504,6 +2505,7 @@ 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"); diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index bce5787ed9a5f..77956be66c9e8 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -24,6 +24,7 @@ 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; @@ -70,6 +71,7 @@ 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); @@ -79,6 +81,7 @@ public class LingerMonitorTest extends TestCase { assertFalse(mMonitor.isNotificationEnabled(nai2, nai1)); } + @SmallTest public void testNotificationOnLinger() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -89,6 +92,7 @@ public class LingerMonitorTest extends TestCase { verifyNotification(from, to); } + @SmallTest public void testToastOnLinger() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); @@ -99,6 +103,7 @@ public class LingerMonitorTest extends TestCase { verifyToast(from, to); } + @SmallTest public void testNotificationClearedAfterDisconnect() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -112,6 +117,7 @@ public class LingerMonitorTest extends TestCase { verify(mNotifier, times(1)).clearNotification(100); } + @SmallTest public void testNotificationClearedAfterSwitchingBack() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -125,6 +131,7 @@ public class LingerMonitorTest extends TestCase { verify(mNotifier, times(1)).clearNotification(100); } + @SmallTest public void testUniqueToast() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); @@ -142,6 +149,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testMultipleNotifications() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -160,6 +168,7 @@ 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); @@ -185,6 +194,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testDailyLimiting() throws InterruptedException { mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT); @@ -211,6 +221,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testUniqueNotification() { setNotificationSwitch(transition(WIFI, CELLULAR)); setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); @@ -227,6 +238,7 @@ public class LingerMonitorTest extends TestCase { verifyNotification(from, to); } + @SmallTest public void testIgnoreNeverValidatedNetworks() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -238,6 +250,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testIgnoreCurrentlyValidatedNetworks() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -249,6 +262,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testNoNotificationType() { setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); setNotificationSwitch(); @@ -259,6 +273,7 @@ public class LingerMonitorTest extends TestCase { verifyNoNotifications(); } + @SmallTest public void testNoTransitionToNotify() { setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE); setNotificationSwitch(transition(WIFI, CELLULAR)); @@ -269,6 +284,7 @@ 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/MetricsLoggerServiceTest.java b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java index 5f84ea1bfd96b..5981f48e7ccd1 100644 --- a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java @@ -20,6 +20,7 @@ import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.os.Bundle; import android.os.RemoteException; +import android.test.suitebuilder.annotation.SmallTest; import static android.net.ConnectivityMetricsEvent.Reference; import junit.framework.TestCase; @@ -67,12 +68,14 @@ public class MetricsLoggerServiceTest extends TestCase { mService.onStart(); } + @SmallTest public void testGetNoEvents() throws Exception { Reference r = new Reference(0); assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); assertEquals(0, r.getValue()); } + @SmallTest public void testLogAndGetEvents() throws Exception { mService.mBinder.logEvents(EVENTS); @@ -85,6 +88,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r.getValue()); } + @SmallTest public void testLogOneByOne() throws Exception { for (ConnectivityMetricsEvent ev : EVENTS) { mService.mBinder.logEvent(ev); @@ -99,6 +103,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r.getValue()); } + @SmallTest public void testInterleavedLogAndGet() throws Exception { mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 0, 3)); @@ -117,6 +122,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r.getValue()); } + @SmallTest public void testMultipleGetAll() throws Exception { mService.mBinder.logEvents(Arrays.copyOf(EVENTS, 3)); @@ -131,6 +137,7 @@ public class MetricsLoggerServiceTest extends TestCase { assertEquals(N_EVENTS, r2.getValue()); } + @SmallTest public void testLogAndDumpConcurrently() throws Exception { for (int i = 0; i < 50; i++) { mContext = null; diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index af4a374bffddf..2bb62bbdcf595 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -23,6 +23,7 @@ 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; @@ -83,6 +84,7 @@ 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 @@ -97,6 +99,7 @@ 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); @@ -110,6 +113,7 @@ 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); @@ -126,6 +130,7 @@ 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")); @@ -147,6 +152,7 @@ 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);