הגדרת רשתות אתרנט פנימיות

מערכת Android Auto OS בגרסה 13 ואילך כוללת תכונות שמאפשרות להגדיר ולנהל רשתות אתרנט. איור 1 מציג רשת לדוגמה של כלי רכב:

רשתות של Android Auto

איור 1. רשת של Android Auto.

באיור הזה מוצגות השיטות לשיחות באפליקציית הרשת של ה-OEM (יצרן הציוד המקורי) מחלקה אחת (EthernetManager) להגדרה ולניהול של רשתות Ethernet הקיימות (eth0.1, eth0.2 ו-eth0.3). שאר איור 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_ethernet_interfaces config.xml.

נקודות עיקריות לגבי הקוד

  • 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 הוא קריאה חוזרת (callback) שמשמשת לדיווח על השלמה של עודכן בשם הרשת בהצלחה, או 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 הוא קריאה חוזרת (callback) שמשמשת לדיווח על השלמה של עודכן בשם הרשת בהצלחה, או 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() להמרה שמות חבילות קריאים לאנשים למזהה ייחודי (UID) של Linux. בדרך כלל, הם לא מכירים את מזהי UID מראש את החבילות שמשויכות אליהן. לכן, אם רוצים להשתמש EthernetManager.updateConfiguration() כדי להגביל את הגישה לקבוצת משנה של אפליקציות, אפשר צריכים להשתמש ב-UID שלהם.
  • request היא ההגדרה שתשמש לרשת הפנימית. הבקשה יכולה להכיל הגדרות חדשות לתצורת ה-IP ולרשת יכולות. אם רשומה במקבץ הקישוריות, היא מתעדכנת בהתאם הגדרה אישית. ההגדרה הזו לא נשמרת בכל הפעלות מחדש.
  • getMainExecutor() מחזיר את האופרטור שממנו מופעל ה-listen.
  • mCallback הוא הקריאה החוזרת (callback) שמשמשת לדיווח על השלמה של עודכן בשם הרשת בהצלחה, או 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 שיש לך.