diff options
author | Jeff Sharkey <jsharkey@android.com> | 2011-07-19 23:47:12 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2011-07-29 22:24:01 -0700 |
commit | a63ba59260cd1bb3f5c16e395ace45a61f1d4461 (patch) | |
tree | f70f8270c45744686c1c6741f39340c0cb644dd3 /services | |
parent | 1e833b31ee04c35b5a3494db1acb0068350d8391 (diff) | |
download | frameworks_base-a63ba59260cd1bb3f5c16e395ace45a61f1d4461.zip frameworks_base-a63ba59260cd1bb3f5c16e395ace45a61f1d4461.tar.gz frameworks_base-a63ba59260cd1bb3f5c16e395ace45a61f1d4461.tar.bz2 |
Add operation counts to network statistics.
Provide API to increment "operation counts" for a UID and tag, used
to eventually derive bytes/operation stats. Internally is stored at
network layer, but should belong at data layer. Switch profiling
to use data layer stats, which are emulated by summarizing network
layer details.
Read packet counts from new /proc/ columns and collect them into
NetworkStatsHistory. Prevent double-counting by ignoring values from
first snapshot. Watch for duplicate /proc/ entries. Update tests
to verify packet and operation counters.
Bug: 5052136, 5097392
Change-Id: I1832f65a2b8a9188f8088f253474a667c21a2f09
Diffstat (limited to 'services')
7 files changed, 245 insertions, 105 deletions
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 39d2b1c..a59b6c0 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -21,6 +21,8 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.provider.Settings.Secure.NETSTATS_ENABLED; +import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; +import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.content.Context; import android.content.pm.PackageManager; @@ -54,7 +56,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.Inet4Address; import java.net.InetAddress; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -89,8 +90,10 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final String KEY_IFACE = "iface"; private static final String KEY_TAG_HEX = "acct_tag_hex"; private static final String KEY_UID = "uid_tag_int"; - private static final String KEY_RX = "rx_bytes"; - private static final String KEY_TX = "tx_bytes"; + private static final String KEY_RX_BYTES = "rx_bytes"; + private static final String KEY_RX_PACKETS = "rx_packets"; + private static final String KEY_TX_BYTES = "tx_bytes"; + private static final String KEY_TX_PACKETS = "tx_packets"; class NetdResponseCode { /* Keep in sync with system/netd/ResponseCode.h */ @@ -203,8 +206,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { Slog.d(TAG, "not enabling bandwidth control"); } - SystemProperties.set(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, - mBandwidthControlEnabled ? "1" : "0"); + SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); } public void registerObserver(INetworkManagementEventObserver obs) { @@ -1249,6 +1251,9 @@ class NetworkManagementService extends INetworkManagementService.Stub { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); final NetworkStats.Entry entry = new NetworkStats.Entry(); + // TODO: remove knownLines check once 5087722 verified + final HashSet<String> knownLines = Sets.newHashSet(); + final ArrayList<String> keys = Lists.newArrayList(); final ArrayList<String> values = Lists.newArrayList(); final HashMap<String, String> parsed = Maps.newHashMap(); @@ -1266,14 +1271,18 @@ class NetworkManagementService extends INetworkManagementService.Stub { splitLine(line, values); parseLine(keys, values, parsed); + if (!knownLines.add(line)) { + throw new IllegalStateException("encountered duplicate proc entry"); + } + try { - // TODO: add rxPackets/txPackets once kernel exports entry.iface = parsed.get(KEY_IFACE); - entry.tag = NetworkManagementSocketTagger.kernelToTag( - parsed.get(KEY_TAG_HEX)); - entry.uid = Integer.parseInt(parsed.get(KEY_UID)); - entry.rxBytes = Long.parseLong(parsed.get(KEY_RX)); - entry.txBytes = Long.parseLong(parsed.get(KEY_TX)); + entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX)); + entry.uid = getParsedInt(parsed, KEY_UID); + entry.rxBytes = getParsedLong(parsed, KEY_RX_BYTES); + entry.rxPackets = getParsedLong(parsed, KEY_RX_PACKETS); + entry.txBytes = getParsedLong(parsed, KEY_TX_BYTES); + entry.txPackets = getParsedLong(parsed, KEY_TX_PACKETS); if (limitUid == UID_ALL || limitUid == entry.uid) { stats.addValues(entry); @@ -1291,6 +1300,16 @@ class NetworkManagementService extends INetworkManagementService.Stub { return stats; } + private static int getParsedInt(HashMap<String, String> parsed, String key) { + final String value = parsed.get(key); + return value != null ? Integer.parseInt(value) : 0; + } + + private static long getParsedLong(HashMap<String, String> parsed, String key) { + final String value = parsed.get(key); + return value != null ? Long.parseLong(value) : 0; + } + /** * Build {@link NetworkStats} with detailed UID statistics. * diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 6cc01f4..24188ca 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; +import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.content.Intent.ACTION_SHUTDOWN; @@ -56,6 +58,7 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; +import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; @@ -65,6 +68,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; import android.telephony.TelephonyManager; +import android.util.Log; import android.util.LongSparseArray; import android.util.NtpTrustedTime; import android.util.Slog; @@ -150,9 +154,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Set of currently active ifaces. */ private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap(); - /** Set of historical stats for known networks. */ + /** Set of historical network layer stats for known networks. */ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap(); - /** Set of historical stats for known UIDs. */ + /** Set of historical network layer stats for known UIDs. */ private HashMap<NetworkIdentitySet, LongSparseArray<NetworkStatsHistory>> mUidStats = Maps.newHashMap(); @@ -164,6 +168,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats mLastUidSnapshot; + /** Data layer operation counters for splicing into other structures. */ + private NetworkStats mOperations = new NetworkStats(0L, 10); + private NetworkStats mLastOperationsSnapshot; + private final HandlerThread mHandlerThread; private final Handler mHandler; @@ -381,9 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { entry.uid = uid; entry.tag = tag; entry.rxBytes = historyEntry.rxBytes; + entry.rxPackets = historyEntry.rxPackets; entry.txBytes = historyEntry.txBytes; + entry.txPackets = historyEntry.txPackets; + entry.operations = historyEntry.operations; - if (entry.rxBytes > 0 || entry.txBytes > 0) { + if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 + || entry.txPackets > 0 || entry.operations > 0) { stats.combineValues(entry); } } @@ -396,6 +408,41 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override + public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { + if (Binder.getCallingUid() != uid) { + mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); + } + + // TODO: switch to data layer stats once kernel exports + // for now, read network layer stats and flatten across all ifaces + final NetworkStats networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid); + final NetworkStats dataLayer = new NetworkStats( + networkLayer.getElapsedRealtime(), networkLayer.size()); + + NetworkStats.Entry entry = null; + for (int i = 0; i < networkLayer.size(); i++) { + entry = networkLayer.getValues(i, entry); + entry.iface = IFACE_ALL; + dataLayer.combineValues(entry); + } + + // splice in operation counts + dataLayer.spliceOperationsFrom(mOperations); + return dataLayer; + } + + @Override + public void incrementOperationCount(int uid, int tag, int operationCount) { + if (Binder.getCallingUid() != uid) { + mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + } + + synchronized (mStatsLock) { + mOperations.combineValues(IFACE_ALL, uid, tag, 0L, 0L, 0L, 0L, operationCount); + } + } + + @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); @@ -533,7 +580,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot; try { networkSnapshot = mNetworkManager.getNetworkStatsSummary(); - uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null; + uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsUidDetail(UID_ALL) : null; } catch (IllegalStateException e) { Slog.w(TAG, "problem reading network stats: " + e); return; @@ -592,7 +639,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident); - history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); + history.recordData(timeStart, currentTime, entry); } // trim any history beyond max @@ -615,9 +662,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ensureUidStatsLoadedLocked(); final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot); + final NetworkStats operationsDelta = computeStatsDelta( + mLastOperationsSnapshot, mOperations); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; + NetworkStats.Entry operationsEntry = null; for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); @@ -625,9 +675,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { continue; } + // splice in operation counts since last poll + final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.tag); + if (j != -1) { + operationsEntry = operationsDelta.getValues(j, operationsEntry); + entry.operations = operationsEntry.operations; + } + final NetworkStatsHistory history = findOrCreateUidStatsLocked( ident, entry.uid, entry.tag); - history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); + history.recordData(timeStart, currentTime, entry); } // trim any history beyond max @@ -648,6 +705,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mLastUidSnapshot = uidSnapshot; + mLastOperationsSnapshot = mOperations; + mOperations = new NetworkStats(0L, 10); } /** @@ -980,7 +1039,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int tag = unpackTag(packed); final NetworkStatsHistory history = uidStats.valueAt(i); pw.print(" UID="); pw.print(uid); - pw.print(" tag="); pw.println(tag); + pw.print(" tag=0x"); pw.println(Integer.toHexString(tag)); history.dump(" ", pw, fullHistory); } } @@ -1028,7 +1087,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (before != null) { return current.subtractClamped(before); } else { - return current; + // this is first snapshot; to prevent from double-counting we only + // observe traffic occuring between known snapshots. + return new NetworkStats(0L, 10); } } @@ -1114,5 +1175,4 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return DAY_IN_MILLIS; } } - } diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 1620405..60be35a 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -26,10 +26,12 @@ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" /> <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" /> + <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" /> <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> - <uses-permission android:name="android.permission.WAKE_LOCK" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java index 56ef995..f628977 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java @@ -50,10 +50,9 @@ public class NetworkManagementServiceTest extends AndroidTestCase { public void setUp() throws Exception { super.setUp(); - final File canonicalFilesDir = getContext().getFilesDir().getCanonicalFile(); - mTestProc = new File(canonicalFilesDir, "proc"); + mTestProc = new File(getContext().getFilesDir(), "proc"); if (mTestProc.exists()) { - Files.deleteRecursively(mTestProc); + IoUtils.deleteContents(mTestProc); } mService = NetworkManagementService.createForTest(mContext, mTestProc, true); @@ -64,7 +63,7 @@ public class NetworkManagementServiceTest extends AndroidTestCase { mService = null; if (mTestProc.exists()) { - Files.deleteRecursively(mTestProc); + IoUtils.deleteContents(mTestProc); } super.tearDown(); diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index aab09ca..91fef22 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -197,9 +197,6 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce(); expectTime(System.currentTimeMillis()); - // default behavior is background data enabled - expect(mConnManager.getBackgroundDataSetting()).andReturn(true); - replay(); mService.systemReady(); verifyAndReset(); @@ -471,7 +468,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { // pretend that 512 bytes total have happened stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L, 11); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) .andReturn(stats).atLeastOnce(); @@ -547,7 +544,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); state = new NetworkState[] { buildWifi() }; { @@ -574,7 +571,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L, 11); { expectTime(currentTime); @@ -595,7 +592,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L, 22); { expectTime(currentTime); diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index bd80af9..cf69fd5 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -160,22 +160,25 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 1L, 2048L, 2L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); + assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); verifyAndReset(); // and bump forward again, with counters going higher. this is @@ -185,13 +188,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 4L, 8192L, 8L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4096L, 8192L); + assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); verifyAndReset(); } @@ -211,26 +214,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 8L, 2048L, 16L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 2) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 128L, 1L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 20); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); - assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L); + assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 512L, 4L, 256L, 2L, 20); + assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 10); verifyAndReset(); // graceful shutdown system, which should trigger persist of stats, and @@ -241,7 +250,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // we persisted them to file. expectDefaultSettings(); replay(); - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); assertStatsFilesExist(true); @@ -254,9 +263,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mService.systemReady(); // after systemReady(), we should have historical stats loaded again - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); - assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L); + assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 512L, 4L, 256L, 2L, 20); + assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 10); verifyAndReset(); } @@ -278,20 +287,23 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += 2 * HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history history = mService.getHistoryForNetwork(sTemplateWifi); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(2, history.size()); verifyAndReset(); @@ -301,14 +313,14 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectTime(TEST_START + elapsedRealtime); expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify identical stats, but spread across 4 buckets now history = mService.getHistoryForNetwork(sTemplateWifi); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(4, history.size()); verifyAndReset(); @@ -328,25 +340,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic on first network elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 3) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 15); + mService.incrementOperationCount(UID_RED, 0xF00D, 10); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateImsi1, 2048L, 512L); - assertNetworkTotal(sTemplateWifi, 0L, 0L); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L); + assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 15); + assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 5); verifyAndReset(); // now switch networks; this also tests that we're okay with interfaces @@ -356,7 +375,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkState(buildMobile3gState(IMSI_2)); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -369,22 +388,24 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L)); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify original history still intact - assertNetworkTotal(sTemplateImsi1, 2048L, 512L); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L); + assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 15); + assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 5); // and verify new history also recorded under different template, which // verifies that we didn't cross the streams. - assertNetworkTotal(sTemplateImsi2, 128L, 1024L); - assertNetworkTotal(sTemplateWifi, 0L, 0L); - assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1024L); + assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); verifyAndReset(); } @@ -402,25 +423,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L) .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 10); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 15); + mService.incrementOperationCount(UID_GREEN, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4128L, 544L); - assertUidTotal(sTemplateWifi, UID_RED, 16L, 16L); - assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 512L); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L); + assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); + assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 15); + assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 5); verifyAndReset(); // now pretend two UIDs are uninstalled, which should migrate stats to @@ -435,11 +463,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // existing uid and total should remain unchanged; but removed UID // should be gone completely. - assertNetworkTotal(sTemplateWifi, 4128L, 544L); - assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L); - assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L); - assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 528L); + assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 5); + assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 25); verifyAndReset(); } @@ -457,20 +485,26 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 10); + mService.incrementOperationCount(UID_RED, 0xF00D, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 1024L); + assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 10); verifyAndReset(); // now switch over to 4g network @@ -479,7 +513,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkState(buildMobile4gState()); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -491,14 +525,16 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify that ALL_MOBILE template combines both - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 1280L); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 15); verifyAndReset(); @@ -537,32 +573,41 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic for two apps elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 5); + mService.incrementOperationCount(UID_RED, 0xF00D, 1); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 50L, 50L); - assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 512L); + assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 5); + assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 10); verifyAndReset(); - + // now create more traffic in next hour, but only for one app elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L)); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 15); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -570,28 +615,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mService.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L); - assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L); - assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L); + assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L, 5); + assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L, 1); + assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L, 15); // now verify that recent history only contains one uid final long currentTime = TEST_START + elapsedRealtime; stats = mService.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L); + assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L, 5); verifyAndReset(); } - private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) { + private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { final NetworkStatsHistory history = mService.getHistoryForNetwork(template); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, + txPackets, operations); } - private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) { + private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, + txPackets, operations); } private void expectSystemReady() throws Exception { @@ -611,8 +660,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mNetManager.getNetworkStatsSummary()).andReturn(summary).atLeastOnce(); } - private void expectNetworkStatsDetail(NetworkStats detail) throws Exception { - expect(mNetManager.getNetworkStatsDetail()).andReturn(detail).atLeastOnce(); + private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { + expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce(); } private void expectDefaultSettings() throws Exception { @@ -639,6 +688,17 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); } + private void performBootstrapPoll(long testStart, long elapsedRealtime) throws Exception { + expectTime(testStart + elapsedRealtime); + expectDefaultSettings(); + expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); + + replay(); + mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); + verifyAndReset(); + } + private void assertStatsFilesExist(boolean exist) { final File networkFile = new File(mStatsDir, "netstats.bin"); final File uidFile = new File(mStatsDir, "netstats_uid.bin"); @@ -652,23 +712,26 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag, - long rxBytes, long rxPackets, long txBytes, long txPackets) { + long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStats.Entry entry = stats.getValues(i, null); - assertEquals(iface, entry.iface); - assertEquals(uid, entry.uid); - assertEquals(tag, entry.tag); - assertEquals(rxBytes, entry.rxBytes); - // TODO: enable testing packet counts once stored in history -// assertEquals(rxPackets, entry.rxPackets); - assertEquals(txBytes, entry.txBytes); -// assertEquals(txPackets, entry.txPackets); + assertEquals("unexpected iface", iface, entry.iface); + assertEquals("unexpected uid", uid, entry.uid); + assertEquals("unexpected tag", tag, entry.tag); + assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); + assertEquals("unexpected txBytes", txBytes, entry.txBytes); + assertEquals("unexpected txPackets", txPackets, entry.txPackets); + assertEquals("unexpected operations", operations, entry.operations); } - private static void assertValues( - NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { + private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes, + long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); assertEquals("unexpected txBytes", txBytes, entry.txBytes); + assertEquals("unexpected txPackets", txPackets, entry.txPackets); + assertEquals("unexpected operations", operations, entry.operations); } private static NetworkState buildWifiState() { diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java index 50c18f0..c0870c7 100644 --- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java @@ -289,7 +289,7 @@ public class ThrottleServiceTest extends AndroidTestCase { public void expectGetInterfaceCounter(long rx, long tx) throws Exception { // TODO: provide elapsedRealtime mock to match TimeAuthority final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); - stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L); + stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L, 0); expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats).atLeastOnce(); } |