Android Auto OS 13 以降には、イーサネット ネットワークの設定、管理を行える機能が含まれています。図 1 に、自動車のネットワーク図の例を示します。
図 1. Android Auto のネットワーキング。
この図は、EthernetManager
クラスのメソッドを呼び出してオンボードのイーサネット ネットワーク(eth0.1、eth0.2、eth0.3)の設定、管理を行う OEM ネットワーキング アプリを示しています。図 1 のその他の部分はこのドキュメントの対象外です。
デフォルトのイーサネット ネットワークを設定する
デフォルトのネットワークを設定するには、リソース オーバーレイ 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>
この例は、config.xml
からのリソース オーバーレイ config_ethernet_interfaces
を示しています。
コードに関する主なポイント
eth1
、eth2
、eth3
は、設定するネットワーク インターフェースの名前です。- 連続する
12, 13, 14, 15
という数字は、有効にするネットワーク機能を表します。 ip=
、gateway=
、dns
は、ネットワークの初期 IP アドレス、ゲートウェイ、DNS の設定に使用します。
ネットワーク インターフェースを有効 / 無効にする
ネットワーク インターフェースを有効にするには、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);
}
}
コードに関する主なポイント
ifaceName
は、有効にするネットワーク インターフェースの名前です。getMainExecutor()
は、アプリ コンテキストを返します。OutcomeReceiver
は、完了を伝えるために使うコールバックで、成功した場合は更新されたネットワークの名前、エラーの場合はEthernetNetworkManagementException
を返します。
ネットワーク インターフェースは、有効になると、EthernetManager.updateConfiguration()
によって設定された構成を使用します。EthernetManager.updateConfiguration()
によって構成が設定されていない場合は、リソース オーバーレイ config_ethernet_interfaces
、またはオーバーレイが利用できない場合はデフォルトのイーサネット ネットワーク構成を使用します。
ネットワーク インターフェースを無効にするには、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);
}
}
コードに関する主なポイント
ifaceName
は、無効にするネットワーク インターフェースの名前です。getMainExecutor()
は、アプリ コンテキストを返します。OutcomeReceiver
は、完了を伝えるために使うコールバックで、成功した場合は更新されたネットワークの名前、エラーの場合はEthernetNetworkManagementException
を返します。
ネットワークの構成を更新する
イーサネット ネットワークの構成を更新するには、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);
}
}
コードに関する主なポイント
getCapabilities()
はヘルパー メソッドで、現在のネットワーク機能を取得し、convertToUIDs()
を呼び出して、人が読めるパッケージ名を Linux の固有識別子(UID)に変換します。一般に、関連付けられたパッケージの UID は事前にわからないため、EthernetManager.updateConfiguration()
を使用してアプリの一部にアクセス権を制限したい場合は、該当するアプリの UID を使用する必要があります。request
は、車内ネットワークに使用する構成です。リクエストには、IP 構成とネットワーク機能の新しい設定を含めることができます。ネットワークが接続スタックに登録されている場合は、構成に基づいて更新されます。この構成は再起動後は保持されません。getMainExecutor()
は、リスナーが呼び出されるエグゼキュータを返します。mCallback
は、完了を伝えるために使うコールバックで、成功した場合は更新されたネットワークの名前、エラーの場合はEthernetNetworkManagementException
を返します。
updateConfiguration()
は、Android 接続スタックでは不変と見なされるネットワークの特性を更新することがあります。ネットワークが停止し、更新され、再起動して、これらの不変の属性が更新されます。
ネットワークを一部のアプリに制限する
EthernetManager#updateConfiguration
を使用して、一部の許可された UID のみにアクセス権を制限することができます。この方法を使って、少数の OEM アプリにのみ車内ネットワークの使用を認める場合など、制限を必要とするユースケースに対応できます。
Android は主に UID でアプリを追跡します。UIDToPackageNameConverter.java
の以下のコードは、パッケージ名の文字列から一連の UID を取得する方法を示しています。
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;
コードに関する主なポイント
getApplicationInfoAsuser().uid
は、パッケージ名から UID を取得する場合に使用します。uids
は、整数の生成された配列です。
EthernetManagerTest.kt
の以下のコードは、ネットワークの使用が許可されたアプリの UID でネットワーク インターフェースの構成を更新する方法を示しています。
val allowedUids = setOf(Process.myUid())
val nc = NetworkCapabilities.Builder(request.networkCapabilities)
.setAllowedUids(allowedUids).build()
updateConfiguration(iface, capabilities = nc).expectResult(iface.name)
コードに関する主なポイント
allowUids
は、ネットワークの使用が許可された一連のアプリの UID です。updateConfiguration()
は、指定された一連の UID にネットワークを制限するよう構成を更新します。