summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Paul Jensen <pauljensen@google.com> 2016-04-21 13:47:11 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2016-04-21 13:47:13 +0000
commit3f4510535397bf103d0299440a0299ff8bbeec28 (patch)
tree710d528204ea83a4d5f30bf59130938f378f26a9
parentb99d6af3ab406db14d161cdc0000ed521957d7ca (diff)
parent4e1d3fdf7a43b3e43efac0a26ca3d0f458ce87d3 (diff)
Merge "Cap number of NetworkRequests a UID can make to 100" into nyc-dev
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java29
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java93
3 files changed, 123 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0f217967db6a..b965f64c5333 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2330,6 +2330,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (VDBG || (DBG && nri.isRequest())) log("releasing NetworkRequest " + request);
nri.unlinkDeathRecipient();
mNetworkRequests.remove(request);
+ synchronized (mUidToNetworkRequestCount) {
+ int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
+ if (requests < 1) {
+ Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
+ nri.mUid);
+ } else if (requests == 1) {
+ mUidToNetworkRequestCount.removeAt(
+ mUidToNetworkRequestCount.indexOfKey(nri.mUid));
+ } else {
+ mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
+ }
+ }
mNetworkRequestInfoLogs.log("RELEASE " + nri);
if (nri.isRequest()) {
// Find all networks that are satisfying this request and remove the request
@@ -3677,6 +3689,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
new HashMap<NetworkRequest, NetworkRequestInfo>();
+ private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
+ // Map from UID to number of NetworkRequests that UID has filed.
+ @GuardedBy("mUidToNetworkRequestCount")
+ private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();
+
private static class NetworkFactoryInfo {
public final String name;
public final Messenger messenger;
@@ -3737,6 +3754,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mPid = getCallingPid();
mUid = getCallingUid();
mType = type;
+ enforceRequestCountLimit();
}
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, NetworkRequestType type) {
@@ -3748,6 +3766,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mUid = getCallingUid();
mType = type;
mPendingIntent = null;
+ enforceRequestCountLimit();
try {
mBinder.linkToDeath(this, 0);
@@ -3756,6 +3775,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private void enforceRequestCountLimit() {
+ synchronized (mUidToNetworkRequestCount) {
+ int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
+ if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
+ throw new IllegalArgumentException("Too many NetworkRequests filed");
+ }
+ mUidToNetworkRequestCount.put(mUid, networkRequests);
+ }
+ }
+
private String typeString() {
switch (mType) {
case LISTEN: return "Listen";
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 23f186c42ce3..7017d81e43bb 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -42,6 +42,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
+ <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 26eed24c4f39..4fae4a732aad 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -74,6 +74,7 @@ import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
+import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -1788,4 +1789,96 @@ public class ConnectivityServiceTest extends AndroidTestCase {
waitFor(cv);
assertPinnedToWifiWithCellDefault();
}
+
+ @SmallTest
+ public void testNetworkRequestMaximum() {
+ final int MAX_REQUESTS = 100;
+ // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
+ NetworkRequest networkRequest = new NetworkRequest.Builder().build();
+ ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
+ try {
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.requestNetwork(networkRequest, networkCallback);
+ networkCallbacks.add(networkCallback);
+ }
+ fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
+ } catch (IllegalArgumentException expected) {}
+ for (NetworkCallback networkCallback : networkCallbacks) {
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ networkCallbacks.clear();
+
+ try {
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.registerNetworkCallback(networkRequest, networkCallback);
+ networkCallbacks.add(networkCallback);
+ }
+ fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
+ } catch (IllegalArgumentException expected) {}
+ for (NetworkCallback networkCallback : networkCallbacks) {
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ networkCallbacks.clear();
+
+ ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
+ try {
+ for (int i = 0; i < MAX_REQUESTS + 1; i++) {
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
+ mCm.requestNetwork(networkRequest, pendingIntent);
+ pendingIntents.add(pendingIntent);
+ }
+ fail("Registering " + MAX_REQUESTS +
+ " PendingIntent NetworkRequests did not throw exception");
+ } catch (IllegalArgumentException expected) {}
+ for (PendingIntent pendingIntent : pendingIntents) {
+ mCm.unregisterNetworkCallback(pendingIntent);
+ }
+ pendingIntents.clear();
+
+ try {
+ for (int i = 0; i < MAX_REQUESTS + 1; i++) {
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
+ mCm.registerNetworkCallback(networkRequest, pendingIntent);
+ pendingIntents.add(pendingIntent);
+ }
+ fail("Registering " + MAX_REQUESTS +
+ " PendingIntent NetworkCallbacks did not throw exception");
+ } catch (IllegalArgumentException expected) {}
+ for (PendingIntent pendingIntent : pendingIntents) {
+ mCm.unregisterNetworkCallback(pendingIntent);
+ }
+ pendingIntents.clear();
+ mService.waitForIdle(5000);
+
+ // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.requestNetwork(networkRequest, networkCallback);
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ mService.waitForIdle();
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ NetworkCallback networkCallback = new NetworkCallback();
+ mCm.registerNetworkCallback(networkRequest, networkCallback);
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ mService.waitForIdle();
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
+ mCm.requestNetwork(networkRequest, pendingIntent);
+ mCm.unregisterNetworkCallback(pendingIntent);
+ }
+ mService.waitForIdle();
+ for (int i = 0; i < MAX_REQUESTS; i++) {
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
+ mCm.registerNetworkCallback(networkRequest, pendingIntent);
+ mCm.unregisterNetworkCallback(pendingIntent);
+ }
+ }
}