summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java65
1 files changed, 60 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4e848f8f364c..e3ff72b9a9d7 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -286,6 +286,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private long mPersistThreshold = 2 * MB_IN_BYTES;
private long mGlobalAlertBytes;
+ private static final long POLL_RATE_LIMIT_MS = 15_000;
+
+ private long mLastStatsSessionPoll;
+
+ /** Map from UID to number of opened sessions */
+ @GuardedBy("mOpenSessionCallsPerUid")
+ private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
+
+ private final static int DUMP_STATS_SESSION_COUNT = 20;
+
private static @NonNull File getDefaultSystemDir() {
return new File(Environment.getDataDirectory(), "system");
}
@@ -509,10 +519,31 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return openSessionInternal(flags, callingPackage);
}
+ private boolean isRateLimitedForPoll(int callingUid) {
+ if (callingUid == android.os.Process.SYSTEM_UID) {
+ return false;
+ }
+
+ final long lastCallTime;
+ final long now = SystemClock.elapsedRealtime();
+ synchronized (mOpenSessionCallsPerUid) {
+ int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
+ mOpenSessionCallsPerUid.put(callingUid, calls + 1);
+ lastCallTime = mLastStatsSessionPoll;
+ mLastStatsSessionPoll = now;
+ }
+
+ return now - lastCallTime < POLL_RATE_LIMIT_MS;
+ }
+
private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
assertBandwidthControlEnabled();
- if ((flags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) {
+ final int callingUid = Binder.getCallingUid();
+ final int usedFlags = isRateLimitedForPoll(callingUid)
+ ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
+ : flags;
+ if ((usedFlags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) {
final long ident = Binder.clearCallingIdentity();
try {
performPoll(FLAG_PERSIST_ALL);
@@ -525,7 +556,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// for its lifetime; when caller closes only weak references remain.
return new INetworkStatsSession.Stub() {
- private final int mCallingUid = Binder.getCallingUid();
+ private final int mCallingUid = callingUid;
private final String mCallingPackage = callingPackage;
private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
callingPackage);
@@ -559,20 +590,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public NetworkStats getDeviceSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel,
+ return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
mCallingUid);
}
@Override
public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel,
+ return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
mCallingUid);
}
@Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel,
+ return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
mCallingUid);
}
@@ -1461,6 +1492,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
pw.decreaseIndent();
+ // Get the top openSession callers
+ final SparseIntArray calls;
+ synchronized (mOpenSessionCallsPerUid) {
+ calls = mOpenSessionCallsPerUid.clone();
+ }
+
+ final int N = calls.size();
+ final long[] values = new long[N];
+ for (int j = 0; j < N; j++) {
+ values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
+ }
+ Arrays.sort(values);
+
+ pw.println("Top openSession callers (uid=count):");
+ pw.increaseIndent();
+ final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
+ for (int j = N - 1; j >= end; j--) {
+ final int uid = (int) (values[j] & 0xffffffff);
+ final int count = (int) (values[j] >> 32);
+ pw.print(uid); pw.print("="); pw.println(count);
+ }
+ pw.decreaseIndent();
+ pw.println();
+
pw.println("Dev stats:");
pw.increaseIndent();
mDevRecorder.dumpLocked(pw, fullHistory);