O Android Auto OS 13 e versões mais recentes contêm recursos que permitem configurar e gerenciar redes Ethernet. A Figura 1 mostra um exemplo de diagrama de rede para um automóvel:
Figura 1. Rede do Android Auto.
Essa figura mostra o app de rede do OEM chamando métodos na classe EthernetManager para configurar e gerenciar redes Ethernet integradas (eth0.1, eth0.2 e eth0.3). O restante da Figura 1 está fora do escopo deste documento.
Definir as configurações de rede Ethernet padrão
Para definir as configurações de rede padrão, use a
sobreposição 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>
Este
exemplo mostra a sobreposição de recursos config_ethernet_interfaces de
config.xml.
Principais pontos sobre o código
eth1,eth2eeth3são os nomes da interface de rede que está sendo configurada.- Os números consecutivos de
12, 13, 14, 15representam recursos de rede que estão sendo ativados. ip=,gateway=ednssão usados para definir o endereço IP inicial, o gateway e o DNS da rede.
Ativar ou desativar uma interface de rede
Para ativar uma interface de rede, chame
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);
}
}
Principais pontos sobre o código
ifaceNameé o nome da interface de rede a ser ativada.getMainExecutor()retorna o contexto do app.OutcomeReceiveré um callback usado para comunicar a conclusão, retornando o nome de rede atualizado em caso de sucesso ouEthernetNetworkManagementExceptionem caso de erro.
Quando uma interface de rede é ativada, ela usa a configuração definida por EthernetManager.updateConfiguration(). Se uma configuração não tiver sido definida por EthernetManager.updateConfiguration(), a interface de rede usará a sobreposição de recursos config_ethernet_interfaces ou a configuração de rede Ethernet padrão, se uma sobreposição não estiver disponível.
Para desativar uma interface de rede, chame
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);
}
}
Principais pontos sobre o código
ifaceNameé o nome da interface de rede a ser desativada.getMainExecutor()retorna o contexto do app.OutcomeReceiveré um callback usado para comunicar a conclusão, retornando o nome de rede atualizado em caso de sucesso ouEthernetNetworkManagementExceptionem caso de erro.
Atualizar a configuração de rede
Para atualizar
as configurações de rede Ethernet, chame
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);
}
}
Principais pontos sobre o código
getCapabilities()é um método auxiliar que recebe os recursos de rede atuais e chamaconvertToUIDs()para converter nomes de pacotes legíveis por humanos em identificadores exclusivos (UIDs) do Linux. Normalmente, você não conhece os UIDs com antecedência para os pacotes associados. Portanto, se você quiser usarEthernetManager.updateConfiguration()para limitar o acesso a um subconjunto de apps, será necessário usar os UIDs deles.requesté a configuração a ser usada para a rede interna. A solicitação pode conter uma nova configuração para a configuração de IP e os recursos de rede. Se a rede estiver registrada na pilha de conectividade, ela será atualizada de acordo com a configuração. Essa configuração não persiste nas reinicializações.getMainExecutor()retorna o executor em que o listener é invocado.mCallbacké o callback usado para comunicar a conclusão, retornando o nome de rede atualizado em caso de sucesso ouEthernetNetworkManagementExceptionem caso de erro.
updateConfiguration() pode atualizar características de uma rede considerada imutável pela pilha de conectividade do Android. A rede é desativada, atualizada e reativada para que esses atributos imutáveis sejam atualizados.
Restringir uma rede a um subconjunto de apps
Você pode usar EthernetManager#updateConfiguration para limitar o acesso a apenas um
subconjunto de UIDs permitidos. Use esse método para cobrir casos de uso em que isso é
necessário, como para redes veiculares internas que só podem ser usadas por um pequeno subconjunto
de apps do OEM.
O Android rastreia principalmente os apps pelo UID.
O código a seguir de
UIDToPackageNameConverter.java
mostra como receber uma série de UIDs de uma string de nomes de pacotes:
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;
Principais pontos sobre o código
getApplicationInfoAsuser().uidé usado para recuperar o UID do nome do pacote.uidsé a matriz de números inteiros gerada.
O código a seguir em
EthernetManagerTest.kt
mostra como atualizar a configuração da interface de rede com um UIDs dos apps
permitidos para usar a rede:
val allowedUids = setOf(Process.myUid())
val nc = NetworkCapabilities.Builder(request.networkCapabilities)
.setAllowedUids(allowedUids).build()
updateConfiguration(iface, capabilities = nc).expectResult(iface.name)
Principais pontos sobre o código
allowUidsé o conjunto de UIDs de apps permitidos para usar a rede.updateConfiguration()atualiza a configuração para restringir a rede ao conjunto de UIDs fornecido.