Merge "Revert^2 "Add blocked reason for internet permission"" into main
This commit is contained in:
commit
d86bd6faca
4 changed files with 163 additions and 13 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in a new issue