diff --git a/Android.mk b/Android.mk
index c0bb7240c796b..da26622c62eca 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,6 +45,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/admin/SecurityLogTags.logtags \
core/java/android/content/EventLogTags.logtags \
core/java/android/speech/tts/EventLogTags.logtags \
+ core/java/android/net/EventLogTags.logtags \
core/java/android/webkit/EventLogTags.logtags \
core/java/com/android/internal/logging/EventLogTags.logtags \
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/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..3670b914ecf37 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;
@@ -232,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;
@@ -278,6 +311,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:
@@ -491,6 +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);
+ bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered);
bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
bucketOut.mBeginTimeStamp = mStartTimeStamp;
bucketOut.mEndTimeStamp = mEndTimeStamp;
@@ -539,6 +588,7 @@ public final class NetworkStats implements AutoCloseable {
bucketOut.mUid = Bucket.convertUid(getUid());
bucketOut.mTag = Bucket.convertTag(mTag);
bucketOut.mState = Bucket.STATE_ALL;
+ bucketOut.mMetered = Bucket.METERED_ALL;
bucketOut.mRoaming = Bucket.ROAMING_ALL;
bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
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/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 43c8c81da2668..51431ebfaf146 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) {
@@ -2657,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 */
@@ -2687,24 +2691,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);
}
@@ -2747,9 +2744,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;
@@ -2757,9 +2752,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;
@@ -2779,24 +2772,16 @@ public class ConnectivityManager {
break;
}
case CALLBACK_RELEASED: {
- NetworkCallback callback = null;
- synchronized(mCallbackMap) {
- callback = mCallbackMap.remove(request);
+ final NetworkCallback callback;
+ synchronized(sCallbacks) {
+ callback = sCallbacks.remove(request);
}
- if (callback != null) {
- synchronized(mRefCount) {
- if (mRefCount.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: {
@@ -2806,14 +2791,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");
@@ -2822,63 +2807,56 @@ 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(),
- sNetworkCallback, sCallbackRefCount, this);
+ private CallbackHandler getHandler() {
+ synchronized (sCallbacks) {
+ if (sCallbackHandler == null) {
+ sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper());
}
+ return sCallbackHandler;
}
}
- private void decCallbackHandlerRefCount() {
- synchronized(sCallbackRefCount) {
- if (sCallbackRefCount.decrementAndGet() == 0) {
- sCallbackHandler.obtainMessage(CALLBACK_EXIT).sendToTarget();
- sCallbackHandler = null;
- }
- }
- }
-
- static final HashMap sNetworkCallback =
- new HashMap();
- static final AtomicInteger sCallbackRefCount = new AtomicInteger(0);
- static CallbackHandler sCallbackHandler = null;
+ static final HashMap sCallbacks = new HashMap<>();
+ 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 callback.networkRequest is not null.
+ // http://b/20701525
+ final NetworkRequest request;
try {
- incCallbackHandlerRefCount();
- synchronized(sNetworkCallback) {
+ synchronized(sCallbacks) {
+ Messenger messenger = new Messenger(handler);
+ 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, callback);
}
+ callback.networkRequest = request;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- if (networkCallback.networkRequest == null) decCallbackHandlerRefCount();
- return networkCallback.networkRequest;
+ return request;
}
/**
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();
}
}
diff --git a/core/java/android/net/EventLogTags.logtags b/core/java/android/net/EventLogTags.logtags
new file mode 100644
index 0000000000000..d5ed01496eba6
--- /dev/null
+++ b/core/java/android/net/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.net
+
+50080 ntp_success (server|3),(rtt|2),(offset|2)
+50081 ntp_failure (server|3),(msg|3)
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 25806fa776740..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.
*/
@@ -904,7 +957,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 +973,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 +995,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 +1013,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 {
@@ -994,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) {
@@ -1013,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/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index cf9243f7e7a31..cea56b53d7637 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -36,8 +36,7 @@ import java.util.Arrays;
* }
*
*/
-public class SntpClient
-{
+public class SntpClient {
private static final String TAG = "SntpClient";
private static final boolean DBG = true;
@@ -88,6 +87,7 @@ public class SntpClient
try {
address = InetAddress.getByName(host);
} catch (Exception e) {
+ EventLogTags.writeNtpFailure(host, e.toString());
if (DBG) Log.d(TAG, "request time failed: " + e);
return false;
}
@@ -142,6 +142,7 @@ public class SntpClient
// = (transit + skew - transit + skew)/2
// = (2 * skew)/2 = skew
long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2;
+ EventLogTags.writeNtpSuccess(address.toString(), roundTripTime, clockOffset);
if (DBG) {
Log.d(TAG, "round trip: " + roundTripTime + "ms, " +
"clock offset: " + clockOffset + "ms");
@@ -153,6 +154,7 @@ public class SntpClient
mNtpTimeReference = responseTicks;
mRoundTripTime = roundTripTime;
} catch (Exception e) {
+ EventLogTags.writeNtpFailure(address.toString(), e.toString());
if (DBG) Log.d(TAG, "request time failed: " + e);
return false;
} finally {
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/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}.
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/res/res/values/config.xml b/core/res/res/values/config.xml
index 22255b493ab2f..25021b8deeed8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1681,7 +1681,7 @@
true
- 2.android.pool.ntp.org
+ time.android.com
86400000
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 9074f8a97132e..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,105 +465,175 @@ 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(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,
+ 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, 13829L, 60L, 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, 1719L, 12L, 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, 41872L, 219L, 0L);
- assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
- 9297L, 17L, 3936, 19L, 0L);
- assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO,
- 21691L, 41L, 13179L, 46L, 0L);
- assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO,
- 1281L, 2L, 634L, 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, 11690, 49, 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);
- assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL,
- 126552, 270, 59215, 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);
}
+ // 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, 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, 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, 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, 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, METERED_NO, ROAMING_NO,
+ 50000L, 25L, 100000L, 50L, 0L);
+ 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, METERED_NO, ROAMING_NO,
+ 240000L, 100L, 120000L, 60L, 0L);
+
+ // Existing underlying Iface entries are updated
+ assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
+ ROAMING_NO, 51000L, 35L, 102000L, 70L, 0L);
+
+ // VPN underlying Iface entries are updated
+ 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, 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, 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/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/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index c73d1dd954375..ea2cf5fb4a7ef 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
@@ -678,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();
@@ -732,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) {
@@ -800,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);
@@ -820,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.
@@ -973,6 +1009,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 +1033,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));
}
}
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/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/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index a8356dc4658e7..83001df580233 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -194,8 +194,10 @@ public class ApfFilter {
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
- private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
+ 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;
// NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2;
@@ -805,6 +807,8 @@ public class ApfFilter {
// if it's multicast and we're dropping multicast:
// drop
// pass
+ // if it's ICMPv6 RS to any:
+ // drop
// if it's ICMPv6 NA to ff02::1:
// drop
@@ -829,10 +833,12 @@ public class ApfFilter {
// Add unsolicited multicast neighbor announcements filter
String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
- // If not neighbor announcements, skip unsolicited multicast NA filter
gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET);
+ // Drop all router solicitations (b/32833400)
+ gen.addJumpIfR0Equals(ICMP6_ROUTER_SOLICITATION, gen.DROP_LABEL);
+ // If not neighbor announcements, skip filter.
gen.addJumpIfR0NotEquals(ICMP6_NEIGHBOR_ANNOUNCEMENT, skipUnsolicitedMulticastNALabel);
- // If to ff02::1, drop
+ // If to ff02::1, drop.
// TODO: Drop only if they don't contain the address of on-link neighbours.
gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET);
gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS,
@@ -852,6 +858,7 @@ public class ApfFilter {
* - Pass all non-ICMPv6 IPv6 packets,
*
- Pass all non-IPv4 and non-IPv6 packets,
*
- Drop IPv6 ICMPv6 NAs to ff02::1.
+ *
- Drop IPv6 ICMPv6 RSs.
*
- Let execution continue off the end of the program for IPv6 ICMPv6 packets. This allows
* insertion of RA filters here, or if there aren't any, just passes the packets.
*
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 3183930b08ced..2187c571d7baa 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -12,12 +12,12 @@ 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 \
services.net \
services.usage \
- easymocklib \
guava \
android-support-test \
mockito-target \
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 4b69eb3ac35b3..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;
@@ -40,21 +43,21 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
+
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
-import static org.easymock.EasyMock.anyInt;
-import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
+
+import 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.IAlarmListener;
-import android.app.IAlarmManager;
-import android.app.PendingIntent;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.content.Intent;
@@ -63,6 +66,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 +84,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;
@@ -95,8 +98,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;
@@ -106,11 +115,11 @@ 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.
*/
-@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";
@@ -137,10 +146,12 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
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;
@@ -148,32 +159,24 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private INetworkStatsSession mSession;
private INetworkManagementEventObserver mNetworkObserver;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
+ MockitoAnnotations.initMocks(this);
+ 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);
}
- 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");
@@ -190,22 +193,20 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(buildEmptyStats());
expectSystemReady();
- // catch INetworkManagementEventObserver during systemReady()
- final Capture