Configurar redes Ethernet internas

El SO Android Auto 13 y las versiones posteriores incluyen funciones que te permiten hacer lo siguiente: configurar y administrar redes Ethernet. En la Figura 1, se muestra un ejemplo de red diagrama de un automóvil:

Herramientas de redes de Android Auto

Figura 1: Herramientas de redes de Android Auto

En esta figura, se muestran los métodos de llamada de tu app de red de OEM 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 este documento.

Establece la configuración predeterminada de la red Ethernet

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>

Esta En este ejemplo, se muestra la superposición de recursos config_ethernet_interfaces de config.xml

Puntos clave sobre el código

  • eth1, eth2 y eth3 son los nombres de la interfaz de red que se configura.
  • Las cantidades consecutivas de 12, 13, 14, 15 representan red capacidades que se está habilitando.
  • ip=, gateway= y dns se usan para establecer la dirección IP inicial, la puerta de enlace, y DNS para la red.

Cómo habilitar o inhabilitar 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 que devuelve el Se actualizó el nombre de la red si la operación es correcta o EthernetNetworkManagementException el .

Cuando se habilita una interfaz de red, usa la configuración establecida por EthernetManager.updateConfiguration() Si no se estableció una configuración por EthernetManager.updateConfiguration(), la interfaz de red usa el superposición de recursos config_ethernet_interfaces o la red Ethernet predeterminada actual si una superposición no está 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 que devuelve el Se actualizó el nombre de la red si la operación es correcta o EthernetNetworkManagementException el .

Actualiza la configuración de red

Para actualizar configuraciones de redes Ethernet, llamar 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 el nombre de la red y llama a convertToUIDs() para convertir nombres de paquetes legibles por humanos al identificador único (UID) de Linux. Por lo general, no conoce los UIDs por adelantado para sus paquetes asociados. Por lo tanto, si quieres usar EthernetManager.updateConfiguration() para limitar el acceso a un subconjunto de apps, necesitan usar sus UIDs.
  • request es la configuración que se usará para la red interna. El puede contener una configuración nueva para la configuración de IP y la red capacidades de integración. Si el botón red se registra con la pila de conectividad, se actualiza según el configuración. Esta configuración no se mantiene después de 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 que devuelve el Se actualizó el nombre de la red si la operación es correcta o EthernetNetworkManagementException el .

updateConfiguration() podría actualizar características de una red considerada inmutable para la pila de Android Connectivity. El se desactiva, se actualiza y se vuelve a activar para estos servicios atributos que se actualizarán.

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 abarcar casos de uso en los que sea necesarios, por ejemplo, para redes vehiculares internas que solo pueden usar un pequeño subconjunto de apps de OEM.

Android realiza principalmente un seguimiento de las apps por su UID. El siguiente código de UIDToPackageNameConverter.java 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 objeto de escucha nombre del paquete.
  • uids es el array de números enteros que se genera.

El siguiente código en EthernetManagerTest.kt se muestra cómo actualizar la configuración de la interfaz de red con un UID de las apps 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)

donde:

  • allowUids es el conjunto de UIDs de apps que pueden usar la red.
  • updateConfiguration() actualiza la configuración para restringir la red a el conjunto de UID proporcionado.