diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index f3b97bc5c1..1b3f29d180 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -8343,6 +8343,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceNetworkStackOrSettingsPermission(); // Fall-through since other checks are the same with normal requests. case REQUEST: + case RESERVATION: networkCapabilities = new NetworkCapabilities(networkCapabilities); enforceNetworkRequestPermissions(networkCapabilities, callingPackageName, callingAttributionTag, callingUid); diff --git a/tests/unit/java/com/android/server/connectivityservice/CSNetworkReservationTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSNetworkReservationTest.kt new file mode 100644 index 0000000000..db3bbb7e5e --- /dev/null +++ b/tests/unit/java/com/android/server/connectivityservice/CSNetworkReservationTest.kt @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server + +import android.net.ConnectivityManager +import android.net.ConnectivityManager.NetworkCallback +import android.net.NetworkCapabilities +import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED +import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED +import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET +import android.net.NetworkCapabilities.TRANSPORT_ETHERNET +import android.net.NetworkProvider +import android.net.NetworkRequest +import android.net.NetworkScore +import android.os.Build +import android.os.Messenger +import android.os.Process.INVALID_UID +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import com.android.testutils.DevSdkIgnoreRunner +import com.android.testutils.TestableNetworkOfferCallback +import org.junit.Test +import org.junit.runner.RunWith + + +private val ETHERNET_SCORE = NetworkScore.Builder().build() +private val ETHERNET_CAPS = NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_ETHERNET) + .addCapability(NET_CAPABILITY_INTERNET) + .addCapability(NET_CAPABILITY_NOT_CONGESTED) + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) + .build() + +private const val TIMEOUT_MS = 5_000L +private const val NO_CB_TIMEOUT_MS = 200L + +@RunWith(DevSdkIgnoreRunner::class) +@IgnoreUpTo(Build.VERSION_CODES.R) +class CSNetworkReservationTest : CSTest() { + // TODO: remove this helper once reserveNetwork is added. + // NetworkCallback does not currently do anything. It's just here so the API stays consistent + // with the eventual ConnectivityManager API. + private fun ConnectivityManager.reserveNetwork(req: NetworkRequest, cb: NetworkCallback) { + service.requestNetwork(INVALID_UID, req.networkCapabilities, + NetworkRequest.Type.RESERVATION.ordinal, Messenger(csHandler), 0 /* timeout */, + null /* binder */, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE, + context.packageName, context.attributionTag, NetworkCallback.DECLARED_METHODS_ALL) + } + + @Test + fun testReservationTriggersOnNetworkNeeded() { + val provider = NetworkProvider(context, csHandlerThread.looper, "Ethernet provider") + val offerCb = TestableNetworkOfferCallback(TIMEOUT_MS, NO_CB_TIMEOUT_MS) + + cm.registerNetworkProvider(provider) + provider.registerNetworkOffer(ETHERNET_SCORE, ETHERNET_CAPS, {r -> r.run()}, offerCb) + + // TODO: add reservationId to offer, so it doesn't match the default request. + offerCb.expectOnNetworkNeeded(ETHERNET_CAPS) + + val req = NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET).build() + val cb = NetworkCallback() + cm.reserveNetwork(req, cb) + + offerCb.expectOnNetworkNeeded(req.networkCapabilities) + + // TODO: also test onNetworkUnneeded is called once ConnectivityManager supports the + // reserveNetwork API. + } +}