Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3bc0853 authored by Kamaljeet Maini's avatar Kamaljeet Maini Committed by Gerrit Code Review
Browse files

Framework changes for resetting data usage statistics

As part of data management experience enhancements in Settings
application, a new feature is added. This feature allows users
to fully reset all data usage stats of currently selected network
interface.

When data stats are reset for a specific network interface, the
total data usage and per app data usage for that interface is
reset to zero. There is no way to revert this reset.

Prior to this feature, users could only change the data stats cycle
to hide older data usage history. Alternatively, users could perform
fully factory reset to remove the usage history. This feature allows
fully clearing data usage stats history without any other changes.

Change-Id: I242331cf85cec00997a8aa34e8bdcbccf0917864
parent 39aa78bb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -57,4 +57,5 @@ interface INetworkStatsService {
    /** Advise persistance threshold; may be overridden internally. */
    void advisePersistThreshold(long thresholdBytes);

    void resetDataUsageHistoryForAllUid(in NetworkTemplate template);
}
+15 −0
Original line number Diff line number Diff line
@@ -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;
+61 −0
Original line number Diff line number Diff line
@@ -289,6 +289,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
@@ -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();
+32 −0
Original line number Diff line number Diff line
@@ -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);