กำหนดค่าเครือข่ายอีเทอร์เน็ตภายใน

Android Auto OS 13 ขึ้นไปมีฟีเจอร์ที่ช่วยให้คุณกำหนดค่าและจัดการเครือข่ายอีเทอร์เน็ตได้ รูปที่ 1 แสดงตัวอย่างผังเครือข่ายสําหรับยานยนต์

เครือข่าย Android Auto

รูปที่ 1 เครือข่าย Android Auto

รูปภาพนี้แสดงแอปการทํางานของเครือข่าย OEM ที่เรียกใช้เมธอดในคลาส EthernetManager เพื่อกําหนดค่าและจัดการเครือข่ายอีเทอร์เน็ตบนเครื่อง (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() จะแสดงผลตัวดำเนินการที่เรียกใช้ตัวฟัง
  • 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 ที่ระบุ