Merge changes I03e7cda7,I675c4ef5 am: af7101ff0f
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2072767 Change-Id: Ib8168a048c03e1fedebdcccde9a53dde1573430b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -7825,6 +7825,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
nai.declaredCapabilities = new NetworkCapabilities(nc);
|
||||
NetworkAgentInfo.restrictCapabilitiesFromNetworkAgent(nc, nai.creatorUid,
|
||||
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE),
|
||||
mCarrierPrivilegeAuthenticator);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.connectivity;
|
||||
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
||||
import static android.net.NetworkCapabilities.transportNamesOf;
|
||||
|
||||
@@ -1224,20 +1225,22 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
||||
*
|
||||
* @param nc the capabilities to sanitize
|
||||
* @param creatorUid the UID of the process creating this network agent
|
||||
* @param hasAutomotiveFeature true if this device has the automotive feature, false otherwise
|
||||
* @param authenticator the carrier privilege authenticator to check for telephony constraints
|
||||
*/
|
||||
public static void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
|
||||
final int creatorUid, @NonNull final CarrierPrivilegeAuthenticator authenticator) {
|
||||
final int creatorUid, final boolean hasAutomotiveFeature,
|
||||
@Nullable final CarrierPrivilegeAuthenticator authenticator) {
|
||||
if (nc.hasTransport(TRANSPORT_TEST)) {
|
||||
nc.restrictCapabilitiesForTestNetwork(creatorUid);
|
||||
}
|
||||
if (!areAllowedUidsAcceptableFromNetworkAgent(nc, authenticator)) {
|
||||
if (!areAllowedUidsAcceptableFromNetworkAgent(nc, hasAutomotiveFeature, authenticator)) {
|
||||
nc.setAllowedUids(new ArraySet<>());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean areAllowedUidsAcceptableFromNetworkAgent(
|
||||
@NonNull final NetworkCapabilities nc,
|
||||
@NonNull final NetworkCapabilities nc, final boolean hasAutomotiveFeature,
|
||||
@Nullable final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {
|
||||
// NCs without access UIDs are fine.
|
||||
if (!nc.hasAllowedUids()) return true;
|
||||
@@ -1252,6 +1255,11 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
||||
// access UIDs
|
||||
if (nc.hasTransport(TRANSPORT_TEST)) return true;
|
||||
|
||||
// Factories that make ethernet networks can allow UIDs for automotive devices.
|
||||
if (nc.hasTransport(TRANSPORT_ETHERNET) && hasAutomotiveFeature) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Factories that make cell networks can allow the UID for the carrier service package.
|
||||
// This can only work in T where there is support for CarrierPrivilegeAuthenticator
|
||||
if (null != carrierPrivilegeAuthenticator
|
||||
@@ -1262,8 +1270,6 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO : accept Railway callers
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,49 +15,51 @@
|
||||
*/
|
||||
package android.net.cts
|
||||
|
||||
import android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS
|
||||
import android.Manifest.permission.MANAGE_TEST_NETWORKS
|
||||
import android.Manifest.permission.NETWORK_SETTINGS
|
||||
import android.content.Context
|
||||
import android.net.InetAddresses
|
||||
import android.net.IpConfiguration
|
||||
import android.net.MacAddress
|
||||
import android.net.TestNetworkInterface
|
||||
import android.net.TestNetworkManager
|
||||
import android.platform.test.annotations.AppModeFull
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.net.module.util.ArrayTrackRecord
|
||||
import com.android.net.module.util.TrackRecord
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.SC_V2
|
||||
import com.android.testutils.runAsShell
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import android.content.Context
|
||||
import org.junit.runner.RunWith
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.fail
|
||||
import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
|
||||
import android.os.Handler
|
||||
import android.os.HandlerExecutor
|
||||
import android.os.Looper
|
||||
import android.platform.test.annotations.AppModeFull
|
||||
import android.util.ArraySet
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.net.module.util.ArrayTrackRecord
|
||||
import com.android.net.module.util.TrackRecord
|
||||
import com.android.networkstack.apishim.EthernetManagerShimImpl
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.InterfaceStateListener
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_CLIENT
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_NONE
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_ABSENT
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_DOWN
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_UP
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_CLIENT
|
||||
import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_NONE
|
||||
import com.android.networkstack.apishim.EthernetManagerShimImpl
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.RouterAdvertisementResponder
|
||||
import com.android.testutils.SC_V2
|
||||
import com.android.testutils.TapPacketReader
|
||||
import com.android.testutils.runAsShell
|
||||
import com.android.testutils.waitForIdle
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.net.Inet6Address
|
||||
import java.util.concurrent.Executor
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import java.net.NetworkInterface
|
||||
import java.util.concurrent.Executor
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
private const val TIMEOUT_MS = 1000L
|
||||
private const val NO_CALLBACK_TIMEOUT_MS = 200L
|
||||
@@ -141,10 +143,13 @@ class EthernetManagerTest {
|
||||
}
|
||||
|
||||
fun expectCallback(iface: EthernetTestInterface, state: Int, role: Int) {
|
||||
expectCallback(InterfaceStateChanged(iface.interfaceName, state, role,
|
||||
if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null))
|
||||
expectCallback(createChangeEvent(iface, state, role))
|
||||
}
|
||||
|
||||
fun createChangeEvent(iface: EthernetTestInterface, state: Int, role: Int) =
|
||||
InterfaceStateChanged(iface.interfaceName, state, role,
|
||||
if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null)
|
||||
|
||||
fun pollForNextCallback(): CallbackEntry {
|
||||
return events.poll(TIMEOUT_MS) ?: fail("Did not receive callback after ${TIMEOUT_MS}ms")
|
||||
}
|
||||
@@ -172,7 +177,9 @@ class EthernetManagerTest {
|
||||
}
|
||||
|
||||
private fun addInterfaceStateListener(executor: Executor, listener: EthernetStateListener) {
|
||||
em.addInterfaceStateListener(executor, listener)
|
||||
runAsShell(CONNECTIVITY_USE_RESTRICTED_NETWORKS) {
|
||||
em.addInterfaceStateListener(executor, listener)
|
||||
}
|
||||
addedListeners.add(listener)
|
||||
}
|
||||
|
||||
@@ -195,28 +202,27 @@ class EthernetManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public fun testCallbacks() {
|
||||
fun testCallbacks() {
|
||||
val executor = HandlerExecutor(Handler(Looper.getMainLooper()))
|
||||
|
||||
// If an interface exists when the callback is registered, it is reported on registration.
|
||||
val iface = createInterface()
|
||||
val listener = EthernetStateListener()
|
||||
addInterfaceStateListener(executor, listener)
|
||||
listener.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
|
||||
val listener1 = EthernetStateListener()
|
||||
addInterfaceStateListener(executor, listener1)
|
||||
validateListenerOnRegistration(listener1)
|
||||
|
||||
// If an interface appears, existing callbacks see it.
|
||||
// TODO: fix the up/up/down/up callbacks and only send down/up.
|
||||
val iface2 = createInterface()
|
||||
listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
|
||||
listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
listener1.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
listener1.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
listener1.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
|
||||
listener1.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
|
||||
// Register a new listener, it should see state of all existing interfaces immediately.
|
||||
val listener2 = EthernetStateListener()
|
||||
addInterfaceStateListener(executor, listener2)
|
||||
listener2.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
|
||||
listener2.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
|
||||
validateListenerOnRegistration(listener2)
|
||||
|
||||
// Removing interfaces first sends link down, then STATE_ABSENT/ROLE_NONE.
|
||||
removeInterface(iface)
|
||||
@@ -233,8 +239,30 @@ class EthernetManagerTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all interfaces are returned for an EthernetStateListener upon registration.
|
||||
*/
|
||||
private fun validateListenerOnRegistration(listener: EthernetStateListener) {
|
||||
// Get all tracked interfaces to validate on listener registration. Ordering and interface
|
||||
// state (up/down) can't be validated for interfaces not created as part of testing.
|
||||
val ifaces = em.getInterfaceList()
|
||||
val polledIfaces = ArraySet<String>()
|
||||
for (i in ifaces) {
|
||||
val event = (listener.pollForNextCallback() as InterfaceStateChanged)
|
||||
val iface = event.iface
|
||||
assertTrue(polledIfaces.add(iface), "Duplicate interface $iface returned")
|
||||
assertTrue(ifaces.contains(iface), "Untracked interface $iface returned")
|
||||
// If the event's iface was created in the test, additional criteria can be validated.
|
||||
createdIfaces.find { it.interfaceName.equals(iface) }?.let {
|
||||
assertEquals(event, listener.createChangeEvent(it, STATE_LINK_UP, ROLE_CLIENT))
|
||||
}
|
||||
}
|
||||
// Assert all callbacks are accounted for.
|
||||
listener.assertNoCallback()
|
||||
}
|
||||
|
||||
@Test
|
||||
public fun testGetInterfaceList() {
|
||||
fun testGetInterfaceList() {
|
||||
setIncludeTestInterfaces(true)
|
||||
|
||||
// Create two test interfaces and check the return list contains the interface names.
|
||||
|
||||
@@ -15518,6 +15518,27 @@ public class ConnectivityServiceTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutomotiveEthernetAllowedUids() throws Exception {
|
||||
mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
|
||||
mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
|
||||
|
||||
// In this test the automotive feature will be enabled.
|
||||
mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
|
||||
|
||||
// Simulate a restricted ethernet network.
|
||||
final NetworkCapabilities.Builder agentNetCaps = new NetworkCapabilities.Builder()
|
||||
.addTransportType(TRANSPORT_ETHERNET)
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
||||
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
|
||||
|
||||
mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
|
||||
new LinkProperties(), agentNetCaps.build());
|
||||
validateAllowedUids(mEthernetNetworkAgent, TRANSPORT_ETHERNET, agentNetCaps);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCbsAllowedUids() throws Exception {
|
||||
mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
|
||||
@@ -15527,6 +15548,24 @@ public class ConnectivityServiceTest {
|
||||
doReturn(true).when(mCarrierPrivilegeAuthenticator)
|
||||
.hasCarrierPrivilegeForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
|
||||
|
||||
// Simulate a restricted telephony network. The telephony factory is entitled to set
|
||||
// the access UID to the service package on any of its restricted networks.
|
||||
final NetworkCapabilities.Builder agentNetCaps = new NetworkCapabilities.Builder()
|
||||
.addTransportType(TRANSPORT_CELLULAR)
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
||||
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
|
||||
.setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
|
||||
|
||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
|
||||
new LinkProperties(), agentNetCaps.build());
|
||||
validateAllowedUids(mCellNetworkAgent, TRANSPORT_CELLULAR, agentNetCaps);
|
||||
}
|
||||
|
||||
private void validateAllowedUids(final TestNetworkAgentWrapper testAgent,
|
||||
@NetworkCapabilities.Transport final int transportUnderTest,
|
||||
final NetworkCapabilities.Builder ncb) throws Exception {
|
||||
final ArraySet<Integer> serviceUidSet = new ArraySet<>();
|
||||
serviceUidSet.add(TEST_PACKAGE_UID);
|
||||
final ArraySet<Integer> nonServiceUidSet = new ArraySet<>();
|
||||
@@ -15537,40 +15576,34 @@ public class ConnectivityServiceTest {
|
||||
|
||||
final TestNetworkCallback cb = new TestNetworkCallback();
|
||||
|
||||
// Simulate a restricted telephony network. The telephony factory is entitled to set
|
||||
// the access UID to the service package on any of its restricted networks.
|
||||
final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
|
||||
.addTransportType(TRANSPORT_CELLULAR)
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
||||
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
|
||||
.setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
|
||||
|
||||
/* Test setting UIDs */
|
||||
// Cell gets to set the service UID as access UID
|
||||
mCm.requestNetwork(new NetworkRequest.Builder()
|
||||
.addTransportType(TRANSPORT_CELLULAR)
|
||||
.addTransportType(transportUnderTest)
|
||||
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
|
||||
.build(), cb);
|
||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
|
||||
new LinkProperties(), ncb.build());
|
||||
mCellNetworkAgent.connect(true);
|
||||
cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
|
||||
testAgent.connect(true);
|
||||
cb.expectAvailableThenValidatedCallbacks(testAgent);
|
||||
ncb.setAllowedUids(serviceUidSet);
|
||||
mCellNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
|
||||
testAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
|
||||
if (SdkLevel.isAtLeastT()) {
|
||||
cb.expectCapabilitiesThat(mCellNetworkAgent,
|
||||
cb.expectCapabilitiesThat(testAgent,
|
||||
caps -> caps.getAllowedUids().equals(serviceUidSet));
|
||||
} else {
|
||||
// S must ignore access UIDs.
|
||||
cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/* Test setting UIDs is rejected when expected */
|
||||
if (TRANSPORT_ETHERNET == transportUnderTest) {
|
||||
mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
|
||||
}
|
||||
|
||||
// ...but not to some other UID. Rejection sets UIDs to the empty set
|
||||
ncb.setAllowedUids(nonServiceUidSet);
|
||||
mCellNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
|
||||
testAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
|
||||
if (SdkLevel.isAtLeastT()) {
|
||||
cb.expectCapabilitiesThat(mCellNetworkAgent,
|
||||
cb.expectCapabilitiesThat(testAgent,
|
||||
caps -> caps.getAllowedUids().isEmpty());
|
||||
} else {
|
||||
// S must ignore access UIDs.
|
||||
@@ -15579,18 +15612,18 @@ public class ConnectivityServiceTest {
|
||||
|
||||
// ...and also not to multiple UIDs even including the service UID
|
||||
ncb.setAllowedUids(serviceUidSetPlus);
|
||||
mCellNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
|
||||
testAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
|
||||
cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
|
||||
|
||||
mCellNetworkAgent.disconnect();
|
||||
cb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
||||
testAgent.disconnect();
|
||||
cb.expectCallback(CallbackEntry.LOST, testAgent);
|
||||
mCm.unregisterNetworkCallback(cb);
|
||||
|
||||
// Must be unset before touching the transports, because remove and add transport types
|
||||
// check the specifier on the builder immediately, contradicting normal builder semantics
|
||||
// TODO : fix the builder
|
||||
ncb.setNetworkSpecifier(null);
|
||||
ncb.removeTransportType(TRANSPORT_CELLULAR);
|
||||
ncb.removeTransportType(transportUnderTest);
|
||||
ncb.addTransportType(TRANSPORT_WIFI);
|
||||
// Wifi does not get to set access UID, even to the correct UID
|
||||
mCm.requestNetwork(new NetworkRequest.Builder()
|
||||
|
||||
Reference in New Issue
Block a user