Định cấu hình mạng Ethernet nội bộ

Android Auto OS 13 trở lên có các tính năng cho phép bạn định cấu hình và quản lý mạng Ethernet. Hình 1 minh hoạ sơ đồ mạng cho một ô tô:

Kết nối mạng Android Auto

Hình 1. Kết nối mạng Android Auto.

Hình này cho thấy các phương thức gọi ứng dụng mạng của OEM trong lớp EthernetManager để định cấu hình và quản lý các mạng Ethernet trên bo mạch (eth0.1, eth0.2 và eth0.3). Phần còn lại của Hình 1 nằm ngoài phạm vi của tài liệu này.

Đặt chế độ cài đặt mạng Ethernet mặc định

Để đặt chế độ cài đặt mạng mặc định, hãy dùng lớp phủ tài nguyên 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>

Ví dụ này cho thấy lớp phủ tài nguyên config_ethernet_interfaces từ config.xml.

Các điểm chính về mã

  • eth1, eth2eth3 là tên của giao diện mạng đang được định cấu hình.
  • Các số liên tiếp của 12, 13, 14, 15 biểu thị các chức năng mạng đang được bật.
  • ip=, gateway=dns được dùng để đặt địa chỉ IP, cổng và DNS ban đầu cho mạng.

Bật hoặc tắt giao diện mạng

Để bật một giao diện mạng, hãy gọi 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);
    }
}

Các điểm chính về mã

  • ifaceName là tên của giao diện mạng cần bật.
  • getMainExecutor() trả về ngữ cảnh ứng dụng.
  • OutcomeReceiver là một lệnh gọi lại được dùng để thông báo hoàn tất, trả về tên mạng đã cập nhật khi thành công hoặc EthernetNetworkManagementException khi gặp lỗi.

Khi một giao diện mạng được bật, giao diện đó sẽ sử dụng cấu hình do EthernetManager.updateConfiguration() đặt. Nếu EthernetManager.updateConfiguration() chưa đặt cấu hình, thì giao diện mạng sẽ sử dụng lớp phủ tài nguyên config_ethernet_interfaces hoặc cấu hình mạng Ethernet mặc định nếu không có lớp phủ.

Để tắt một giao diện mạng, hãy gọi 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);
    }
}

Các điểm chính về mã

  • ifaceName là tên của giao diện mạng cần tắt.
  • getMainExecutor() trả về ngữ cảnh ứng dụng.
  • OutcomeReceiver là một lệnh gọi lại được dùng để thông báo hoàn tất, trả về tên mạng đã cập nhật khi thành công hoặc EthernetNetworkManagementException khi gặp lỗi.

Cập nhật cấu hình mạng

Để cập nhật cấu hình mạng Ethernet, hãy gọi 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);

    }
}

Các điểm chính về mã

  • getCapabilities() là một phương thức trợ giúp lấy các chức năng mạng hiện tại và gọi convertToUIDs() để chuyển đổi tên gói mà con người có thể đọc được thành giá trị nhận dạng duy nhất (UID) của Linux. Thông thường, bạn không biết trước UID cho các gói được liên kết. Do đó, nếu muốn sử dụng EthernetManager.updateConfiguration() để hạn chế quyền truy cập vào một nhóm nhỏ ứng dụng, bạn cần sử dụng UID của các ứng dụng đó.
  • request là cấu hình sẽ được dùng cho mạng nội bộ. Yêu cầu có thể chứa chế độ cài đặt mới cho cấu hình IP và các chức năng mạng. Nếu mạng được đăng ký với ngăn xếp kết nối, thì mạng đó sẽ được cập nhật theo cấu hình. Cấu hình này không được duy trì sau khi khởi động lại.
  • getMainExecutor() trả về trình thực thi mà trình nghe được gọi.
  • mCallback là lệnh gọi lại dùng để truyền đạt trạng thái hoàn tất, trả về tên mạng đã cập nhật khi thành công hoặc EthernetNetworkManagementException khi có lỗi.

updateConfiguration() có thể cập nhật các đặc điểm của một mạng được ngăn xếp Kết nối Android coi là bất biến. Mạng này sẽ ngừng hoạt động, được cập nhật rồi hoạt động trở lại để những thuộc tính không thay đổi này được cập nhật.

Hạn chế một mạng đối với một nhóm nhỏ ứng dụng

Bạn có thể sử dụng EthernetManager#updateConfiguration để giới hạn quyền truy cập chỉ cho một nhóm nhỏ UID được phép. Sử dụng phương thức này để bao gồm các trường hợp sử dụng bắt buộc, chẳng hạn như đối với các mạng nội bộ trên xe chỉ có thể sử dụng bởi một nhóm nhỏ các ứng dụng OEM.

Android chủ yếu theo dõi các ứng dụng theo UID của chúng. Đoạn mã sau đây trong UIDToPackageNameConverter.java cho biết cách lấy một loạt UID từ chuỗi tên gói:

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;

Các điểm chính về mã

  • getApplicationInfoAsuser().uid được dùng để truy xuất UID từ tên gói.
  • uids là mảng số nguyên được tạo.

Đoạn mã sau đây trong EthernetManagerTest.kt cho biết cách cập nhật cấu hình giao diện mạng bằng UID của các ứng dụng được phép sử dụng mạng:

val allowedUids = setOf(Process.myUid())
        val nc = NetworkCapabilities.Builder(request.networkCapabilities)
                .setAllowedUids(allowedUids).build()
        updateConfiguration(iface, capabilities = nc).expectResult(iface.name)

Các điểm chính về mã

  • allowUids là tập hợp các UID ứng dụng được phép sử dụng mạng.
  • updateConfiguration() cập nhật cấu hình để hạn chế mạng đối với nhóm UID được cung cấp.