Loading core/java/android/net/IIpConnectivityMetrics.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,8 @@ import android.net.ConnectivityMetricsEvent; interface IIpConnectivityMetrics { /** * @return number of remaining available slots in buffer. * @return the number of remaining available slots in buffer, * or -1 if the event was dropped due to rate limiting. */ int logEvent(in ConnectivityMetricsEvent event); } core/tests/coretests/src/android/util/TokenBucketTest.java +0 −1 Original line number Diff line number Diff line Loading @@ -177,4 +177,3 @@ public class TokenBucketTest extends TestCase { interface Fn { void call(); } } services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java +24 −0 Original line number Diff line number Diff line Loading @@ -19,15 +19,19 @@ package com.android.server.connectivity; import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.net.IIpConnectivityMetrics; import android.net.metrics.ApfProgramEvent; import android.net.metrics.IpConnectivityLog; import android.os.IBinder; import android.os.Parcelable; import android.provider.Settings; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.Base64; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.TokenBucket; import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -56,6 +60,8 @@ final public class IpConnectivityMetrics extends SystemService { // Maximum size of the event buffer. private static final int MAXIMUM_BUFFER_SIZE = DEFAULT_BUFFER_SIZE * 10; private static final int ERROR_RATE_LIMITED = -1; // Lock ensuring that concurrent manipulations of the event buffer are correct. // There are three concurrent operations to synchronize: // - appending events to the buffer. Loading @@ -73,6 +79,8 @@ final public class IpConnectivityMetrics extends SystemService { private int mDropped; @GuardedBy("mLock") private int mCapacity; @GuardedBy("mLock") private final ArrayMap<Class<?>, TokenBucket> mBuckets = makeRateLimitingBuckets(); private final ToIntFunction<Context> mCapacityGetter; Loading Loading @@ -122,6 +130,10 @@ final public class IpConnectivityMetrics extends SystemService { if (event == null) { return left; } if (isRateLimited(event)) { // Do not count as a dropped event. TODO: consider adding separate counter return ERROR_RATE_LIMITED; } if (left == 0) { mDropped++; return 0; Loading @@ -131,6 +143,11 @@ final public class IpConnectivityMetrics extends SystemService { } } private boolean isRateLimited(ConnectivityMetricsEvent event) { TokenBucket tb = mBuckets.get(event.data.getClass()); return (tb != null) && !tb.get(); } private String flushEncodedOutput() { final ArrayList<ConnectivityMetricsEvent> events; final int dropped; Loading Loading @@ -253,4 +270,11 @@ final public class IpConnectivityMetrics extends SystemService { } return Math.min(size, MAXIMUM_BUFFER_SIZE); }; private static ArrayMap<Class<?>, TokenBucket> makeRateLimitingBuckets() { ArrayMap<Class<?>, TokenBucket> map = new ArrayMap<>(); // one token every minute, 50 tokens max: burst of ~50 events every hour. map.put(ApfProgramEvent.class, new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50)); return map; } } services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java +22 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.connectivity; import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.net.IIpConnectivityMetrics; import android.net.metrics.ApfProgramEvent; import android.net.metrics.ApfStats; import android.net.metrics.DefaultNetworkEvent; import android.net.metrics.DhcpClientEvent; Loading Loading @@ -112,6 +113,27 @@ public class IpConnectivityMetricsTest extends TestCase { assertEquals("", output3); } public void testRateLimiting() { final IpConnectivityLog logger = new IpConnectivityLog(mService.impl); final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0); final long fakeTimestamp = 1; int attempt = 100; // More than burst quota, but less than buffer size. for (int i = 0; i < attempt; i++) { logger.log(ev); } String output1 = getdump("flush"); assertFalse("".equals(output1)); for (int i = 0; i < attempt; i++) { assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev)); } String output2 = getdump("flush"); assertEquals("", output2); } public void testEndToEndLogging() { IpConnectivityLog logger = new IpConnectivityLog(mService.impl); Loading Loading
core/java/android/net/IIpConnectivityMetrics.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,8 @@ import android.net.ConnectivityMetricsEvent; interface IIpConnectivityMetrics { /** * @return number of remaining available slots in buffer. * @return the number of remaining available slots in buffer, * or -1 if the event was dropped due to rate limiting. */ int logEvent(in ConnectivityMetricsEvent event); }
core/tests/coretests/src/android/util/TokenBucketTest.java +0 −1 Original line number Diff line number Diff line Loading @@ -177,4 +177,3 @@ public class TokenBucketTest extends TestCase { interface Fn { void call(); } }
services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java +24 −0 Original line number Diff line number Diff line Loading @@ -19,15 +19,19 @@ package com.android.server.connectivity; import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.net.IIpConnectivityMetrics; import android.net.metrics.ApfProgramEvent; import android.net.metrics.IpConnectivityLog; import android.os.IBinder; import android.os.Parcelable; import android.provider.Settings; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.Base64; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.TokenBucket; import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -56,6 +60,8 @@ final public class IpConnectivityMetrics extends SystemService { // Maximum size of the event buffer. private static final int MAXIMUM_BUFFER_SIZE = DEFAULT_BUFFER_SIZE * 10; private static final int ERROR_RATE_LIMITED = -1; // Lock ensuring that concurrent manipulations of the event buffer are correct. // There are three concurrent operations to synchronize: // - appending events to the buffer. Loading @@ -73,6 +79,8 @@ final public class IpConnectivityMetrics extends SystemService { private int mDropped; @GuardedBy("mLock") private int mCapacity; @GuardedBy("mLock") private final ArrayMap<Class<?>, TokenBucket> mBuckets = makeRateLimitingBuckets(); private final ToIntFunction<Context> mCapacityGetter; Loading Loading @@ -122,6 +130,10 @@ final public class IpConnectivityMetrics extends SystemService { if (event == null) { return left; } if (isRateLimited(event)) { // Do not count as a dropped event. TODO: consider adding separate counter return ERROR_RATE_LIMITED; } if (left == 0) { mDropped++; return 0; Loading @@ -131,6 +143,11 @@ final public class IpConnectivityMetrics extends SystemService { } } private boolean isRateLimited(ConnectivityMetricsEvent event) { TokenBucket tb = mBuckets.get(event.data.getClass()); return (tb != null) && !tb.get(); } private String flushEncodedOutput() { final ArrayList<ConnectivityMetricsEvent> events; final int dropped; Loading Loading @@ -253,4 +270,11 @@ final public class IpConnectivityMetrics extends SystemService { } return Math.min(size, MAXIMUM_BUFFER_SIZE); }; private static ArrayMap<Class<?>, TokenBucket> makeRateLimitingBuckets() { ArrayMap<Class<?>, TokenBucket> map = new ArrayMap<>(); // one token every minute, 50 tokens max: burst of ~50 events every hour. map.put(ApfProgramEvent.class, new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50)); return map; } }
services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java +22 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.connectivity; import android.content.Context; import android.net.ConnectivityMetricsEvent; import android.net.IIpConnectivityMetrics; import android.net.metrics.ApfProgramEvent; import android.net.metrics.ApfStats; import android.net.metrics.DefaultNetworkEvent; import android.net.metrics.DhcpClientEvent; Loading Loading @@ -112,6 +113,27 @@ public class IpConnectivityMetricsTest extends TestCase { assertEquals("", output3); } public void testRateLimiting() { final IpConnectivityLog logger = new IpConnectivityLog(mService.impl); final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0); final long fakeTimestamp = 1; int attempt = 100; // More than burst quota, but less than buffer size. for (int i = 0; i < attempt; i++) { logger.log(ev); } String output1 = getdump("flush"); assertFalse("".equals(output1)); for (int i = 0; i < attempt; i++) { assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev)); } String output2 = getdump("flush"); assertEquals("", output2); } public void testEndToEndLogging() { IpConnectivityLog logger = new IpConnectivityLog(mService.impl); Loading