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

Commit 915d09b5 authored by Erik Kline's avatar Erik Kline Committed by android-build-merger
Browse files

Support requesting async LinkProperties/NetworkCapabilities updates

am: acdd6395

Change-Id: Icc048323debbbe641941c5c0d993f4c9782c5d3e
parents 461e4fff acdd6395
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -1034,6 +1034,26 @@ public class ConnectivityManager {
        }
    }

    /**
     * Request that this callback be invoked at ConnectivityService's earliest
     * convenience with the current satisfying network's LinkProperties.
     * If no such network exists no callback invocation is performed.
     *
     * The callback must have been registered with #requestNetwork() or
     * #registerDefaultNetworkCallback(); callbacks registered with
     * registerNetworkCallback() are not specific to any particular Network so
     * do not cause any updates.
     *
     * @hide
     */
    public void requestLinkProperties(NetworkCallback networkCallback) {
        try {
            mService.requestLinkProperties(networkCallback.networkRequest);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}.  This
     * will return {@code null} if the network is unknown.
@@ -1051,6 +1071,26 @@ public class ConnectivityManager {
        }
    }

    /**
     * Request that this callback be invoked at ConnectivityService's earliest
     * convenience with the current satisfying network's NetworkCapabilities.
     * If no such network exists no callback invocation is performed.
     *
     * The callback must have been registered with #requestNetwork() or
     * #registerDefaultNetworkCallback(); callbacks registered with
     * registerNetworkCallback() are not specific to any particular Network so
     * do not cause any updates.
     *
     * @hide
     */
    public void requestNetworkCapabilities(NetworkCallback networkCallback) {
        try {
            mService.requestNetworkCapabilities(networkCallback.networkRequest);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the URL that should be used for resolving whether a captive portal is present.
     * 1. This URL should respond with a 204 response to a GET request to indicate no captive
+2 −0
Original line number Diff line number Diff line
@@ -156,6 +156,8 @@ interface IConnectivityManager
    void pendingListenForNetwork(in NetworkCapabilities networkCapabilities,
            in PendingIntent operation);

    void requestLinkProperties(in NetworkRequest networkRequest);
    void requestNetworkCapabilities(in NetworkRequest networkRequest);
    void releaseNetworkRequest(in NetworkRequest networkRequest);

    void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
+158 −86
Original line number Diff line number Diff line
@@ -303,7 +303,7 @@ public class ConnectivityService extends IConnectivityManager.Stub

    /**
     * indicates a timeout period is over - check if we had a network yet or not
     * and if not, call the timeout calback (but leave the request live until they
     * and if not, call the timeout callback (but leave the request live until they
     * cancel it.
     * includes a NetworkRequestInfo
     */
@@ -380,6 +380,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
     */
    private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;

    /**
     * Indicates a caller has requested to have its callback invoked with
     * the latest LinkProperties or NetworkCapabilities.
     *
     * arg1 = UID of caller
     * obj  = NetworkRequest
     */
    private static final int EVENT_REQUEST_LINKPROPERTIES  = 32;
    private static final int EVENT_REQUEST_NETCAPABILITIES = 33;

    /** Handler thread used for both of the handlers below. */
    @VisibleForTesting
    protected final HandlerThread mHandlerThread;
@@ -2447,13 +2457,54 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return true;
    }

    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
        NetworkRequestInfo nri = mNetworkRequests.get(request);
    private NetworkRequestInfo getNriForAppRequest(
            NetworkRequest request, int callingUid, String requestedOperation) {
        final NetworkRequestInfo nri = mNetworkRequests.get(request);

        if (nri != null) {
            if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
                if (DBG) log("Attempt to release unowned NetworkRequest " + request);
                return;
                log(String.format("UID %d attempted to %s for unowned request %s",
                        callingUid, requestedOperation, nri));
                return null;
            }
        }

        return nri;
    }

    private void handleRequestCallbackUpdate(NetworkRequest request, int callingUid,
            String description, int callbackType) {
        final NetworkRequestInfo nri = getNriForAppRequest(request, callingUid, description);
        if (nri == null) return;

        final NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
        // The network that is satisfying this request may have changed since
        // the application requested the update.
        //
        // - If the request is no longer satisfied, don't send any updates.
        // - If the request is satisfied by a different network, it is the
        //   caller's responsibility to check that the Network object in the
        //   callback matches the network that was returned in the last
        //   onAvailable() callback for this request.
        if (nai == null) return;
        callCallbackForRequest(nri, nai, callbackType, 0);
    }

    private void handleRequestLinkProperties(NetworkRequest request, int callingUid) {
        handleRequestCallbackUpdate(request, callingUid,
                "request LinkProperties", ConnectivityManager.CALLBACK_IP_CHANGED);
    }

    private void handleRequestNetworkCapabilities(NetworkRequest request, int callingUid) {
        handleRequestCallbackUpdate(request, callingUid,
                "request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED);
    }

    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
        final NetworkRequestInfo nri = getNriForAppRequest(
                request, callingUid, "release NetworkRequest");
        if (nri == null) return;

        if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request);
        nri.unlinkDeathRecipient();
        mNetworkRequests.remove(request);
@@ -2547,7 +2598,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
        callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0);
    }
    }

    @Override
    public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
@@ -2709,6 +2759,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    handleMobileDataAlwaysOn();
                    break;
                }
                case EVENT_REQUEST_LINKPROPERTIES:
                    handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1);
                    break;
                case EVENT_REQUEST_NETCAPABILITIES:
                    handleRequestNetworkCapabilities((NetworkRequest) msg.obj, msg.arg1);
                    break;
                // Sent by KeepaliveTracker to process an app request on the state machine thread.
                case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
                    mKeepaliveTracker.handleStartKeepalive(msg);
@@ -4169,11 +4225,27 @@ public class ConnectivityService extends IConnectivityManager.Stub
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
    }

    @Override
    public void requestLinkProperties(NetworkRequest networkRequest) {
        ensureNetworkRequestHasType(networkRequest);
        if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
        mHandler.sendMessage(mHandler.obtainMessage(
                EVENT_REQUEST_LINKPROPERTIES, getCallingUid(), 0, networkRequest));
    }

    @Override
    public void requestNetworkCapabilities(NetworkRequest networkRequest) {
        ensureNetworkRequestHasType(networkRequest);
        if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
        mHandler.sendMessage(mHandler.obtainMessage(
                EVENT_REQUEST_NETCAPABILITIES, getCallingUid(), 0, networkRequest));
    }

    @Override
    public void releaseNetworkRequest(NetworkRequest networkRequest) {
        ensureNetworkRequestHasType(networkRequest);
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(),
                0, networkRequest));
        mHandler.sendMessage(mHandler.obtainMessage(
                EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
    }

    @Override
+67 −1
Original line number Diff line number Diff line
@@ -1040,6 +1040,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
    enum CallbackState {
        NONE,
        AVAILABLE,
        NETWORK_CAPABILITIES,
        LINK_PROPERTIES,
        LOSING,
        LOST
    }
@@ -1072,18 +1074,21 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        }
        private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();

        private void setLastCallback(CallbackState state, Network network, Object o) {
        protected void setLastCallback(CallbackState state, Network network, Object o) {
            mCallbacks.offer(new CallbackInfo(state, network, o));
        }

        @Override
        public void onAvailable(Network network) {
            setLastCallback(CallbackState.AVAILABLE, network, null);
        }

        @Override
        public void onLosing(Network network, int maxMsToLive) {
            setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
        }

        @Override
        public void onLost(Network network) {
            setLastCallback(CallbackState.LOST, network, null);
        }
@@ -1744,6 +1749,67 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
    }

    private class TestRequestUpdateCallback extends TestNetworkCallback {
        @Override
        public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
            setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
        }

        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
            setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
        }
    }

    @LargeTest
    public void testRequestCallbackUpdates() throws Exception {
        // File a network request for mobile.
        final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
        final NetworkRequest cellRequest = new NetworkRequest.Builder()
                .addTransportType(TRANSPORT_CELLULAR).build();
        mCm.requestNetwork(cellRequest, cellNetworkCallback);

        // Bring up the mobile network.
        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
        mCellNetworkAgent.connect(true);

        // We should get onAvailable().
        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
        // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
        cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();

        // Update LinkProperties.
        final LinkProperties lp = new LinkProperties();
        lp.setInterfaceName("foonet_data0");
        mCellNetworkAgent.sendLinkProperties(lp);
        // We should get onLinkPropertiesChanged().
        cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();

        // Register a garden variety default network request.
        final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
        mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
        // Only onAvailable() is called; no other information is delivered.
        dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
        dfltNetworkCallback.assertNoCallback();

        // Request a NetworkCapabilities update; only the requesting callback is notified.
        mCm.requestNetworkCapabilities(dfltNetworkCallback);
        dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();
        dfltNetworkCallback.assertNoCallback();

        // Request a LinkProperties update; only the requesting callback is notified.
        mCm.requestLinkProperties(dfltNetworkCallback);
        dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();
        dfltNetworkCallback.assertNoCallback();

        mCm.unregisterNetworkCallback(dfltNetworkCallback);
        mCm.unregisterNetworkCallback(cellNetworkCallback);
    }

    @SmallTest
    public void testRequestBenchmark() throws Exception {
        // Benchmarks connecting and switching performance in the presence of a large number of