Allow NetworkFactories to match any network specifier on a request
Current usage of NetworkSpecifier: network factory will match a request
if the request has either a (1) empty network specifier, or (2) a
network specifier which is identical to that of the network factory.
Note: 'matching' w.r.t. network specifier - all other matching rules
are still in effect.
Change: add rule (3) or the network specifier of the network factory
is the special string (which is defined as "*" and which user-facing
network requests aren't allowed to use).
Rationale: allows on-demand network creation.
Example:
- Can specify a Wi-Fi NetworkRequest with NetworkSpecifier="ssid"
- It will match a Wi-Fi network factory specifying NetworkSpecifier="*"
- That network factory will bring up a Wi-Fi network, connecting to the
specified SSID.
- Once the network is created it will create a NetworkAgent which will
now have a NetworkSpecifier matching that of the request (not the
match-all special string!)
That final step of making sure that the NetworkAgent matches the request
and not the match-all is critical to delivering any subsequent callbacks
correctly. I.e. your network will only get callbacks which match it.
Bug: 26192833
Change-Id: I49e3b492e0bb48a3f6e9a34e3f94f0e1cf89741f
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 3bd12c0..e27c0fb 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -197,6 +197,19 @@
(1 << NET_CAPABILITY_CAPTIVE_PORTAL);
/**
+ * Network specifier for factories which want to match any network specifier
+ * (NS) in a request. Behavior:
+ * <li>Empty NS in request matches any network factory NS</li>
+ * <li>Empty NS in the network factory NS only matches a request with an
+ * empty NS</li>
+ * <li>"*" (this constant) NS in the network factory matches requests with
+ * any NS</li>
+ *
+ * @hide
+ */
+ public static final String MATCH_ALL_REQUESTS_NETWORK_SPECIFIER = "*";
+
+ /**
* Network capabilities that are not allowed in NetworkRequests. This exists because the
* NetworkFactory / NetworkAgent model does not deal well with the situation where a
* capability's presence cannot be known in advance. If such a capability is requested, then we
@@ -596,7 +609,8 @@
}
private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
return (TextUtils.isEmpty(mNetworkSpecifier) ||
- mNetworkSpecifier.equals(nc.mNetworkSpecifier));
+ mNetworkSpecifier.equals(nc.mNetworkSpecifier) ||
+ MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier));
}
private boolean equalsSpecifier(NetworkCapabilities nc) {
if (TextUtils.isEmpty(mNetworkSpecifier)) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 7da4818..f1edcbe 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -188,6 +188,10 @@
* networks.
*/
public Builder setNetworkSpecifier(String networkSpecifier) {
+ if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) {
+ throw new IllegalArgumentException("Invalid network specifier - must not be '"
+ + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
+ }
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
return this;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 327fb8a..9c09f24 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3678,6 +3678,12 @@
throw new IllegalArgumentException("Bad timeout specified");
}
+ if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER
+ .equals(networkCapabilities.getNetworkSpecifier())) {
+ throw new IllegalArgumentException("Invalid network specifier - must not be '"
+ + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
+ }
+
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 97e16da..d096c28 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -52,13 +52,16 @@
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
+import android.os.Messenger;
import android.os.MessageQueue.IdleHandler;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.LogPrinter;
@@ -1291,6 +1294,36 @@
validatedCallback.expectCallback(CallbackState.LOST);
}
+ @SmallTest
+ public void testInvalidNetworkSpecifier() {
+ boolean execptionCalled = true;
+
+ try {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+ execptionCalled = false;
+ } catch (IllegalArgumentException e) {
+ // do nothing - should get here
+ }
+
+ assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
+ execptionCalled);
+
+ try {
+ NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+ networkCapabilities.addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+ mService.requestNetwork(networkCapabilities, null, 0, null,
+ ConnectivityManager.TYPE_WIFI);
+ execptionCalled = false;
+ } catch (IllegalArgumentException e) {
+ // do nothing - should get here
+ }
+
+ assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
+ execptionCalled);
+ }
+
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };