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

Commit fb5b6805 authored by Etan Cohen's avatar Etan Cohen Committed by Android (Google) Code Review
Browse files

Merge "Support timeouts for requestNetwork() invocations."

parents 35941967 57faba9e
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -2595,7 +2595,8 @@ public class ConnectivityManager {

        /**
         * Called if no network is found in the given timeout time.  If no timeout is given,
         * this will not be called.
         * this will not be called. The associated {@link NetworkRequest} will have already
         * been removed and released, as if {@link #unregisterNetworkCallback} had been called.
         * @hide
         */
        public void onUnavailable() {}
@@ -2668,6 +2669,26 @@ public class ConnectivityManager {
    /** @hide */
    public static final int CALLBACK_RESUMED             = BASE + 12;

    /** @hide */
    public static String getCallbackName(int whichCallback) {
        switch (whichCallback) {
            case CALLBACK_PRECHECK:     return "CALLBACK_PRECHECK";
            case CALLBACK_AVAILABLE:    return "CALLBACK_AVAILABLE";
            case CALLBACK_LOSING:       return "CALLBACK_LOSING";
            case CALLBACK_LOST:         return "CALLBACK_LOST";
            case CALLBACK_UNAVAIL:      return "CALLBACK_UNAVAIL";
            case CALLBACK_CAP_CHANGED:  return "CALLBACK_CAP_CHANGED";
            case CALLBACK_IP_CHANGED:   return "CALLBACK_IP_CHANGED";
            case CALLBACK_RELEASED:     return "CALLBACK_RELEASED";
            case CALLBACK_EXIT:         return "CALLBACK_EXIT";
            case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST";
            case CALLBACK_SUSPENDED:    return "CALLBACK_SUSPENDED";
            case CALLBACK_RESUMED:      return "CALLBACK_RESUMED";
            default:
                return Integer.toString(whichCallback);
        }
    }

    private class CallbackHandler extends Handler {
        private final HashMap<NetworkRequest, NetworkCallback>mCallbackMap;
        private final AtomicInteger mRefCount;
@@ -2834,7 +2855,7 @@ public class ConnectivityManager {
    private final static int REQUEST = 2;

    private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
            NetworkCallback networkCallback, int timeoutSec, int action,
            NetworkCallback networkCallback, int timeoutMs, int action,
            int legacyType) {
        if (networkCallback == null) {
            throw new IllegalArgumentException("null NetworkCallback");
@@ -2850,7 +2871,7 @@ public class ConnectivityManager {
                            new Messenger(sCallbackHandler), new Binder());
                } else {
                    networkCallback.networkRequest = mService.requestNetwork(need,
                            new Messenger(sCallbackHandler), timeoutSec, new Binder(), legacyType);
                            new Messenger(sCallbackHandler), timeoutMs, new Binder(), legacyType);
                }
                if (networkCallback.networkRequest != null) {
                    sNetworkCallback.put(networkCallback.networkRequest, networkCallback);
+23 −4
Original line number Diff line number Diff line
@@ -2539,14 +2539,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
                "request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED);
    }

    private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
        if (mNetworkRequests.get(nri.request) != null && mNetworkForRequestId.get(
                nri.request.requestId) == null) {
            handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_UNAVAIL);
        }
    }

    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
        final NetworkRequestInfo nri = getNriForAppRequest(
                request, callingUid, "release NetworkRequest");
        if (nri == null) return;
        if (nri != null) {
            handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_RELEASED);
        }
    }

        if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request);
    private void handleRemoveNetworkRequest(final NetworkRequestInfo nri, final int whichCallback) {
        final String logCallbackType = ConnectivityManager.getCallbackName(whichCallback);
        if (VDBG || (DBG && nri.request.isRequest())) {
            log("releasing " + nri.request + " (" + logCallbackType + ")");
        }
        nri.unlinkDeathRecipient();
        mNetworkRequests.remove(request);
        mNetworkRequests.remove(nri.request);
        synchronized (mUidToNetworkRequestCount) {
            int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
            if (requests < 1) {
@@ -2635,7 +2649,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                }
            }
        }
        callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0);
        callCallbackForRequest(nri, null, whichCallback, 0);
    }

    @Override
@@ -2778,6 +2792,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    handleRegisterNetworkRequestWithIntent(msg);
                    break;
                }
                case EVENT_TIMEOUT_NETWORK_REQUEST: {
                    NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
                    handleTimedOutNetworkRequest(nri);
                    break;
                }
                case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
                    handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
                    break;
+80 −1
Original line number Diff line number Diff line
@@ -1047,7 +1047,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        NETWORK_CAPABILITIES,
        LINK_PROPERTIES,
        LOSING,
        LOST
        LOST,
        UNAVAILABLE
    }

    /**
@@ -1087,6 +1088,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
            setLastCallback(CallbackState.AVAILABLE, network, null);
        }

        @Override
        public void onUnavailable() {
            setLastCallback(CallbackState.UNAVAILABLE, null, null);
        }

        @Override
        public void onLosing(Network network, int maxMsToLive) {
            setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
@@ -1953,6 +1959,79 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        handlerThread.quit();
    }

    /**
     * Validate that a satisfied network request does not trigger onUnavailable() once the
     * time-out period expires.
     */
    @SmallTest
    public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI).build();
        final TestNetworkCallback networkCallback = new TestNetworkCallback();
        mCm.requestNetwork(nr, networkCallback, 10);

        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connect(false);
        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);

        // pass timeout and validate that UNAVAILABLE is not called
        try {
            Thread.sleep(15);
        } catch (InterruptedException e) {
        }
        networkCallback.assertNoCallback();
    }

    /**
     * Validate that when a time-out is specified for a network request the onUnavailable()
     * callback is called when time-out expires. Then validate that if network request is
     * (somehow) satisfied - the callback isn't called later.
     */
    @SmallTest
    public void testTimedoutNetworkRequest() {
        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI).build();
        final TestNetworkCallback networkCallback = new TestNetworkCallback();
        mCm.requestNetwork(nr, networkCallback, 10);

        // pass timeout and validate that UNAVAILABLE is called
        networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);

        // create a network satisfying request - validate that request not triggered
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connect(false);
        networkCallback.assertNoCallback();
    }

    /**
     * Validate that when a network request is unregistered (cancelled) the time-out for that
     * request doesn't trigger the onUnavailable() callback.
     */
    @SmallTest
    public void testTimedoutAfterUnregisteredNetworkRequest() {
        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI).build();
        final TestNetworkCallback networkCallback = new TestNetworkCallback();
        mCm.requestNetwork(nr, networkCallback, 10);

        // remove request
        mCm.unregisterNetworkCallback(networkCallback);

        // pass timeout and validate that no callbacks
        // Note: doesn't validate that nothing called from CS since even if called the CM already
        // unregisters the callback and won't pass it through!
        try {
            Thread.sleep(15);
        } catch (InterruptedException e) {
        }
        networkCallback.assertNoCallback();

        // create a network satisfying request - validate that request not triggered
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connect(false);
        networkCallback.assertNoCallback();
    }

    private static class TestKeepaliveCallback extends PacketKeepaliveCallback {

        public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };