diff options
| author | 2011-09-18 13:30:23 -0700 | |
|---|---|---|
| committer | 2011-09-18 16:17:51 -0700 | |
| commit | 1f0b13b9d64085dd8342ba942f39b6063b6d534d (patch) | |
| tree | 7b0781aeeb1534d44c9a58643126cbe207700529 | |
| parent | cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85f (diff) | |
DO NOT MERGE: Sample atomic network stats buckets, full poll.
When sampling network stats, always use atomic buckets instead of
interpolating. Always poll iface and UID together so we distribute
into buckets equally. Move stale bucket trimming to just before
writing stats.
Bug: 5321340
Change-Id: I78a2226778a79c875f3668336e39ea24a7b4d5c4
5 files changed, 89 insertions, 106 deletions
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index d8ac31f277a0..a5cdf70325ee 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -441,10 +441,10 @@ public class NetworkStatsHistory implements Parcelable { final long curStart = bucketStart[i]; final long curEnd = curStart + bucketDuration; - // bucket is older than record; we're finished - if (curEnd < start) break; - // bucket is newer than record; keep looking - if (curStart > end) continue; + // bucket is older than request; we're finished + if (curEnd <= start) break; + // bucket is newer than request; keep looking + if (curStart >= end) continue; // include full value for active buckets, otherwise only fractional final boolean activeBucket = curStart < now && curEnd > now; @@ -466,7 +466,6 @@ public class NetworkStatsHistory implements Parcelable { if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration; if (operations != null) entry.operations += operations[i] * overlap / bucketDuration; } - return entry; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e5882fc26445..bc5994e371de 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4031,8 +4031,6 @@ public final class Settings { public static final String NETSTATS_UID_MAX_HISTORY = "netstats_uid_max_history"; /** {@hide} */ public static final String NETSTATS_TAG_MAX_HISTORY = "netstats_tag_max_history"; - /** {@hide} */ - public static final String NETSTATS_FORCE_COMPLETE_POLL = "netstats_force_complete_poll"; /** Preferred NTP server. {@hide} */ public static final String NTP_SERVER = "ntp_server"; diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags index f0b5958abc3e..99f6b8ef3eb5 100644 --- a/services/java/com/android/server/EventLogTags.logtags +++ b/services/java/com/android/server/EventLogTags.logtags @@ -142,5 +142,5 @@ option java_package com.android.server # --------------------------- # NetworkStatsService.java # --------------------------- -51100 netstats_mobile_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2) -51101 netstats_wifi_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2) +51100 netstats_mobile_sample (iface_rx_bytes|2|2),(iface_tx_bytes|2|2),(iface_rx_pkts|2|1),(iface_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1) +51101 netstats_wifi_sample (iface_rx_bytes|2|2),(iface_tx_bytes|2|2),(iface_rx_pkts|2|1),(iface_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1) diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index bb5f015de6cb..947cf9c2d8bf 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -36,7 +36,6 @@ import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateWifi; import static android.net.TrafficStats.UID_REMOVED; import static android.net.TrafficStats.UID_TETHERING; -import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL; import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD; @@ -136,15 +135,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 0x1; /** Flags to control detail level of poll event. */ - private static final int FLAG_POLL_NETWORK = 0x1; - private static final int FLAG_POLL_UID = 0x2; - private static final int FLAG_POLL_TETHER = 0x3; private static final int FLAG_PERSIST_NETWORK = 0x10; private static final int FLAG_PERSIST_UID = 0x20; - private static final int FLAG_FORCE_PERSIST = 0x100; - - private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID | FLAG_POLL_TETHER; private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; + private static final int FLAG_PERSIST_FORCE = 0x100; private final Context mContext; private final INetworkManagementService mNetworkManager; @@ -182,7 +176,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public long getUidMaxHistory(); public long getTagMaxHistory(); public long getTimeCacheMaxAge(); - public boolean getForceCompletePoll(); } private final Object mStatsLock = new Object(); @@ -529,7 +522,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); - performPoll(FLAG_POLL_ALL | FLAG_PERSIST_ALL); + performPoll(FLAG_PERSIST_ALL); } /** @@ -561,7 +554,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void onReceive(Context context, Intent intent) { // on background handler thread, and verified CONNECTIVITY_INTERNAL // permission above. - performPoll(FLAG_POLL_TETHER); + performPoll(FLAG_PERSIST_NETWORK); } }; @@ -570,7 +563,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void onReceive(Context context, Intent intent) { // on background handler thread, and verified UPDATE_DEVICE_STATS // permission above. - performPoll(FLAG_POLL_ALL | FLAG_PERSIST_ALL); + performPoll(FLAG_PERSIST_ALL); // verify that we're watching global alert registerGlobalAlert(); @@ -617,7 +610,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (LIMIT_GLOBAL_ALERT.equals(limitName)) { // kick off background poll to collect network stats; UID stats // are handled during normal polling interval. - final int flags = FLAG_POLL_NETWORK | FLAG_PERSIST_NETWORK; + final int flags = FLAG_PERSIST_NETWORK; mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget(); // re-arm global alert for next update @@ -639,10 +632,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // isn't perfect, since the kernel may already be counting traffic from // the updated network. - // poll both network and UID stats, but only persist network stats, - // since this codepath should stay fast. UID stats will be persisted - // during next alarm poll event. - performPollLocked(FLAG_POLL_ALL | FLAG_PERSIST_NETWORK); + // poll, but only persist network stats to keep codepath fast. UID stats + // will be persisted during next alarm poll event. + performPollLocked(FLAG_PERSIST_NETWORK); final NetworkState[] states; try { @@ -706,21 +698,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); final long startRealtime = SystemClock.elapsedRealtime(); - boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0; - boolean pollUid = (flags & FLAG_POLL_UID) != 0; - boolean pollTether = (flags & FLAG_POLL_TETHER) != 0; - - // when complete poll requested, any partial poll enables everything - final boolean forceCompletePoll = mSettings.getForceCompletePoll(); - if (forceCompletePoll && (pollNetwork || pollUid || pollTether)) { - pollNetwork = true; - pollUid = true; - pollTether = true; - } - final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; - final boolean forcePersist = (flags & FLAG_FORCE_PERSIST) != 0; + final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; // try refreshing time source when stale if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) { @@ -733,41 +713,36 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final long threshold = mSettings.getPersistThreshold(); try { - if (pollNetwork) { - final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary(); - performNetworkPollLocked(networkSnapshot, currentTime); - - // persist when enough network data has occurred - final NetworkStats persistNetworkDelta = computeStatsDelta( - mLastPersistNetworkSnapshot, networkSnapshot, true); - final boolean pastThreshold = persistNetworkDelta.getTotalBytes() > threshold; - if (forcePersist || (persistNetwork && pastThreshold)) { - writeNetworkStatsLocked(); - mLastPersistNetworkSnapshot = networkSnapshot; - } + // record network stats + final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary(); + performNetworkPollLocked(networkSnapshot, currentTime); + + // persist when enough network data has occurred + final NetworkStats persistNetworkDelta = computeStatsDelta( + mLastPersistNetworkSnapshot, networkSnapshot, true); + final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold; + if (persistForce || (persistNetwork && networkPastThreshold)) { + writeNetworkStatsLocked(); + mLastPersistNetworkSnapshot = networkSnapshot; } - if (pollTether) { - final String[] ifacePairs = mConnManager.getTetheredIfacePairs(); - final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( - ifacePairs); - performTetherPollLocked(tetherSnapshot, currentTime); - - // persisted during normal UID cycle below - } - - if (pollUid) { - final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); - performUidPollLocked(uidSnapshot, currentTime); - - // persist when enough network data has occurred - final NetworkStats persistUidDelta = computeStatsDelta( - mLastPersistUidSnapshot, uidSnapshot, true); - final boolean pastThreshold = persistUidDelta.getTotalBytes() > threshold; - if (forcePersist || (persistUid && pastThreshold)) { - writeUidStatsLocked(); - mLastPersistUidSnapshot = uidSnapshot; - } + // record tethering stats; persisted during normal UID cycle below + final String[] ifacePairs = mConnManager.getTetheredIfacePairs(); + final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( + ifacePairs); + performTetherPollLocked(tetherSnapshot, currentTime); + + // record uid stats + final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); + performUidPollLocked(uidSnapshot, currentTime); + + // persist when enough network data has occurred + final NetworkStats persistUidDelta = computeStatsDelta( + mLastPersistUidSnapshot, uidSnapshot, true); + final boolean uidPastThreshold = persistUidDelta.getTotalBytes() > threshold; + if (persistForce || (persistUid && uidPastThreshold)) { + writeUidStatsLocked(); + mLastPersistUidSnapshot = uidSnapshot; } } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); @@ -781,9 +756,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // sample stats after each full poll - if (pollNetwork && pollUid) { - performSample(); - } + performSample(); // finally, dispatch updated event to any listeners final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); @@ -813,12 +786,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { history.recordData(timeStart, currentTime, entry); } - // trim any history beyond max - final long maxHistory = mSettings.getNetworkMaxHistory(); - for (NetworkStatsHistory history : mNetworkStats.values()) { - history.removeBucketsBefore(currentTime - maxHistory); - } - mLastPollNetworkSnapshot = networkSnapshot; if (LOGD && unknownIface.size() > 0) { @@ -862,20 +829,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { history.recordData(timeStart, currentTime, entry); } - // trim any history beyond max - final long maxUidHistory = mSettings.getUidMaxHistory(); - final long maxTagHistory = mSettings.getTagMaxHistory(); - for (UidStatsKey key : mUidStats.keySet()) { - final NetworkStatsHistory history = mUidStats.get(key); - - // detailed tags are trimmed sooner than summary in TAG_NONE - if (key.tag == TAG_NONE) { - history.removeBucketsBefore(currentTime - maxUidHistory); - } else { - history.removeBucketsBefore(currentTime - maxTagHistory); - } - } - mLastPollUidSnapshot = uidSnapshot; mLastPollOperationsSnapshot = mOperations; mOperations = new NetworkStats(0L, 10); @@ -917,9 +870,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Sample recent statistics summary into {@link EventLog}. */ private void performSample() { - // take sample as total over last 4 hours - final long end = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); - final long start = end - (4 * HOUR_IN_MILLIS); + final long largestBucketSize = Math.max( + mSettings.getNetworkBucketDuration(), mSettings.getUidBucketDuration()); + + // take sample as atomic buckets + final long now = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); + final long end = now - (now % largestBucketSize) + largestBucketSize; + final long start = end - largestBucketSize; NetworkTemplate template = null; NetworkStats.Entry ifaceTotal = null; @@ -929,15 +886,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { template = buildTemplateMobileAll(getActiveSubscriberId(mContext)); ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal); uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal); - EventLogTags.writeNetstatsMobileSample( - ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes); + EventLogTags.writeNetstatsMobileSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets, + ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, + uidTotal.txBytes, uidTotal.rxPackets); // collect wifi sample template = buildTemplateWifi(); ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal); uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal); - EventLogTags.writeNetstatsWifiSample( - ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes); + EventLogTags.writeNetstatsWifiSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets, + ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, + uidTotal.txBytes, uidTotal.rxPackets); } /** @@ -1137,6 +1096,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // TODO: consider duplicating stats and releasing lock while writing + // trim any history beyond max + if (mTime.hasCache()) { + final long currentTime = mTime.currentTimeMillis(); + final long maxHistory = mSettings.getNetworkMaxHistory(); + for (NetworkStatsHistory history : mNetworkStats.values()) { + history.removeBucketsBefore(currentTime - maxHistory); + } + } + FileOutputStream fos = null; try { fos = mNetworkFile.startWrite(); @@ -1172,6 +1140,23 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // TODO: consider duplicating stats and releasing lock while writing + // trim any history beyond max + if (mTime.hasCache()) { + final long currentTime = mTime.currentTimeMillis(); + final long maxUidHistory = mSettings.getUidMaxHistory(); + final long maxTagHistory = mSettings.getTagMaxHistory(); + for (UidStatsKey key : mUidStats.keySet()) { + final NetworkStatsHistory history = mUidStats.get(key); + + // detailed tags are trimmed sooner than summary in TAG_NONE + if (key.tag == TAG_NONE) { + history.removeBucketsBefore(currentTime - maxUidHistory); + } else { + history.removeBucketsBefore(currentTime - maxTagHistory); + } + } + } + // build UidStatsKey lists grouped by ident final HashMap<NetworkIdentitySet, ArrayList<UidStatsKey>> keysByIdent = Maps.newHashMap(); for (UidStatsKey key : mUidStats.keySet()) { @@ -1236,7 +1221,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } if (argSet.contains("poll")) { - performPollLocked(FLAG_POLL_ALL | FLAG_PERSIST_ALL | FLAG_FORCE_PERSIST); + performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE); pw.println("Forced poll"); return; } @@ -1464,8 +1449,5 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public long getTimeCacheMaxAge() { return DAY_IN_MILLIS; } - public boolean getForceCompletePoll() { - return getSecureBoolean(NETSTATS_FORCE_COMPLETE_POLL, false); - } } } diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index 2b1eea138aea..99ae027f4b16 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -272,7 +272,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // graceful shutdown system, which should trigger persist of stats, and // clear any values in memory. + expectCurrentTime(); + expectDefaultSettings(); + replay(); mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN)); + verifyAndReset(); // talk with zombie service to assert stats have gone; and assert that // we persisted them to file. @@ -487,6 +491,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // now pretend two UIDs are uninstalled, which should migrate stats to // special "removed" bucket. + expectCurrentTime(); expectDefaultSettings(); replay(); final Intent intent = new Intent(ACTION_UID_REMOVED); @@ -758,7 +763,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mSettings.getUidMaxHistory()).andReturn(maxHistory).anyTimes(); expect(mSettings.getTagMaxHistory()).andReturn(maxHistory).anyTimes(); expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes(); - expect(mSettings.getForceCompletePoll()).andReturn(false).anyTimes(); } private void expectCurrentTime() throws Exception { |