Loading core/java/android/net/ConnectivityManager.java +24 −3 Original line number Diff line number Diff line Loading @@ -2606,7 +2606,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() {} Loading Loading @@ -2679,6 +2680,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; Loading Loading @@ -2845,7 +2866,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"); Loading @@ -2861,7 +2882,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); Loading services/core/java/com/android/server/ConnectivityService.java +23 −4 Original line number Diff line number Diff line Loading @@ -2605,14 +2605,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) { Loading Loading @@ -2706,7 +2720,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0); callCallbackForRequest(nri, null, whichCallback, 0); } @Override Loading Loading @@ -2943,6 +2957,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; Loading services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +80 −1 Original line number Diff line number Diff line Loading @@ -1086,7 +1086,8 @@ public class ConnectivityServiceTest extends AndroidTestCase { NETWORK_CAPABILITIES, LINK_PROPERTIES, LOSING, LOST LOST, UNAVAILABLE } private static class CallbackInfo { Loading Loading @@ -1134,6 +1135,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 */); Loading Loading @@ -2291,6 +2297,79 @@ public class ConnectivityServiceTest extends AndroidTestCase { mCm.unregisterNetworkCallback(defaultCallback); } /** * 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 }; Loading Loading
core/java/android/net/ConnectivityManager.java +24 −3 Original line number Diff line number Diff line Loading @@ -2606,7 +2606,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() {} Loading Loading @@ -2679,6 +2680,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; Loading Loading @@ -2845,7 +2866,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"); Loading @@ -2861,7 +2882,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); Loading
services/core/java/com/android/server/ConnectivityService.java +23 −4 Original line number Diff line number Diff line Loading @@ -2605,14 +2605,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) { Loading Loading @@ -2706,7 +2720,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0); callCallbackForRequest(nri, null, whichCallback, 0); } @Override Loading Loading @@ -2943,6 +2957,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; Loading
services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +80 −1 Original line number Diff line number Diff line Loading @@ -1086,7 +1086,8 @@ public class ConnectivityServiceTest extends AndroidTestCase { NETWORK_CAPABILITIES, LINK_PROPERTIES, LOSING, LOST LOST, UNAVAILABLE } private static class CallbackInfo { Loading Loading @@ -1134,6 +1135,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 */); Loading Loading @@ -2291,6 +2297,79 @@ public class ConnectivityServiceTest extends AndroidTestCase { mCm.unregisterNetworkCallback(defaultCallback); } /** * 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 }; Loading