El SO Android Auto 13 y versiones posteriores contiene funciones que te permiten configurar y administrar redes Ethernet. En la Figura 1, se muestra un ejemplo de diagrama de red para un automóvil:
Figura 1: Redes de Android Auto
En esta imagen, se muestra la app de redes del OEM que llama a métodos en la clase EthernetManager
para configurar y administrar redes Ethernet integradas (eth0.1, eth0.2 y eth0.3). El resto de la Figura 1 está fuera del alcance de este documento.
Establece la configuración de red Ethernet predeterminada
Para establecer la configuración de red predeterminada, usa la superposición de recursos
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>
En este
ejemplo, se muestra la superposición de recursos config_ethernet_interfaces
de
config.xml
.
Puntos clave sobre el código
eth1
,eth2
yeth3
son los nombres de la interfaz de red que se está configurando.- Los números consecutivos de
12, 13, 14, 15
representan las funciones de red que se habilitan. ip=
,gateway=
ydns
se usan para establecer la dirección IP, la puerta de enlace y el DNS iniciales de la red.
Habilita o inhabilita una interfaz de red
Para habilitar una interfaz de red, llama a 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);
}
}
Puntos clave sobre el código
ifaceName
es el nombre de la interfaz de red que se habilitará.getMainExecutor()
muestra el contexto de la app.OutcomeReceiver
es una devolución de llamada que se usa para comunicar la finalización y muestra el nombre de red actualizado si se realiza correctamente oEthernetNetworkManagementException
si se produce un error.
Cuando se habilita una interfaz de red, usa la configuración que estableció EthernetManager.updateConfiguration()
. Si EthernetManager.updateConfiguration()
no configuró una configuración, la interfaz de red usa la superposición de recursos config_ethernet_interfaces
o la configuración predeterminada de la red Ethernet si no hay una superposición disponible.
Para inhabilitar una interfaz de red, llama a 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);
}
}
Puntos clave sobre el código
ifaceName
es el nombre de la interfaz de red que se inhabilitará.getMainExecutor()
muestra el contexto de la app.OutcomeReceiver
es una devolución de llamada que se usa para comunicar la finalización y muestra el nombre de la red actualizado si se realiza correctamente oEthernetNetworkManagementException
si se produce un error.
Actualiza la configuración de red
Para actualizar la configuración de la red Ethernet, llama a 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);
}
}
Puntos clave sobre el código
getCapabilities()
es un método auxiliar que obtiene las capacidades de red actuales y llama aconvertToUIDs()
para convertir los nombres de paquetes legibles por humanos en un identificador único (UID) de Linux. Por lo general, no conoces los UIDs con anticipación para sus paquetes asociados. Por lo tanto, si deseas usarEthernetManager.updateConfiguration()
para limitar el acceso a un subconjunto de apps, debes usar sus UIDs.request
es la configuración que se usará para la red interna. La solicitud puede contener una configuración nueva para la configuración de IP y las capacidades de red. Si la red está registrada en la pila de conectividad, se actualiza según la configuración. Esta configuración no persiste en los reinicios.getMainExecutor()
muestra el ejecutor en el que se invoca el objeto de escucha.mCallback
es la devolución de llamada que se usa para comunicar la finalización y muestra el nombre de red actualizado si se realiza correctamente oEthernetNetworkManagementException
si se produce un error.
updateConfiguration()
podría actualizar las características de una red que la pila de conectividad de Android considera inmutable. La red se baja, se actualiza y se vuelve a subir para que se actualicen estos atributos inmutables.
Cómo restringir una red a un subconjunto de apps
Puedes usar EthernetManager#updateConfiguration
para limitar el acceso solo a un subconjunto de UIDs permitidos. Usa este método para cubrir los casos de uso en los que esto es obligatorio, como en el caso de las redes vehiculares internas que solo puede usar un subconjunto pequeño de apps de OEM.
Android realiza un seguimiento de las apps principalmente por su UID.
En el siguiente código de UIDToPackageNameConverter.java
, se muestra cómo obtener una serie de UIDs a partir de una cadena de nombres de paquetes:
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;
Puntos clave sobre el código
getApplicationInfoAsuser().uid
se usa para recuperar el UID del nombre del paquete.uids
es el array de números enteros generado.
En el siguiente código de EthernetManagerTest.kt
, se muestra cómo actualizar la configuración de la interfaz de red con un UID de las apps que pueden usar la red:
val allowedUids = setOf(Process.myUid())
val nc = NetworkCapabilities.Builder(request.networkCapabilities)
.setAllowedUids(allowedUids).build()
updateConfiguration(iface, capabilities = nc).expectResult(iface.name)
Puntos clave sobre el código
allowUids
es el conjunto de UIDs de apps que pueden usar la red.updateConfiguration()
actualiza la configuración para restringir la red al conjunto de UIDs proporcionado.