מערכת ההפעלה Android Auto מגרסה 13 ומעלה כוללת תכונות שמאפשרות להגדיר ולנהל רשתות Ethernet. איור 1 מציג תרשים רשת לדוגמה של מכונית:
איור 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()
כדי להגביל את הגישה לקבוצת משנה של אפליקציות, צריך להשתמש במזהי המשתמשים שלהן. -
request
היא ההגדרה שתשמש לרשת הפנימית. הבקשה יכולה להכיל הגדרות חדשות של תצורת ה-IP והיכולות של הרשת. אם הרשת רשומה במערך הקישוריות, היא מתעדכנת בהתאם להגדרה. ההגדרה הזו לא נשמרת אחרי הפעלה מחדש. -
getMainExecutor()
מחזירה את ה-executor שבו מופעל ה-listener. -
mCallback
הוא ה-callback שמשמש לתקשורת של השלמת ההחזרה של שם הרשת המעודכן במקרה של הצלחה אוEthernetNetworkManagementException
במקרה של שגיאה.
יכול להיות ש-updateConfiguration()
יעדכן מאפיינים של רשת שנחשבת לבלתי ניתנת לשינוי על ידי ערימת הקישוריות של Android. כדי לעדכן את המאפיינים הבלתי ניתנים לשינוי האלה, המערכת משביתה את הרשת, מעדכנת אותה ומפעילה אותה מחדש.
הגבלת רשת לקבוצת משנה של אפליקציות
אפשר להשתמש ב-EthernetManager#updateConfiguration
כדי להגביל את הגישה רק לקבוצת משנה של מזהי משתמשים מורשים. אפשר להשתמש בשיטה הזו כדי לכסות תרחישי שימוש שבהם זה נדרש, למשל ברשתות פנימיות של כלי רכב שאפשר להשתמש בהן רק בחלק קטן של אפליקציות 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
היא קבוצת מזהי המשתמש של האפליקציות שמורשות להשתמש ברשת.updateConfiguration()
מעדכן את ההגדרות כדי להגביל את הרשת לקבוצת ה-UID שצוינה.