Android Auto OS 13 and higher contains features allowing you to configure and manage Ethernet networks. Figure 1 shows an example network diagram for an automobile:
Figure 1. Android Auto networking.
This figure shows your OEM networking app calling methods in the
EthernetManager
class to configure and manage onboard Ethernet networks
(eth0.1, eth0.2, and eth0.3). The remainder of Figure 1 is out of scope for
this document.
Set default Ethernet network settings
To set default network settings, use the
resource overlay
config_ethernet_interfaces
:
<string-array translatable="false" name="config_ethernet_interfaces">
<!--
<item>eth1;12,13,14,15;ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8</item>
<item>eth2;;ip=192.168.0.11/24</item>
<item>eth3;12,13,14,15;ip=192.168.0.12/24;1</item>
-->
</string-array>
This
example shows the config_ethernet_interfaces
resource overlay from
config.xml
.
Key points about the code
eth1
,eth2
, andeth3
are the names of network interface being configured.- The consecutive numbers of
12, 13, 14, 15
represent network capabilities being enabled. ip=
,gateway=
, anddns
are used to set the initial IP address, gateway, and DNS for the network.
Enable or disable a network interface
To enable a network interface, call
EthernetManager.enableInterface()
:
public final class InterfaceEnabler {
private final Context mApplicationContext;
private final EthernetManager mEthernetManager;
private final OutcomeReceiver<String, EthernetNetworkManagementException> mOutcomeReceiver;
public InterfaceEnabler(Context applicationContext,
OutcomeReceiver<String, EthernetNetworkManagementException> outcomeReceiver) {
mApplicationContext = applicationContext;
mEthernetManager = applicationContext.getSystemService(EthernetManager.class);
mOutcomeReceiver = outcomeReceiver;
}
public void enableInterface(String ifaceName) {
mEthernetManager.enableInterface(ifaceName,
mApplicationContext.getMainExecutor(),
mOutcomeReceiver);
}
}
Key points about the code
ifaceName
is the name of the network interface to enable.getMainExecutor()
returns the app context.OutcomeReceiver
is a callback used to communicate completion returning the updated network name on success orEthernetNetworkManagementException
on error.
When a network interface is enabled, it uses the configuration set by
EthernetManager.updateConfiguration()
. If a configuration hasn't been set
by EthernetManager.updateConfiguration()
, the network interface uses the
resource overlay config_ethernet_interfaces
or the default Ethernet network
configuration if an overlay isn't available.
To disable a network interface, call
EthernetManager.disableInterface()
:
public final class InterfaceEnabler {
private final Context mApplicationContext;
private final EthernetManager mEthernetManager;
private final OutcomeReceiver<String, EthernetNetworkManagementException> mOutcomeReceiver;
public InterfaceEnabler(Context applicationContext,
OutcomeReceiver<String, EthernetNetworkManagementException> outcomeReceiver) {
mApplicationContext = applicationContext;
mEthernetManager = applicationContext.getSystemService(EthernetManager.class);
mOutcomeReceiver = outcomeReceiver;
}
public void disableInterface(String ifaceName) {
mEthernetManager.disableInterface(ifaceName,
mApplicationContext.getMainExecutor(),
mOutcomeReceiver);
}
}
Key points about the code
ifaceName
is the name of the network interface to disable.getMainExecutor()
returns the app context.OutcomeReceiver
is a callback used to communicate completion returning the updated network name on success orEthernetNetworkManagementException
on error.
Update network configuration
To update
Ethernet network configurations, call
EthernetManager.updateConfiguration()
:
public final class ConfigurationUpdater {
private final Context mApplicationContext;
private final EthernetManager mEthernetManager;
private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
public ConfigurationUpdater(Context applicationContext,
OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
mApplicationContext = applicationContext;
mEthernetManager = applicationContext.getSystemService(EthernetManager.class);
mCallback = callback;
}
public void updateNetworkConfiguration(String packageNames,
String ipConfigurationText,
String networkCapabilitiesText,
String interfaceName)
throws IllegalArgumentException, PackageManager.NameNotFoundException {
EthernetNetworkUpdateRequest request = new EthernetNetworkUpdateRequest.Builder()
.setIpConfiguration(getIpConfiguration(ipConfigurationText))
.setNetworkCapabilities(getCapabilities(
interfaceName, networkCapabilitiesText, packageNames))
.build();
mEthernetManager.updateConfiguration(interfaceName, request,
mApplicationContext.getMainExecutor(), mCallback);
}
}
Key points about the code
getCapabilities()
is a helper method that gets the current network capabilities and callsconvertToUIDs()
to convert human-readable package names to Linux unique identifier (UID). Typically, you don't know the UIDs in advance for their associated packages. Therefore, if you want to useEthernetManager.updateConfiguration()
to limit access to a subset of apps, you need to use their UIDs.request
is the configuration to be used for the internal network. The request can contain a new settings for the IP configuration and network capabilities. If the network is registered with the connectivity stack, it's updated as per the configuration. This configuration doesn't persist across reboots.getMainExecutor()
returns the executor on which the listener is invoked.mCallback
is the callback used to communicate completion returning the updated network name on success orEthernetNetworkManagementException
on error.
updateConfiguration()
might update characteristics of a network considered
immutable by the Android Connectivity stack. The
network is brought down, updated, and brought back up for these immutable
attributes to be updated.
Restrict a network to a subset of apps
You can use EthernetManager#updateConfiguration
to limit access to only a
subset of allowed UIDs. Use this method to cover use cases where this is
required, such as for internal vehicular networks only usable by a small subset
of OEM apps.
Android primarily tracks apps by their UID.
The following code from
UIDToPackageNameConverter.java
shows how to obtain a series of UIDs from a string of package names:
public static Set<Integer> convertToUids(Context applicationContext, String packageNames)
throws PackageManager.NameNotFoundException {
final PackageManager packageManager = applicationContext.getPackageManager();
final UserManager userManager = applicationContext.getSystemService(UserManager.class);
final Set<Integer> uids = new ArraySet<>();
final List<UserHandle> users = userManager.getUserHandles(true);
String[] packageNamesArray = packageNames.split(",");
for (String packageName : packageNamesArray) {
boolean nameNotFound = true;
packageName = packageName.trim();
for (final UserHandle user : users) {
try {
final int uid =
packageManager.getApplicationInfoAsUser(packageName, 0, user).uid;
uids.add(uid);
nameNotFound = false;
} catch (PackageManager.NameNotFoundException e) {
// Although this may seem like an error scenario, it is OK as all packages are
// not expected to be installed for all users.
continue;
}
}
if (nameNotFound) {
throw new PackageManager.NameNotFoundException("Not installed: " + packageName);
}
}
return uids;
Key points about the code
getApplicationInfoAsuser().uid
is used to retrieve the UID of from the package name.uids
is the generated array of integers.
The following code in
EthernetManagerTest.kt
shows how to update your network interface configuration with a UIDs of the apps
allowed to use the network:
val allowedUids = setOf(Process.myUid())
val nc = NetworkCapabilities.Builder(request.networkCapabilities)
.setAllowedUids(allowedUids).build()
updateConfiguration(iface, capabilities = nc).expectResult(iface.name)
Key points about the code
allowUids
is the set of app UIDs allowed to use the network.updateConfiguration()
updates the configuration to restrict the network to the provided set of UIDs.