Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddb9ef03 authored by Etan Cohen's avatar Etan Cohen
Browse files

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
parent 9be302b4
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -196,6 +196,19 @@ public final class NetworkCapabilities implements Parcelable {
            (1 << NET_CAPABILITY_VALIDATED) |
            (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
@@ -596,7 +609,8 @@ public final class NetworkCapabilities implements Parcelable {
    }
    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)) {
+4 −0
Original line number Diff line number Diff line
@@ -188,6 +188,10 @@ public class NetworkRequest implements Parcelable {
         *                         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;
        }
+6 −0
Original line number Diff line number Diff line
@@ -3678,6 +3678,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
            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,
+33 −0
Original line number Diff line number Diff line
@@ -52,13 +52,16 @@ import android.net.RouteInfo;
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 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        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 };