Merge "Revert^2 "Add blocked reason for internet permission"" into main

This commit is contained in:
Treehugger Robot 2024-05-28 00:00:07 +00:00 • committed by Gerrit Code Review
commit d86bd6faca
4 changed files with 163 additions and 13 deletions

View file

@ -53,6 +53,7 @@ import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.EXTRA_DEVICE_TYPE;
@ -9880,6 +9881,28 @@ public class ConnectivityServiceTest {
assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertExtraInfoFromCmPresent(mCellAgent);
// Remove PERMISSION_INTERNET and disable NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION
doReturn(INetd.PERMISSION_NONE).when(mBpfNetMaps).getNetPermForUid(Process.myUid());
mDeps.setChangeIdEnabled(false,
NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, Process.myUid());
setBlockedReasonChanged(BLOCKED_REASON_DOZE);
if (mDeps.isAtLeastV()) {
// On V+, network access from app that does not have INTERNET permission is considered
// not blocked if NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION is disabled.
// So blocked status does not change from BLOCKED_REASON_NONE
cellNetworkCallback.assertNoCallback();
detailedCallback.assertNoCallback();
} else {
// On U-, onBlockedStatusChanged callback is called with blocked reasons CS receives
// from NPMS callback regardless of permission app has.
// Note that this cannot actually happen because on U-, NPMS will never notify any
// blocked reasons for apps that don't have the INTERNET permission.
cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
cb -> cb.getReason() == BLOCKED_REASON_DOZE);
}
mCm.unregisterNetworkCallback(cellNetworkCallback);
}

View file

@ -20,6 +20,7 @@ import android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER
import android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED
import android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND
import android.net.ConnectivityManager.BLOCKED_REASON_DOZE
import android.net.ConnectivityManager.BLOCKED_REASON_NETWORK_RESTRICTED
import android.net.ConnectivityManager.BLOCKED_REASON_NONE
import android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND
import android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE
@ -27,6 +28,7 @@ import android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER
import android.net.ConnectivityManager.FIREWALL_RULE_ALLOW
import android.net.ConnectivityManager.FIREWALL_RULE_DENY
import android.net.ConnectivitySettingsManager
import android.net.INetd.PERMISSION_NONE
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
@ -36,6 +38,7 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.net.connectivity.ConnectivityCompatChanges.NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION
import android.os.Build
import android.os.Process
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@ -144,6 +147,12 @@ class CSBlockedReasonsTest : CSTest() {
cm.setDataSaverEnabled(false)
cellCb.expectBlockedStatusChanged(cellAgent.network, BLOCKED_REASON_APP_BACKGROUND)
// waitForIdle since stubbing bpfNetMaps while CS handler thread calls
// bpfNetMaps.getNetPermForUid throws exception.
// The expectBlockedStatusChanged just above guarantees that the onBlockedStatusChanged
// method on this callback was called, but it does not guarantee that ConnectivityService
// has finished processing all onBlockedStatusChanged callbacks for all requests.
waitForIdle()
// Enable data saver
doReturn(BLOCKED_REASON_APP_BACKGROUND or BLOCKED_METERED_REASON_DATA_SAVER)
.`when`(bpfNetMaps).getUidNetworkingBlockedReasons(Process.myUid())
@ -186,6 +195,12 @@ class CSBlockedReasonsTest : CSTest() {
blockedReason = BLOCKED_REASON_DOZE
)
// waitForIdle since stubbing bpfNetMaps while CS handler thread calls
// bpfNetMaps.getNetPermForUid throws exception.
// The expectBlockedStatusChanged just above guarantees that the onBlockedStatusChanged
// method on this callback was called, but it does not guarantee that ConnectivityService
// has finished processing all onBlockedStatusChanged callbacks for all requests.
waitForIdle()
// Set RULE_ALLOW on metered deny chain
doReturn(BLOCKED_REASON_DOZE)
.`when`(bpfNetMaps).getUidNetworkingBlockedReasons(Process.myUid())
@ -343,4 +358,61 @@ class CSBlockedReasonsTest : CSTest() {
cm.unregisterNetworkCallback(wifiCb)
cm.unregisterNetworkCallback(cb)
}
private fun doTestBlockedReasonsNoInternetPermission(blockedByNoInternetPermission: Boolean) {
doReturn(PERMISSION_NONE).`when`(bpfNetMaps).getNetPermForUid(Process.myUid())
val wifiCb = DetailedBlockedStatusCallback()
cm.requestNetwork(wifiRequest(), wifiCb)
val wifiAgent = Agent(nc = wifiNc())
wifiAgent.connect()
val expectedBlockedReason = if (blockedByNoInternetPermission) {
BLOCKED_REASON_NETWORK_RESTRICTED
} else {
BLOCKED_REASON_NONE
}
wifiCb.expectAvailableCallbacks(
wifiAgent.network,
validated = false,
blockedReason = expectedBlockedReason
)
// Enable background firewall chain
doReturn(BLOCKED_REASON_APP_BACKGROUND)
.`when`(bpfNetMaps).getUidNetworkingBlockedReasons(Process.myUid())
cm.setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true)
if (blockedByNoInternetPermission) {
wifiCb.expectBlockedStatusChanged(
wifiAgent.network,
BLOCKED_REASON_NETWORK_RESTRICTED or BLOCKED_REASON_APP_BACKGROUND
)
}
// Disable background firewall chain
doReturn(BLOCKED_REASON_NONE)
.`when`(bpfNetMaps).getUidNetworkingBlockedReasons(Process.myUid())
cm.setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, false)
if (blockedByNoInternetPermission) {
wifiCb.expectBlockedStatusChanged(
wifiAgent.network,
BLOCKED_REASON_NETWORK_RESTRICTED
)
} else {
// No callback is expected since blocked reasons does not change from
// BLOCKED_REASON_NONE.
wifiCb.assertNoCallback()
}
}
@Test
fun testBlockedReasonsNoInternetPermission_changeDisabled() {
deps.setChangeIdEnabled(false, NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION)
doTestBlockedReasonsNoInternetPermission(blockedByNoInternetPermission = false)
}
@Test
fun testBlockedReasonsNoInternetPermission_changeEnabled() {
deps.setChangeIdEnabled(true, NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION)
doTestBlockedReasonsNoInternetPermission(blockedByNoInternetPermission = true)
}
}

View file

@ -37,6 +37,7 @@ import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChange
import com.android.testutils.TestableNetworkCallback
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.InOrder
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
import org.mockito.Mockito.timeout
@ -96,6 +97,11 @@ class CSIngressDiscardRuleTests : CSTest() {
private val LOCAL_IPV6_ADDRRESS = InetAddresses.parseNumericAddress("fe80::1234")
private val LOCAL_IPV6_LINK_ADDRRESS = LinkAddress(LOCAL_IPV6_ADDRRESS, 64)
fun verifyNoMoreIngressDiscardRuleChange(inorder: InOrder) {
inorder.verify(bpfNetMaps, never()).setIngressDiscardRule(any(), any())
inorder.verify(bpfNetMaps, never()).removeIngressDiscardRule(any())
}
@Test
fun testVpnIngressDiscardRule_UpdateVpnAddress() {
// non-VPN network whose address will be not duplicated with VPN address
@ -148,7 +154,7 @@ class CSIngressDiscardRuleTests : CSTest() {
// IngressDiscardRule is added to the VPN address
inorder.verify(bpfNetMaps).setIngressDiscardRule(IPV6_ADDRESS, VPN_IFNAME)
inorder.verifyNoMoreInteractions()
verifyNoMoreIngressDiscardRuleChange(inorder)
// The VPN interface name is changed
val newlp = lp(VPN_IFNAME2, IPV6_LINK_ADDRESS, LOCAL_IPV6_LINK_ADDRRESS)
@ -157,7 +163,7 @@ class CSIngressDiscardRuleTests : CSTest() {
// IngressDiscardRule is updated with the new interface name
inorder.verify(bpfNetMaps).setIngressDiscardRule(IPV6_ADDRESS, VPN_IFNAME2)
inorder.verifyNoMoreInteractions()
verifyNoMoreIngressDiscardRuleChange(inorder)
agent.disconnect()
inorder.verify(bpfNetMaps, timeout(TIMEOUT_MS)).removeIngressDiscardRule(IPV6_ADDRESS)
@ -206,10 +212,10 @@ class CSIngressDiscardRuleTests : CSTest() {
// IngressDiscardRule for IPV6_ADDRESS2 is removed but IngressDiscardRule for
// IPV6_LINK_ADDRESS is not added since Wi-Fi also uses IPV6_LINK_ADDRESS
inorder.verify(bpfNetMaps).removeIngressDiscardRule(IPV6_ADDRESS2)
inorder.verifyNoMoreInteractions()
verifyNoMoreIngressDiscardRuleChange(inorder)
vpnAgent.disconnect()
inorder.verifyNoMoreInteractions()
verifyNoMoreIngressDiscardRuleChange(inorder)
cm.unregisterNetworkCallback(cb)
}
@ -225,7 +231,7 @@ class CSIngressDiscardRuleTests : CSTest() {
// IngressDiscardRule is added to the VPN address
inorder.verify(bpfNetMaps).setIngressDiscardRule(IPV6_ADDRESS, VPN_IFNAME)
inorder.verifyNoMoreInteractions()
verifyNoMoreIngressDiscardRuleChange(inorder)
val nr = nr(TRANSPORT_WIFI)
val cb = TestableNetworkCallback()
@ -247,7 +253,7 @@ class CSIngressDiscardRuleTests : CSTest() {
// IngressDiscardRule is added to the VPN address since the VPN address is not duplicated
// with the Wi-Fi address
inorder.verify(bpfNetMaps).setIngressDiscardRule(IPV6_ADDRESS, VPN_IFNAME)
inorder.verifyNoMoreInteractions()
verifyNoMoreIngressDiscardRuleChange(inorder)
// The Wi-Fi address is changed back to the same address as the VPN interface
wifiAgent.sendLinkProperties(wifiLp)

View file

@ -27,6 +27,7 @@ import android.content.pm.UserInfo
import android.content.res.Resources
import android.net.ConnectivityManager
import android.net.INetd
import android.net.INetd.PERMISSION_INTERNET
import android.net.InetAddresses
import android.net.LinkProperties
import android.net.LocalNetworkConfig
@ -89,6 +90,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.rules.TestName
import org.mockito.AdditionalAnswers.delegatesTo
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
@ -187,7 +189,9 @@ open class CSTest {
val connResources = makeMockConnResources(sysResources, packageManager)
val netd = mock<INetd>()
val bpfNetMaps = mock<BpfNetMaps>()
val bpfNetMaps = mock<BpfNetMaps>().also {
doReturn(PERMISSION_INTERNET).`when`(it).getNetPermForUid(anyInt())
}
val clatCoordinator = mock<ClatCoordinator>()
val networkRequestStateStatsMetrics = mock<NetworkRequestStateStatsMetrics>()
val proxyTracker = ProxyTracker(