diff options
4 files changed, 109 insertions, 0 deletions
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 6436e42..17033c4 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -57,4 +57,5 @@ interface INetworkStatsService { /** Advise persistance threshold; may be overridden internally. */ void advisePersistThreshold(long thresholdBytes); + void resetDataUsageHistoryForAllUid(in NetworkTemplate template); } diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 15b68c7..0176ec4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -491,6 +491,21 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } + /** + * Replace data usage history for each matching identity in the template with empty values + */ + public void resetDataUsage(NetworkTemplate template) { + final ArrayList<Key> knownKeys = Lists.newArrayList(); + knownKeys.addAll(mStats.keySet()); + + for (Key key : knownKeys) { + if (templateMatches(template, key.ident)) { + mStats.put(key, new NetworkStatsHistory(mBucketDuration, 10)); + mDirty = true; + } + } + } + private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) { if (startMillis < mStartMillis) mStartMillis = startMillis; if (endMillis > mEndMillis) mEndMillis = endMillis; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 6490865..3201981 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -290,6 +290,31 @@ public class NetworkStatsRecorder { } /** + * Reset data usage for all matching identities in {@link FileRotator} history, + */ + public void resetDataUsageLocked(NetworkTemplate template) { + try { + // Reset all persisted data to empty values + mRotator.rewriteAll(new ResetDataUsageRewriter(mBucketDuration, template)); + } catch (IOException e) { + Log.wtf(TAG, "problem resetting data stats " + e); + recoverFromWtf(); + } catch (OutOfMemoryError e) { + Log.wtf(TAG, "problem resetting data stats " + e); + recoverFromWtf(); + } + + // Reset any pending stats + mPending.resetDataUsage(template); + mSinceBoot.resetDataUsage(template); + + final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; + if (complete != null) { + complete.resetDataUsage(template); + } + } + + /** * Rewriter that will combine current {@link NetworkStatsCollection} values * with anything read from disk, and write combined set to disk. Clears the * original {@link NetworkStatsCollection} when finished writing. @@ -359,6 +384,42 @@ public class NetworkStatsRecorder { } } + /** + * Rewriter that will remove any {@link NetworkStatsHistory} attributed to + * identities in input template, replacing it with empty values. + */ + public static class ResetDataUsageRewriter implements FileRotator.Rewriter { + private final NetworkStatsCollection mTemp; + private NetworkTemplate mTemplate; + + public ResetDataUsageRewriter(long bucketDuration, NetworkTemplate template) { + mTemp = new NetworkStatsCollection(bucketDuration); + mTemplate = template; + } + + @Override + public void reset() { + mTemp.reset(); + } + + @Override + public void read(InputStream in) throws IOException { + mTemp.read(in); + mTemp.clearDirty(); + mTemp.resetDataUsage(mTemplate); + } + + @Override + public boolean shouldWrite() { + return mTemp.isDirty(); + } + + @Override + public void write(OutputStream out) throws IOException { + mTemp.write(new DataOutputStream(out)); + } + } + public void importLegacyNetworkLocked(File file) throws IOException { // legacy file still exists; start empty to avoid double importing mRotator.deleteAll(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index acd05f7..dce601b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -628,6 +628,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); } + /** + * Reset entire data usage history for all the uids in the template and update global + * data stats + */ + @Override + public void resetDataUsageHistoryForAllUid(NetworkTemplate template) { + mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + + synchronized (mStatsLock) { + mWakeLock.acquire(); + try { + resetDataUsageLocked(template); + } catch (Exception e) { + // ignored; service lives in system_server + } finally { + mWakeLock.release(); + } + } + } + @Override public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); @@ -1148,6 +1168,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { removeUidsLocked(uids); } + /** + * Reset data usage history for all uids, uid tags, and global transfer data for the input template + */ + private void resetDataUsageLocked(NetworkTemplate template) { + // Perform one last poll before removing + performPollLocked(FLAG_PERSIST_ALL); + + mUidRecorder.resetDataUsageLocked(template); + mUidTagRecorder.resetDataUsageLocked(template); + mXtRecorder.resetDataUsageLocked(template); + } + @Override protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); |