Merge changes I03e7cda7,I675c4ef5
* changes:
Allow ethernet on automotive to set allowed UIDs
Updating Eth CTS to account for existing ifaces
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 6e6b020..691cb4d 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -7825,6 +7825,7 @@
}
nai.declaredCapabilities = new NetworkCapabilities(nc);
NetworkAgentInfo.restrictCapabilitiesFromNetworkAgent(nc, nai.creatorUid,
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE),
mCarrierPrivilegeAuthenticator);
}
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 323888a..466e7b1 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -19,6 +19,7 @@
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 @@
*
* @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 @@
// 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 @@
return true;
}
- // TODO : accept Railway callers
-
return false;
}
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index 04434e5..b12c4db 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -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 @@
}
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 @@
}
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 @@
}
@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 @@
}
}
+ /**
+ * 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.
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 52cebec..6294bff 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -15519,6 +15519,27 @@
}
@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);
mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
@@ -15527,6 +15548,24 @@
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 @@
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 @@
// ...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()