diff options
author | Jeff Sharkey <jsharkey@android.com> | 2011-04-26 16:25:36 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2011-05-04 16:07:21 -0700 |
commit | 9a13f36cddaad01350bdb5f000167811a1d753c9 (patch) | |
tree | 024269b4f6c6ab8fb284156955ecace0578eaba2 /services | |
parent | 588f280fe099dc5b18f15124ffb035fc1f5ef2f1 (diff) | |
download | frameworks_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')
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(); } /** |