הגדרת רשתות Ethernet פנימיות

מערכת ההפעלה Android Auto מגרסה 13 ומעלה כוללת תכונות שמאפשרות להגדיר ולנהל רשתות Ethernet. איור 1 מציג תרשים רשת לדוגמה של מכונית:

חיבור לרשת ב-Android Auto

איור 1. רשתות ב-Android Auto.

באיור הזה מוצגות שיטות להפעלת אפליקציית רשת של יצרן ציוד מקורי (OEM) במחלקה EthernetManager כדי להגדיר ולנהל רשתות Ethernet מובנות (eth0.1,‏ eth0.2 ו-eth0.3). שאר התרשים באיור 1 לא רלוונטי למסמך הזה.

קביעת הגדרות ברירת המחדל של רשת Ethernet

כדי להגדיר את הגדרות הרשת כברירת מחדל, משתמשים בשכבת-על של משאבים 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.

עדכון הגדרת הרשת

כדי לעדכן את ההגדרות של רשת Ethernet, צריך להתקשר אל 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() מחזירה את ה-executor שבו מופעל ה-listener.
  • 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 שצוינה.