summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-05-17 14:55:15 -0700
committerJeff Sharkey <jsharkey@android.com>2011-05-21 15:02:58 -0700
commiteedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3 (patch)
tree2753882abd3cd277dce4c30a1d6a59172f2c6f46 /core/java
parent850ae9acda0d062f9a1836d159bdce819e0f8066 (diff)
downloadframeworks_base-eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3.zip
frameworks_base-eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3.tar.gz
frameworks_base-eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3.tar.bz2
APIs to profile network usage for current UID.
Added startDataProfiling() and stopDataProfiling() to TrafficStats, which can be used by apps to measure network usage delta between two points in time. Currently takes two NetworkStats snapshots and returns delta, which will eventually include tag-level granularity. Added tests for NetworkStats delta subtraction. Added NMS.getNetworkStatsUidDetail() that returns stats for specific UID. Always gives stats access for the calling UID, otherwise enforces that caller has permission. Fix readSingleLongFromFile(), since /proc/ files don't have well-defined lengths. Change-Id: Ic5b6414d8effbd66846e275b00d4b8a82c74589d
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/content/Context.java3
-rw-r--r--core/java/android/net/NetworkPolicyManager.java5
-rw-r--r--core/java/android/net/NetworkStats.java54
-rw-r--r--core/java/android/net/TrafficStats.java72
-rw-r--r--core/java/android/os/INetworkManagementService.aidl6
5 files changed, 133 insertions, 7 deletions
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4c7d87f..a660bd7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1544,6 +1544,9 @@ public abstract class Context {
*/
public static final String NETWORKMANAGEMENT_SERVICE = "network_management";
+ /** {@hide} */
+ public static final String NETWORK_POLICY_SERVICE = "netpolicy";
+
/**
* Use with {@link #getSystemService} to retrieve a {@link
* android.net.wifi.WifiManager} for handling management of
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 2312bd9..1913aa7 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -16,6 +16,7 @@
package android.net;
+import android.content.Context;
import android.os.RemoteException;
/**
@@ -43,6 +44,10 @@ public class NetworkPolicyManager {
mService = service;
}
+ public static NetworkPolicyManager getSystemService(Context context) {
+ return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
+ }
+
/**
* Set policy flags for specific UID.
*
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 4430e00..0f207bc 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -36,6 +36,9 @@ public class NetworkStats implements Parcelable {
/** {@link #uid} value when entry is summarized over all UIDs. */
public static final int UID_ALL = 0;
+ // NOTE: data should only be accounted for once in this structure; if data
+ // is broken out, the summarized version should not be included.
+
/**
* {@link SystemClock#elapsedRealtime()} timestamp when this data was
* generated.
@@ -81,12 +84,13 @@ public class NetworkStats implements Parcelable {
mTx = new long[size];
}
- public void addEntry(String iface, int uid, long rx, long tx) {
+ public Builder addEntry(String iface, int uid, long rx, long tx) {
mIface[mIndex] = iface;
mUid[mIndex] = uid;
mRx[mIndex] = rx;
mTx[mIndex] = tx;
mIndex++;
+ return this;
}
public NetworkStats build() {
@@ -97,11 +101,17 @@ public class NetworkStats implements Parcelable {
}
}
+ public int length() {
+ // length is identical for all fields
+ return iface.length;
+ }
+
/**
* Find first stats index that matches the requested parameters.
*/
public int findIndex(String iface, int uid) {
- for (int i = 0; i < this.iface.length; i++) {
+ final int length = length();
+ for (int i = 0; i < length; i++) {
if (equal(iface, this.iface[i]) && uid == this.uid[i]) {
return i;
}
@@ -109,13 +119,38 @@ public class NetworkStats implements Parcelable {
return -1;
}
- private static boolean equal(Object a, Object b) {
- return a == b || (a != null && a.equals(b));
+ /**
+ * Subtract the given {@link NetworkStats}, effectively leaving the delta
+ * between two snapshots in time. Assumes that statistics rows collect over
+ * time, and that none of them have disappeared.
+ */
+ public NetworkStats subtract(NetworkStats value) {
+ // result will have our rows, but no meaningful timestamp
+ final int length = length();
+ final NetworkStats.Builder result = new NetworkStats.Builder(-1, length);
+
+ for (int i = 0; i < length; i++) {
+ final String iface = this.iface[i];
+ final int uid = this.uid[i];
+
+ // find remote row that matches, and subtract
+ final int j = value.findIndex(iface, uid);
+ if (j == -1) {
+ // newly appearing row, return entire value
+ result.addEntry(iface, uid, this.rx[i], this.tx[i]);
+ } else {
+ // existing row, subtract remote value
+ final long rx = this.rx[i] - value.rx[j];
+ final long tx = this.tx[i] - value.tx[j];
+ result.addEntry(iface, uid, rx, tx);
+ }
+ }
+
+ return result.build();
}
- /** {@inheritDoc} */
- public int describeContents() {
- return 0;
+ private static boolean equal(Object a, Object b) {
+ return a == b || (a != null && a.equals(b));
}
public void dump(String prefix, PrintWriter pw) {
@@ -138,6 +173,11 @@ public class NetworkStats implements Parcelable {
}
/** {@inheritDoc} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(elapsedRealtime);
dest.writeStringArray(iface);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 7ee7a81..c0ff734 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,6 +16,12 @@
package android.net;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
import dalvik.system.BlockGuard;
import java.net.Socket;
@@ -36,6 +42,17 @@ public class TrafficStats {
public final static int UNSUPPORTED = -1;
/**
+ * Snapshot of {@link NetworkStats} when the currently active profiling
+ * session started, or {@code null} if no session active.
+ *
+ * @see #startDataProfiling(Context)
+ * @see #stopDataProfiling(Context)
+ */
+ private static NetworkStats sActiveProfilingStart;
+
+ private static Object sProfilingLock = new Object();
+
+ /**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* <p>
@@ -93,6 +110,44 @@ public class TrafficStats {
}
/**
+ * Start profiling data usage for current UID. Only one profiling session
+ * can be active at a time.
+ *
+ * @hide
+ */
+ public static void startDataProfiling(Context context) {
+ synchronized (sProfilingLock) {
+ if (sActiveProfilingStart != null) {
+ throw new IllegalStateException("already profiling data");
+ }
+
+ // take snapshot in time; we calculate delta later
+ sActiveProfilingStart = getNetworkStatsForUid(context);
+ }
+ }
+
+ /**
+ * Stop profiling data usage for current UID.
+ *
+ * @return Detailed {@link NetworkStats} of data that occurred since last
+ * {@link #startDataProfiling(Context)} call.
+ * @hide
+ */
+ public static NetworkStats stopDataProfiling(Context context) {
+ synchronized (sProfilingLock) {
+ if (sActiveProfilingStart == null) {
+ throw new IllegalStateException("not profiling data");
+ }
+
+ // subtract starting values and return delta
+ final NetworkStats profilingStop = getNetworkStatsForUid(context);
+ final NetworkStats profilingDelta = profilingStop.subtract(sActiveProfilingStart);
+ sActiveProfilingStart = null;
+ return profilingDelta;
+ }
+ }
+
+ /**
* Get the total number of packets transmitted through the mobile interface.
*
* @return number of packets. If the statistics are not supported by this device,
@@ -350,4 +405,21 @@ public class TrafficStats {
* {@link #UNSUPPORTED} will be returned.
*/
public static native long getUidUdpRxPackets(int uid);
+
+ /**
+ * Return detailed {@link NetworkStats} for the current UID. Requires no
+ * special permission.
+ */
+ private static NetworkStats getNetworkStatsForUid(Context context) {
+ final IBinder binder = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ final INetworkManagementService service = INetworkManagementService.Stub.asInterface(
+ binder);
+
+ final int uid = android.os.Process.myUid();
+ try {
+ return service.getNetworkStatsUidDetail(uid);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index ecc111b..f17a6f2 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -214,6 +214,12 @@ interface INetworkManagementService
NetworkStats getNetworkStatsDetail();
/**
+ * Return detailed network statistics for the requested UID,
+ * including interface and tag details.
+ */
+ NetworkStats getNetworkStatsUidDetail(int uid);
+
+ /**
* Configures bandwidth throttling on an interface.
*/
void setInterfaceThrottle(String iface, int rxKbps, int txKbps);