diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 5edefb5e23..dadc5f53eb 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -40,6 +40,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.util.ArrayMap; @@ -2695,6 +2696,28 @@ public class ConnectivityManager { } } + /** + * Constant error codes used by ConnectivityService to communicate about failures and errors + * across a Binder boundary. + * @hide + */ + public interface Errors { + static int TOO_MANY_REQUESTS = 1; + } + + /** @hide */ + public static class TooManyRequestsException extends RuntimeException {} + + private static RuntimeException convertServiceException(ServiceSpecificException e) { + switch (e.errorCode) { + case Errors.TOO_MANY_REQUESTS: + return new TooManyRequestsException(); + default: + Log.w(TAG, "Unknown service error code " + e.errorCode); + return new RuntimeException(e); + } + } + private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; /** @hide */ public static final int CALLBACK_PRECHECK = BASE + 1; @@ -2886,6 +2909,8 @@ public class ConnectivityManager { } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw convertServiceException(e); } return request; } @@ -3127,6 +3152,8 @@ public class ConnectivityManager { mService.pendingRequestForNetwork(request.networkCapabilities, operation); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw convertServiceException(e); } } @@ -3226,6 +3253,8 @@ public class ConnectivityManager { mService.pendingListenForNetwork(request.networkCapabilities, operation); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw convertServiceException(e); } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 8555851fbc..54b02a8b4f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -91,6 +91,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.ServiceSpecificException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -3951,7 +3952,8 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (mUidToNetworkRequestCount) { int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1; if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) { - throw new IllegalArgumentException("Too many NetworkRequests filed"); + throw new ServiceSpecificException( + ConnectivityManager.Errors.TOO_MANY_REQUESTS); } mUidToNetworkRequestCount.put(mUid, networkRequests); } diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java index ceb0135727..cc792cc749 100644 --- a/tests/net/java/android/net/ConnectivityManagerTest.java +++ b/tests/net/java/android/net/ConnectivityManagerTest.java @@ -45,6 +45,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.PendingIntent; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.content.Context; @@ -66,8 +67,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; - - @RunWith(AndroidJUnit4.class) @SmallTest public class ConnectivityManagerTest { @@ -296,6 +295,43 @@ public class ConnectivityManagerTest { manager.requestNetwork(request, callback); } + @Test + public void testArgumentValidation() throws Exception { + ConnectivityManager manager = new ConnectivityManager(mCtx, mService); + + NetworkRequest request = mock(NetworkRequest.class); + NetworkCallback callback = mock(NetworkCallback.class); + Handler handler = mock(Handler.class); + NetworkCallback nullCallback = null; + PendingIntent nullIntent = null; + + mustFail(() -> { manager.requestNetwork(null, callback); }); + mustFail(() -> { manager.requestNetwork(request, nullCallback); }); + mustFail(() -> { manager.requestNetwork(request, callback, null); }); + mustFail(() -> { manager.requestNetwork(request, callback, -1); }); + mustFail(() -> { manager.requestNetwork(request, nullIntent); }); + + mustFail(() -> { manager.registerNetworkCallback(null, callback, handler); }); + mustFail(() -> { manager.registerNetworkCallback(request, null, handler); }); + mustFail(() -> { manager.registerNetworkCallback(request, callback, null); }); + mustFail(() -> { manager.registerNetworkCallback(request, nullIntent); }); + + mustFail(() -> { manager.registerDefaultNetworkCallback(null, handler); }); + mustFail(() -> { manager.registerDefaultNetworkCallback(callback, null); }); + + mustFail(() -> { manager.unregisterNetworkCallback(nullCallback); }); + mustFail(() -> { manager.unregisterNetworkCallback(nullIntent); }); + mustFail(() -> { manager.releaseNetworkRequest(nullIntent); }); + } + + static void mustFail(Runnable fn) { + try { + fn.run(); + fail(); + } catch (Exception expected) { + } + } + static Message makeMessage(NetworkRequest req, int messageType) { Bundle bundle = new Bundle(); bundle.putParcelable(NetworkRequest.class.getSimpleName(), req); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 46dcdad2e8..009986169c 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -44,6 +44,7 @@ import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.PacketKeepalive; import android.net.ConnectivityManager.PacketKeepaliveCallback; +import android.net.ConnectivityManager.TooManyRequestsException; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.IpPrefix; @@ -3055,7 +3056,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { networkCallbacks.add(networkCallback); } fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception"); - } catch (IllegalArgumentException expected) {} + } catch (TooManyRequestsException expected) {} for (NetworkCallback networkCallback : networkCallbacks) { mCm.unregisterNetworkCallback(networkCallback); } @@ -3068,7 +3069,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { networkCallbacks.add(networkCallback); } fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception"); - } catch (IllegalArgumentException expected) {} + } catch (TooManyRequestsException expected) {} for (NetworkCallback networkCallback : networkCallbacks) { mCm.unregisterNetworkCallback(networkCallback); } @@ -3084,7 +3085,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } fail("Registering " + MAX_REQUESTS + " PendingIntent NetworkRequests did not throw exception"); - } catch (IllegalArgumentException expected) {} + } catch (TooManyRequestsException expected) {} for (PendingIntent pendingIntent : pendingIntents) { mCm.unregisterNetworkCallback(pendingIntent); } @@ -3099,7 +3100,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } fail("Registering " + MAX_REQUESTS + " PendingIntent NetworkCallbacks did not throw exception"); - } catch (IllegalArgumentException expected) {} + } catch (TooManyRequestsException expected) {} for (PendingIntent pendingIntent : pendingIntents) { mCm.unregisterNetworkCallback(pendingIntent); }