Merge "Update enforceMeteredApnPolicy to follow the compat flag" into main

This commit is contained in:
Treehugger Robot 2025-04-20 22:15:06 -07:00 • committed by Android (Google) Code Review
commit 2c8f7b5608
3 changed files with 146 additions and 4 deletions

View file

@ -111,6 +111,8 @@ public final class ConnectivityCompatChanges {
* {@link android.net.ConnectivityManager#getActiveNetwork()} always returns null.
* {@link android.net.ConnectivityManager.NetworkCallback#onBlockedStatusChanged()} is always
* called with blocked=true.
* {@link android.net.ConnectivityManager#requestNetwork} can not bring up metered network if
* the uid is restricted from using metered networks.
* <p>
* For backwards compatibility, apps running on older releases, or targeting older SDK levels,
* network access from apps without {@link android.Manifest.permission#INTERNET} permission is

View file

@ -8850,10 +8850,21 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// Policy already enforced.
return;
}
final boolean isRestrictedOnMeteredNetworks = mDeps.isAtLeastV()
? mBpfNetMaps.isUidRestrictedOnMeteredNetworks(uid)
: BinderUtils.withCleanCallingIdentity(() ->
mPolicyManager.isUidRestrictedOnMeteredNetworks(uid));
final boolean isRestrictedOnMeteredNetworks;
if (mDeps.isAtLeastV()) {
if (mDeps.isChangeEnabled(NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, uid)) {
isRestrictedOnMeteredNetworks =
mBpfNetMaps.isUidRestrictedOnMeteredNetworks(uid);
} else {
// If the change is disabled and the uid does not have Internet permission,
// uid is considered to be allowed to bring up metered networks.
isRestrictedOnMeteredNetworks = hasInternetPermission(uid)
&& mBpfNetMaps.isUidRestrictedOnMeteredNetworks(uid);
}
} else {
isRestrictedOnMeteredNetworks = BinderUtils.withCleanCallingIdentity(() ->
mPolicyManager.isUidRestrictedOnMeteredNetworks(uid));
}
if (isRestrictedOnMeteredNetworks) {
// If UID is restricted, don't allow them to bring up metered APNs.
networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);

View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 2025 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.INetd.PERMISSION_INTERNET
import android.net.INetd.PERMISSION_NONE
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkProvider
import android.net.NetworkRequest
import android.net.NetworkScore
import android.net.connectivity.ConnectivityCompatChanges.NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION
import android.os.Build
import android.os.Process
import androidx.test.filters.SmallTest
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.TestableNetworkOfferCallback
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mockito.Mockito.doReturn
private const val TIMEOUT_MS = 5_000L
private const val NO_CB_TIMEOUT_MS = 200L
private fun cellNc() = nc(
TRANSPORT_CELLULAR,
NET_CAPABILITY_NOT_SUSPENDED,
NET_CAPABILITY_NOT_VCN_MANAGED
)
private fun cellRequest() = NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.build()
@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
@IgnoreUpTo(Build.VERSION_CODES.R)
class CSEnforceMeteredApnPolicy : CSTest() {
@Parameterized.Parameter(0) lateinit var params: TestParams
data class TestParams(
val changeEnabled: Boolean,
val hasInternetPermission: Boolean,
val expectRequestMeteredNetwork: Boolean
)
companion object {
@JvmStatic
@Parameterized.Parameters
fun arguments() = listOf(
// For backwards compatibility, if the change is disabled and the uid does not have
// the internet permission, the uid can request metered network even if the uid is
// restricted from using metered networks.
TestParams(
changeEnabled = false,
hasInternetPermission = false,
expectRequestMeteredNetwork = true
),
// If the uid has the internet permission and the uid is restricted from using
// metered network, the uid cannot request metered network even if the change is
// disabled.
TestParams(
changeEnabled = false,
hasInternetPermission = true,
expectRequestMeteredNetwork = false
),
// If the change is enabled and the uid is restricted from using metered network,
// the uid cannot request metered network regardless of the internet permission.
TestParams(
changeEnabled = true,
hasInternetPermission = false,
expectRequestMeteredNetwork = false
),
TestParams(
changeEnabled = true,
hasInternetPermission = true,
expectRequestMeteredNetwork = false
)
)
}
@Test
fun testEnforceMeteredApnPolicy() {
deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(params.changeEnabled, NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION)
doReturn(true).`when`(bpfNetMaps).isUidRestrictedOnMeteredNetworks(Process.myUid())
doReturn(if (params.hasInternetPermission) PERMISSION_INTERNET else PERMISSION_NONE )
.`when`(bpfNetMaps).getNetPermForUid(Process.myUid())
val provider = NetworkProvider(context, csHandlerThread.looper, "Cell provider")
cm.registerNetworkProvider(provider)
val offerCb = TestableNetworkOfferCallback(TIMEOUT_MS, NO_CB_TIMEOUT_MS)
provider.registerNetworkOffer(
NetworkScore.Builder().build(),
cellNc(),
Runnable::run,
offerCb
)
val cb = TestableNetworkCallback()
cm.requestNetwork(cellRequest(), cb)
if (params.expectRequestMeteredNetwork) {
offerCb.expectOnNetworkNeeded(cellNc())
} else {
offerCb.assertNoCallback()
}
cm.unregisterNetworkCallback(cb)
provider.unregisterNetworkOffer(offerCb)
}
}