Add rate limiting and logging for NetworkStats.

Bug: 77908520, 77808546, 77853238, 77154412
Test: atest com.android.server.net.NetworkStatsServiceTest
Test: manual: flashed, verified network usage updated
Change-Id: I905dbea85e00f80103916939f6d4bf8cab931d03
This commit is contained in:
Remi NGUYEN VAN
2018-04-12 19:26:34 +09:00
committed by Jeff Sharkey
parent 8732487ce6
commit 3d55d4c02e

View File

@@ -286,6 +286,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private long mPersistThreshold = 2 * MB_IN_BYTES; private long mPersistThreshold = 2 * MB_IN_BYTES;
private long mGlobalAlertBytes; 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() { private static @NonNull File getDefaultSystemDir() {
return new File(Environment.getDataDirectory(), "system"); return new File(Environment.getDataDirectory(), "system");
} }
@@ -509,10 +519,31 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return openSessionInternal(flags, callingPackage); 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) { private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
assertBandwidthControlEnabled(); 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(); final long ident = Binder.clearCallingIdentity();
try { try {
performPoll(FLAG_PERSIST_ALL); performPoll(FLAG_PERSIST_ALL);
@@ -525,7 +556,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// for its lifetime; when caller closes only weak references remain. // for its lifetime; when caller closes only weak references remain.
return new INetworkStatsSession.Stub() { return new INetworkStatsSession.Stub() {
private final int mCallingUid = Binder.getCallingUid(); private final int mCallingUid = callingUid;
private final String mCallingPackage = callingPackage; private final String mCallingPackage = callingPackage;
private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel( private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
callingPackage); callingPackage);
@@ -559,20 +590,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override @Override
public NetworkStats getDeviceSummaryForNetwork( public NetworkStats getDeviceSummaryForNetwork(
NetworkTemplate template, long start, long end) { NetworkTemplate template, long start, long end) {
return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
mCallingUid); mCallingUid);
} }
@Override @Override
public NetworkStats getSummaryForNetwork( public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) { NetworkTemplate template, long start, long end) {
return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
mCallingUid); mCallingUid);
} }
@Override @Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel, return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
mCallingUid); mCallingUid);
} }
@@ -1461,6 +1492,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
pw.decreaseIndent(); 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.println("Dev stats:");
pw.increaseIndent(); pw.increaseIndent();
mDevRecorder.dumpLocked(pw, fullHistory); mDevRecorder.dumpLocked(pw, fullHistory);