summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-04-26 16:25:36 -0700
committerJeff Sharkey <jsharkey@android.com>2011-05-04 16:07:21 -0700
commit9a13f36cddaad01350bdb5f000167811a1d753c9 (patch)
tree024269b4f6c6ab8fb284156955ecace0578eaba2 /services
parent588f280fe099dc5b18f15124ffb035fc1f5ef2f1 (diff)
downloadframeworks_base-9a13f36cddaad01350bdb5f000167811a1d753c9.zip
frameworks_base-9a13f36cddaad01350bdb5f000167811a1d753c9.tar.gz
frameworks_base-9a13f36cddaad01350bdb5f000167811a1d753c9.tar.bz2
Return NetworkStats bundle from NM service.
Introduce NetworkStats which is a collection of network statistics, which should match the structure communicated by kernel module through netd. Will introduce tags and fg/bg stats later. Kept entirely in a flat data structure to optimize parcel speed. Initial pass at returning NetworkStats from NetworkManagementService, both summary and details. Will eventually pull data from kernel module over netd connection. Change-Id: I92d9f61678ec8c22e2ce26775fb035a0cf32413f
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/NetworkManagementService.java74
-rw-r--r--services/java/com/android/server/ThrottleService.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java28
3 files changed, 106 insertions, 10 deletions
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 44f5df2..d931350 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.pm.PackageManager;
+import android.net.NetworkStats;
import android.net.Uri;
import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
@@ -32,6 +33,8 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.os.INetworkManagementService;
import android.os.Handler;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
@@ -44,13 +47,21 @@ import android.content.ContentResolver;
import android.database.ContentObserver;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.RandomAccessFile;
+import java.io.Reader;
import java.lang.IllegalStateException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
+import libcore.io.IoUtils;
+
/**
* @hide
*/
@@ -716,12 +727,47 @@ class NetworkManagementService extends INetworkManagementService.Stub {
return -1;
}
- public long getInterfaceRxCounter(String iface) {
- return getInterfaceCounter(iface, true);
+ /** {@inheritDoc} */
+ public NetworkStats getNetworkStatsSummary() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+
+ final String[] ifaces = listInterfaces();
+ final NetworkStats.Builder stats = new NetworkStats.Builder(
+ SystemClock.elapsedRealtime(), ifaces.length);
+
+ for (String iface : ifaces) {
+ final long rx = getInterfaceCounter(iface, true);
+ final long tx = getInterfaceCounter(iface, false);
+ stats.addEntry(iface, NetworkStats.UID_ALL, rx, tx);
+ }
+
+ return stats.build();
}
- public long getInterfaceTxCounter(String iface) {
- return getInterfaceCounter(iface, false);
+ /** {@inheritDoc} */
+ public NetworkStats getNetworkStatsDetail() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+
+ final File procPath = new File("/proc/uid_stat");
+ final String[] knownUids = procPath.list();
+ final NetworkStats.Builder stats = new NetworkStats.Builder(
+ SystemClock.elapsedRealtime(), knownUids.length);
+
+ // TODO: kernel module will provide interface-level stats in future
+ // TODO: migrate these stats to come across netd in bulk, instead of all
+ // these individual file reads.
+ for (String uid : knownUids) {
+ final File uidPath = new File(procPath, uid);
+ final int rx = readSingleIntFromFile(new File(uidPath, "tcp_rcv"));
+ final int tx = readSingleIntFromFile(new File(uidPath, "tcp_snd"));
+
+ final int uidInt = Integer.parseInt(uid);
+ stats.addEntry(NetworkStats.IFACE_ALL, uidInt, rx, tx);
+ }
+
+ return stats.build();
}
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
@@ -782,4 +828,24 @@ class NetworkManagementService extends INetworkManagementService.Stub {
public int getInterfaceTxThrottle(String iface) {
return getInterfaceThrottle(iface, false);
}
+
+ /**
+ * Utility method to read a single plain-text {@link Integer} from the given
+ * {@link File}, usually from a {@code /proc/} filesystem.
+ */
+ private static int readSingleIntFromFile(File file) {
+ RandomAccessFile f = null;
+ try {
+ f = new RandomAccessFile(file, "r");
+ byte[] buffer = new byte[(int) f.length()];
+ f.readFully(buffer);
+ return Integer.parseInt(new String(buffer).trim());
+ } catch (NumberFormatException e) {
+ return -1;
+ } catch (IOException e) {
+ return -1;
+ } finally {
+ IoUtils.closeQuietly(f);
+ }
+ }
}
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 02332b7..510ff62 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -33,6 +33,7 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.INetworkManagementEventObserver;
import android.net.IThrottleManager;
+import android.net.NetworkStats;
import android.net.ThrottleManager;
import android.os.Binder;
import android.os.Environment;
@@ -531,8 +532,17 @@ public class ThrottleService extends IThrottleManager.Stub {
long incRead = 0;
long incWrite = 0;
try {
- incRead = mNMService.getInterfaceRxCounter(mIface) - mLastRead;
- incWrite = mNMService.getInterfaceTxCounter(mIface) - mLastWrite;
+ final NetworkStats stats = mNMService.getNetworkStatsSummary();
+ final int index = stats.findIndex(mIface, NetworkStats.UID_ALL);
+
+ if (index != -1) {
+ incRead = stats.rx[index] - mLastRead;
+ incWrite = stats.tx[index] - mLastWrite;
+ } else {
+ // missing iface, assume stats are 0
+ Slog.w(TAG, "unable to find stats for iface " + mIface);
+ }
+
// handle iface resets - on some device the 3g iface comes and goes and gets
// totals reset to 0. Deal with it
if ((incRead < 0) || (incWrite < 0)) {
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index 6f55f46..f20d5e5 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -34,11 +34,17 @@ import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.INetworkManagementEventObserver;
+import android.net.NetworkStats;
import android.net.ThrottleManager;
+import android.os.IBinder;
import android.os.INetworkManagementService;
+import android.os.ServiceManager;
+import android.os.SystemClock;
import android.provider.Settings;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
import android.text.format.DateUtils;
+import android.util.Log;
import android.util.TrustedTime;
import java.util.Iterator;
@@ -222,6 +228,16 @@ public class ThrottleServiceTest extends AndroidTestCase {
verify(mMockTime, mMockNMService);
}
+ @Suppress
+ public void testReturnStats() throws Exception {
+ final IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ final INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
+
+ // test is currently no-op, just exercises stats apis
+ Log.d(TAG, nmService.getNetworkStatsSummary().toString());
+ Log.d(TAG, nmService.getNetworkStatsDetail().toString());
+ }
+
/**
* Persist the given {@link ThrottleService} policy into {@link Settings}.
*/
@@ -272,12 +288,16 @@ public class ThrottleServiceTest extends AndroidTestCase {
}
/**
- * Expect {@link NetworkManagementService#getInterfaceRxCounter} mock calls,
- * responding with the given counter values.
+ * Expect {@link NetworkManagementService#getNetworkStatsSummary()} mock
+ * calls, responding with the given counter values.
*/
public void expectGetInterfaceCounter(long rx, long tx) throws Exception {
- expect(mMockNMService.getInterfaceRxCounter(isA(String.class))).andReturn(rx).atLeastOnce();
- expect(mMockNMService.getInterfaceTxCounter(isA(String.class))).andReturn(tx).atLeastOnce();
+ // TODO: provide elapsedRealtime mock to match TimeAuthority
+ final NetworkStats.Builder stats = new NetworkStats.Builder(
+ SystemClock.elapsedRealtime(), 1);
+ stats.addEntry(TEST_IFACE, NetworkStats.UID_ALL, rx, tx);
+
+ expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats.build()).atLeastOnce();
}
/**