Android 11 เปิดตัวความสามารถในการใช้ AIDL สำหรับ HAL ใน Android จึงทำให้ ในการนำส่วนต่างๆ ของ Android มาใช้ได้โดยไม่ต้องมี HIDL เปลี่ยน HAL ไปใช้ AIDL เฉพาะในกรณีที่เป็นไปได้เท่านั้น (เมื่อ HAL อัปสตรีมใช้ HIDL จะต้องใช้ HIDL)
HAL ที่ใช้ AIDL เพื่อสื่อสารระหว่างคอมโพเนนต์ของเฟรมเวิร์ก เช่น คอมโพเนนต์ใน
system.img
และคอมโพเนนต์ฮาร์ดแวร์ เช่น คอมโพเนนต์ใน vendor.img
ต้องใช้
AIDL เวอร์ชันเสถียร แต่ในการสื่อสารภายในพาร์ติชัน เช่น จากพาร์ติชัน
HAL กับอีกแบบหนึ่ง ไม่มีข้อจำกัดในการใช้กลไก IPC
แรงจูงใจ
AIDL ใช้งานได้นานกว่า HIDL และมีการใช้งานในที่อื่นๆ อีกมากมาย เช่น ระหว่างคอมโพเนนต์เฟรมเวิร์กของ Android หรือในแอป เมื่อ AIDL มีความเสถียรแล้ว คุณติดตั้งใช้งานทั้งสแต็กได้ด้วยรันไทม์ IPC เดียวได้ นอกจากนี้ AIDL ยังมีระบบการกำหนดเวอร์ชันที่ดีกว่า HIDL อีกด้วย
- การใช้ภาษา IPC เดียวหมายถึงการมีเพียงแค่ 1 สิ่งที่ในการเรียนรู้ แก้ไขข้อบกพร่อง เพิ่มประสิทธิภาพ และรักษาความปลอดภัย
- AIDL รองรับการกำหนดเวอร์ชันในตัวสำหรับเจ้าของอินเทอร์เฟซ ดังนี้
- เจ้าของสามารถเพิ่มเมธอดไว้ที่ส่วนท้ายของอินเทอร์เฟซหรือใส่ฟิลด์ลงในพาร์เซลได้ ซึ่งหมายความว่าการสร้างรหัสเวอร์ชันจะง่ายขึ้นในช่วงหลายปีที่ผ่านมา และ ค่าใช้จ่ายลดลงกว่า (คุณสามารถแก้ไขประเภทต่างๆ ได้ด้วยตนเอง หรือความต้องการไลบรารีเพิ่มเติมสำหรับแต่ละเวอร์ชันอินเทอร์เฟซ)
- อินเทอร์เฟซของส่วนขยายสามารถแนบขณะรันไทม์ได้โดยไม่ต้องอยู่ในประเภท ระบบของคุณ คุณจึงไม่จำเป็นต้องปรับเปลี่ยนฐานของส่วนขยายดาวน์สตรีมไปเป็นเวอร์ชันใหม่ เวอร์ชันอินเทอร์เฟซต่างๆ
- คุณสามารถใช้อินเทอร์เฟซ AIDL ที่มีอยู่ได้โดยตรงเมื่อเจ้าของเลือกที่จะทำ แก้ภาพสั่น ก่อนหน้านี้ สำเนาทั้งหมดของอินเทอร์เฟซจะต้องเป็น ที่สร้างใน HIDL
สร้างเทียบกับรันไทม์ของ AIDL
AIDL มีแบ็กเอนด์ 3 แบบ ได้แก่ Java, NDK และ CPP หากต้องการใช้ AIDL เวอร์ชันเสถียร คุณต้องมีคุณสมบัติดังนี้
ใช้สำเนาของ libbinder เสมอที่ system/lib*/libbinder.so
และ Talk
ในวันที่ /dev/binder
สำหรับโค้ดในรูปภาพของผู้ให้บริการ จะหมายความว่า libbinder
(จาก VNDK) ไม่สามารถใช้ได้: ไลบรารีนี้มี C++ API ที่ไม่เสถียร และ
ที่ไม่เสถียร โค้ดของผู้ให้บริการเนทีฟต้องใช้แบ็กเอนด์ NDK ของ
AIDL ลิงก์กับ libbinder_ndk
(ซึ่งรับการสนับสนุนโดยระบบ libbinder.so
)
และลิงก์กับคลัง NDK ที่สร้างโดย aidl_interface
รายการ สำหรับ
ชื่อโมดูลที่แน่นอน โปรดดู
กฎการตั้งชื่อโมดูล
เขียนอินเทอร์เฟซ AIDL HAL
อินเทอร์เฟซ AIDL ต้องใช้ระหว่างระบบและผู้ให้บริการ การเปลี่ยนแปลง 2 รายการ ได้แก่
- คำจำกัดความประเภททั้งหมดต้องใส่คำอธิบายประกอบด้วย
@VintfStability
- การประกาศ
aidl_interface
ต้องมีstability: "vintf",
เฉพาะเจ้าของอินเทอร์เฟซเท่านั้นที่สามารถทำการเปลี่ยนแปลงเหล่านี้ได้
เมื่อคุณทำการเปลี่ยนแปลงเหล่านี้ อินเทอร์เฟซจะต้องอยู่ใน
ไฟล์ Manifest VINTF เพื่อให้ทำงานได้ ทดสอบฟีเจอร์นี้ (และ
เช่น การยืนยันว่าอินเทอร์เฟซที่เปิดตัวนั้นค้าง) โดยใช้
การทดสอบ VTS vts_treble_vintf_vendor_test
คุณใช้แพ็กเกจ @VintfStability
ได้
อินเทอร์เฟซที่ไม่มีข้อกำหนดเหล่านี้ด้วยการเรียกใช้
AIBinder_forceDowngradeToLocalStability
ในแบ็กเอนด์ NDK
android::Stability::forceDowngradeToLocalStability
ในแบ็กเอนด์ C++
หรือ android.os.Binder#forceDowngradeToSystemStability
ในแบ็กเอนด์ Java
บนออบเจ็กต์ Binder ก่อนที่จะส่งไปยังกระบวนการอื่น การดาวน์เกรดบริการ
ความเสถียรของผู้ให้บริการไม่รองรับใน Java เนื่องจากแอปทั้งหมดทำงานในระบบ
บริบท
นอกจากนี้ เพื่อให้สามารถถ่ายโอนโค้ดได้สูงสุดและเพื่อหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น เป็นไลบรารีเพิ่มเติมที่ไม่จำเป็น ให้ปิดใช้แบ็กเอนด์ CPP
โปรดทราบว่าการใช้ backends
ในตัวอย่างโค้ดด้านล่างถูกต้อง ดังที่เห็น
คือแบ็กเอนด์ 3 แบบ (Java, NDK และ CPP) โค้ดด้านล่างบอกวิธีเลือก
แบ็กเอนด์ CPP โดยเฉพาะเพื่อปิดใช้
aidl_interface: {
...
backends: {
cpp: {
enabled: false,
},
},
}
ค้นหาอินเทอร์เฟซ AIDL HAL
อินเทอร์เฟซ AOSP Stable AIDL สำหรับ HAL อยู่ในไดเรกทอรีพื้นฐานเดียวกันกับ
อินเทอร์เฟซ HIDL ใน aidl
โฟลเดอร์
- ฮาร์ดแวร์/อินเทอร์เฟซ
- เฟรมเวิร์ก/ฮาร์ดแวร์/อินเทอร์เฟซ
- ระบบ/ฮาร์ดแวร์/อินเทอร์เฟซ
คุณควรใส่อินเทอร์เฟซส่วนขยายในhardware/interfaces
อื่นๆ
ไดเรกทอรีย่อยใน vendor
หรือ hardware
อินเทอร์เฟซส่วนขยาย
Android มีชุดอินเทอร์เฟซ AOSP อย่างเป็นทางการในทุกรุ่น เมื่อ Android พาร์ทเนอร์ต้องการเพิ่มฟังก์ชันการทำงานในอินเทอร์เฟซเหล่านี้ ก็ไม่ควรเปลี่ยนแปลง เหล่านี้โดยตรง เนื่องจากรันไทม์ของ Android จะ ใช้ร่วมกับรันไทม์ AOSP สำหรับ Android ไม่ได้ สำหรับอุปกรณ์ GMS คุณไม่ควรเปลี่ยน อินเทอร์เฟซเหล่านี้ยังช่วยให้มั่นใจว่าอิมเมจ GSI จะทำงานต่อไปได้
ส่วนขยายสามารถลงทะเบียนได้ 2 วิธี ดังนี้
- ขณะรันไทม์ โปรดดูส่วนขยายที่แนบมา
- แบบสแตนด์อโลน จดทะเบียนทั่วโลกและใน VINTF
อย่างไรก็ตาม มีการลงทะเบียนส่วนขยายเมื่อเฉพาะผู้ให้บริการ (หมายความว่าไม่ได้เป็นส่วนหนึ่งของ อัปสตรีม AOSP) ใช้อินเทอร์เฟซ ไม่สามารถผสานรวมได้ ความขัดแย้ง อย่างไรก็ตาม เมื่อการปรับเปลี่ยนคอมโพเนนต์ AOSP ต้นทาง เกิด ความขัดแย้ง การรวมอาจทำให้เกิดความขัดแย้งได้ และเราขอแนะนำกลยุทธ์ต่อไปนี้
- คุณสามารถทำให้การเพิ่มอินเทอร์เฟซเป็นอัปสตรีมไปยัง AOSP ในรุ่นถัดไป
- การเพิ่มอินเทอร์เฟซที่ช่วยให้มีความยืดหยุ่นมากขึ้น โดยไม่มีความขัดแย้งในการรวม สามารถอัปสตรีมได้ในรุ่นถัดไป
ส่วนขยายพาร์เซล: ParcelableHolder
ParcelableHolder
เป็น Parcelable
ซึ่งมี Parcelable
อื่นได้
กรณีการใช้งานหลักของ ParcelableHolder
คือการทำให้ Parcelable
ขยายได้
ตัวอย่างเช่น ภาพที่ผู้ใช้อุปกรณ์คาดหวังว่าจะสามารถ
Parcelable
ที่ AOSP กำหนด คือ AospDefinedParcelable
เพื่อรวมการเพิ่มมูลค่า
ใหม่ๆ
ก่อนหน้านี้ไม่มี ParcelableHolder
ผู้ติดตั้งใช้งานอุปกรณ์จะแก้ไขไม่ได้
อินเทอร์เฟซ AIDL เวอร์ชันเสถียรที่ AOSP กำหนด เนื่องจากอาจเป็นข้อผิดพลาดในการเพิ่มอินเทอร์เฟซ
ฟิลด์:
parcelable AospDefinedParcelable {
int a;
String b;
String x; // ERROR: added by a device implementer
int[] y; // added by a device implementer
}
ตามที่เห็นในโค้ดก่อนหน้านี้ ว่าแนวทางปฏิบัตินี้ใช้ไม่ได้เนื่องจากฟิลด์ ที่ผู้ติดตั้งใช้งานอุปกรณ์เพิ่มเข้ามาอาจมีข้อขัดแย้งเมื่อไฟล์พาร์เซลได้ ซึ่งแก้ไขใน Android รุ่นต่อๆ ไป
เมื่อใช้ ParcelableHolder
เจ้าของพัสดุไปรษณีย์จะกำหนดการขยายระยะเวลาได้
Parcelable
parcelable AospDefinedParcelable {
int a;
String b;
ParcelableHolder extension;
}
จากนั้นผู้ใช้อุปกรณ์จะกำหนด Parcelable
ของตนเองสำหรับ
ส่วนขยาย
parcelable OemDefinedParcelable {
String x;
int[] y;
}
สุดท้าย คุณสามารถแนบ Parcelable
ใหม่เข้ากับ Parcelable
เดิมด้วย
ฟิลด์ ParcelableHolder
// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;
ap.extension.setParcelable(op);
...
OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);
// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();
ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);
...
std::shared_ptr<OemDefinedParcelable> op_ptr;
ap.extension.getParcelable(&op_ptr);
// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);
...
std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);
// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });
ap.extension.set_parcelable(Rc::clone(&op));
...
let op = ap.extension.get_parcelable::<OemDefinedParcelable>();
ชื่ออินสแตนซ์ของเซิร์ฟเวอร์ AIDL HAL
ตามหลักแล้ว บริการ AIDL HAL จะมีชื่ออินสแตนซ์ตามรูปแบบ
$package.$type/$instance
ตัวอย่างเช่น ตัวอย่างของ HAL การสั่นคือ
ลงทะเบียนเป็น android.hardware.vibrator.IVibrator/default
เขียนเซิร์ฟเวอร์ AIDL HAL
@VintfStability
ต้องประกาศเซิร์ฟเวอร์ AIDL ในไฟล์ Manifest VINTF สำหรับ
ตัวอย่างเช่น
<hal format="aidl">
<name>android.hardware.vibrator</name>
<version>1</version>
<fqname>IVibrator/default</fqname>
</hal>
ไม่เช่นนั้น ผู้ดูแลระบบควรลงทะเบียนบริการ AIDL ตามปกติ เมื่อเรียกใช้ VTS ฉันคาดว่าจะมี AIDL HAL ที่ประกาศทั้งหมด
เขียนไคลเอ็นต์ AIDL
ไคลเอ็นต์ AIDL ต้องประกาศตนเองในเมทริกซ์ความเข้ากันได้ ตัวอย่างเช่น ดังนี้
<hal format="aidl" optional="true">
<name>android.hardware.vibrator</name>
<version>1-2</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
แปลง HAL ที่มีอยู่จาก HIDL เป็น AIDL
ใช้เครื่องมือ hidl2aidl
เพื่อแปลงอินเทอร์เฟซ HIDL เป็น AIDL
ฟีเจอร์ hidl2aidl
รายการ:
- สร้างไฟล์
.aidl
ไฟล์ตามไฟล์.hal
สำหรับแพ็กเกจที่ระบุ - สร้างกฎการสร้างสำหรับแพ็กเกจ AIDL ที่สร้างขึ้นใหม่พร้อมด้วยแบ็กเอนด์ทั้งหมด เปิดใช้อยู่
- สร้างวิธีการแปลในแบ็กเอนด์ Java, CPP และ NDK สำหรับการแปล จากประเภท HIDL ไปจนถึงประเภท AIDL
- สร้างกฎการสร้างสำหรับไลบรารีการแปลที่มีทรัพยากร Dependency ที่จำเป็น
- สร้างการยืนยันแบบคงที่เพื่อให้แน่ใจว่าตัวระบุ HIDL และ AIDL มี ค่าเดียวกันในแบ็กเอนด์ CPP และ NDK
ทำตามขั้นตอนต่อไปนี้เพื่อแปลงแพ็กเกจไฟล์ .hal เป็นไฟล์ .aidl
สร้างเครื่องมือใน
system/tools/hidl/hidl2aidl
การสร้างเครื่องมือนี้จาก แหล่งข้อมูลล่าสุดทำให้ ประสบการณ์การใช้งาน คุณสามารถใช้เวอร์ชันล่าสุดเพื่อแปลงอินเทอร์เฟซในเวอร์ชันที่เก่ากว่าได้ สาขาจากรุ่นก่อนหน้า
m hidl2aidl
เรียกใช้เครื่องมือด้วยไดเรกทอรีเอาต์พุตตามด้วยแพ็กเกจที่จะใช้ แปลงแล้ว
ใช้อาร์กิวเมนต์
-l
เพื่อเพิ่มเนื้อหาของไฟล์ใบอนุญาตใหม่ (ไม่บังคับ) ไว้ที่ด้านบนของไฟล์ที่สร้างขึ้นทั้งหมด โปรดตรวจสอบว่าใช้ใบอนุญาตและวันที่ที่ถูกต้องhidl2aidl -o <output directory> -l <file with license> <package>
เช่น
hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
อ่านไฟล์ที่สร้างขึ้นทั้งหมดและแก้ไขปัญหาเกี่ยวกับ Conversion
conversion.log
มีปัญหาที่ไม่ได้รับการจัดการที่ต้องแก้ไขก่อน- ไฟล์
.aidl
ที่สร้างขึ้นอาจมีคำเตือนและคำแนะนำที่อาจ จำเป็นต้องดำเนินการ ความคิดเห็นเหล่านี้ขึ้นต้นด้วย//
- ลองใช้โอกาสนี้ล้างข้อมูลและปรับปรุงแพ็กเกจ
- ดู
@JavaDerive
สำหรับฟีเจอร์ที่จำเป็นต้องใช้ เช่นtoString
หรือequals
สร้างเฉพาะเป้าหมายที่คุณต้องการ
- ปิดใช้แบ็กเอนด์ที่จะไม่ใช้ ต้องการใช้แบ็กเอนด์ NDK มากกว่า CPP โปรดดูการเลือกรันไทม์
- นำไลบรารีการแปลภาษาหรือโค้ดที่สร้างขึ้นซึ่งไม่มีการใช้งานออก
ดูความแตกต่างของ AIDL/HIDL ที่สำคัญ
- การใช้
Status
ในตัวของ AIDL และข้อยกเว้นมักจะช่วยปรับปรุง ของอินเทอร์เฟซ และลดความจำเป็นในการดูสถานะเฉพาะอินเทอร์เฟซประเภทอื่น - อาร์กิวเมนต์อินเทอร์เฟซ AIDL ในเมธอดไม่ใช่
@nullable
โดยค่าเริ่มต้นเหมือนอาร์กิวเมนต์ อยู่ในช่วง HIDL
- การใช้
SEPolicy สำหรับ AIDL HAL
ประเภทบริการ AIDL ที่โค้ดผู้ให้บริการมองเห็นได้ต้องมีแอตทริบิวต์
hal_service_type
มิเช่นนั้น การกำหนดค่า Sepolicy จะเหมือนกัน
เช่นเดียวกับบริการ AIDL อื่นๆ (แม้จะมีแอตทริบิวต์พิเศษสำหรับ HAL) ที่นี่
ตัวอย่างคำจำกัดความของบริบทบริการ HAL
type hal_foo_service, service_manager_type, hal_service_type;
สำหรับบริการส่วนใหญ่ที่แพลตฟอร์มเป็นผู้กำหนด คือ บริบทบริการที่มี
มีการเพิ่มประเภท (ตัวอย่างเช่น android.hardware.foo.IFoo/default
จะ
ถูกทำเครื่องหมายเป็น hal_foo_service
อยู่แล้ว) แต่ถ้าลูกค้าเฟรมเวิร์กสนับสนุน
ชื่ออินสแตนซ์หลายรายการ ต้องเพิ่มชื่ออินสแตนซ์เพิ่มเติมใน
service_contexts
ไฟล์เฉพาะอุปกรณ์
android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0
ต้องเพิ่มแอตทริบิวต์ HAL เมื่อเราสร้าง HAL ประเภทใหม่ HAL ที่เฉพาะเจาะจง
อาจเชื่อมโยงกับบริการหลายประเภท (แต่ละประเภทอาจ
ก็มีหลายกรณีเหมือนอย่างที่เพิ่งกล่าวไป) สำหรับ HAL foo
เรามี
hal_attribute(foo)
มาโครนี้กำหนดแอตทริบิวต์ hal_foo_client
และ
hal_foo_server
สำหรับโดเมนที่ระบุ hal_client_domain
และ
มาโคร hal_server_domain
รายการจะเชื่อมโยงโดเมนกับแอตทริบิวต์ HAL ที่ระบุ สำหรับ
เช่น เซิร์ฟเวอร์ระบบที่เป็นไคลเอ็นต์ของ HAL นี้ก็จะสอดคล้องกับนโยบาย
hal_client_domain(system_server, hal_foo)
เซิร์ฟเวอร์ HAL ประกอบด้วย
hal_server_domain(my_hal_domain, hal_foo)
โดยทั่วไปแล้ว สำหรับ HAL ที่ระบุ
เรายังสร้างโดเมนเช่น hal_foo_default
สำหรับการอ้างอิงหรือ
HAL ตัวอย่าง แต่อุปกรณ์บางรุ่นจะใช้โดเมนเหล่านี้เป็นเซิร์ฟเวอร์ของตนเอง
การแยกความแตกต่างระหว่างโดเมนสำหรับเซิร์ฟเวอร์มากกว่า 1 เครื่องมีความสำคัญก็ต่อเมื่อเรามี
เซิร์ฟเวอร์หลายเครื่องที่ทำงานอินเทอร์เฟซเดียวกันและจำเป็นต้องได้รับการอนุญาตที่แตกต่างออกไป
ที่ตั้งไว้ในการติดตั้งใช้งาน ในมาโครเหล่านี้ทั้งหมด hal_foo
ไม่ได้
ออบเจ็กต์ sepolicy แต่มาโครเหล่านี้จะใช้โทเค็นนี้เพื่ออ้างอิง
กลุ่มของแอตทริบิวต์ที่เชื่อมโยงกับคู่เซิร์ฟเวอร์ไคลเอ็นต์
แต่จนถึงตอนนี้เรายังไม่ได้เชื่อมโยง hal_foo_service
กับ hal_foo
(คู่แอตทริบิวต์จาก hal_attribute(foo)
) มีการเชื่อมโยงแอตทริบิวต์ HAL
ร่วมกับบริการ AIDL HAL ที่ใช้มาโคร hal_attribute_service
(HIDL HAL ใช้
มาโคร hal_attribute_hwservice
) ตัวอย่างเช่น
hal_attribute_service(hal_foo, hal_foo_service)
ซึ่งหมายความว่า
hal_foo_client
กระบวนการอาจระงับ HAL และ hal_foo_server
กระบวนการต่างๆ จะลงทะเบียน HAL ได้ การบังคับใช้กฎการลงทะเบียนเหล่านี้คือ
ดำเนินการโดยเครื่องมือจัดการบริบท (servicemanager
) ประกาศ ชื่อบริการอาจ
ไม่สอดคล้องกับแอตทริบิวต์ HAL เสมอไป ตัวอย่างเช่น เราอาจเห็น
hal_attribute_service(hal_foo, hal_foo2_service)
แต่โดยทั่วไป
นั่นหมายความว่าบริการต่างๆ จะมีการใช้งานร่วมกันเสมอ เราอาจพิจารณานำ
hal_foo2_service
และใช้ hal_foo_service
สำหรับบริการทั้งหมดของเรา
บริบทเหล่านี้ HAL ส่วนใหญ่ที่ตั้งค่า hal_attribute_service
หลายตัวเป็นเพราะ
ชื่อแอตทริบิวต์ HAL เดิมไม่กว้างพอและไม่สามารถเปลี่ยนแปลงได้
เมื่อนำทุกอย่างมารวมกัน ตัวอย่าง HAL จะเป็นดังนี้
public/attributes:
// define hal_foo, hal_foo_client, hal_foo_server
hal_attribute(foo)
public/service.te
// define hal_foo_service
type hal_foo_service, hal_service_type, protected_service, service_manager_type
public/hal_foo.te:
// allow binder connection from client to server
binder_call(hal_foo_client, hal_foo_server)
// allow client to find the service, allow server to register the service
hal_attribute_service(hal_foo, hal_foo_service)
// allow binder communication from server to service_manager
binder_use(hal_foo_server)
private/service_contexts:
// bind an AIDL service name to the selinux type
android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0
private/<some_domain>.te:
// let this domain use the hal service
binder_use(some_domain)
hal_client_domain(some_domain, hal_foo)
vendor/<some_hal_server_domain>.te
// let this domain serve the hal service
hal_server_domain(some_hal_server_domain, hal_foo)
อินเทอร์เฟซของส่วนขยายที่แนบ
คุณสามารถแนบส่วนขยายกับอินเทอร์เฟซ Binder ใดก็ได้ ไม่ว่าจะเป็นลิงก์ระดับบนสุด ลงทะเบียนโดยตรงกับผู้ดูแลบริการหรือเป็นอินเทอร์เฟซย่อย ในการรับส่วนขยาย คุณต้องยืนยันประเภทของส่วนขยาย ที่คาดไว้ ตั้งค่าส่วนขยายได้จากกระบวนการที่แสดงไฟล์ Binder เท่านั้น
ควรใช้ส่วนขยายที่แนบมาเมื่อใดก็ตามที่ส่วนขยายแก้ไข ของ HAL ที่มีอยู่ เมื่อจำเป็นต้องใช้ฟังก์ชันใหม่ทั้งหมด กลไกนี้โดยไม่ต้องใช้กลไกนี้ และอินเทอร์เฟซส่วนขยายสามารถ จดทะเบียนกับผู้ดูแลบริการโดยตรง อินเทอร์เฟซของส่วนขยายที่แนบ ก็จะเหมาะสมที่สุดเมื่อวางไว้บนอินเทอร์เฟซย่อย เพราะว่า ลำดับชั้นอาจเป็นแบบลึกหรือหลายอินสแตนซ์ การใช้ส่วนขยายส่วนกลางเพื่อมิเรอร์ ลำดับชั้นอินเทอร์เฟซ Binder ของบริการอื่นจะต้องครอบคลุม บริการทำบัญชีเพื่อมอบฟังก์ชันการทำงานเทียบเท่ากับส่วนขยายที่แนบโดยตรง
หากต้องการตั้งค่าส่วนขยายใน Binder ให้ใช้ API ต่อไปนี้
- ในแบ็กเอนด์ NDK:
AIBinder_setExtension
- ในแบ็กเอนด์ Java:
android.os.Binder.setExtension
- ในแบ็กเอนด์ CPP:
android::Binder::setExtension
- ในแบ็กเอนด์ Rust:
binder::Binder::set_extension
หากต้องการรับส่วนขยายใน Binder ให้ใช้ API ต่อไปนี้
- ในแบ็กเอนด์ NDK:
AIBinder_getExtension
- ในแบ็กเอนด์ Java:
android.os.IBinder.getExtension
- ในแบ็กเอนด์ CPP:
android::IBinder::getExtension
- ในแบ็กเอนด์ Rust:
binder::Binder::get_extension
คุณดูข้อมูลเพิ่มเติมสำหรับ API เหล่านี้ได้ในเอกสารประกอบของ
getExtension
ในแบ็กเอนด์ที่เกี่ยวข้อง ตัวอย่างวิธีใช้
จะสามารถพบส่วนขยายใน
ฮาร์ดแวร์/อินเทอร์เฟซ/การทดสอบ/ส่วนขยาย/การสั่น
ความแตกต่างของ AIDL และ HIDL ที่สำคัญ
โปรดคำนึงถึงความแตกต่างเมื่อใช้ AIDL HAL หรือใช้อินเทอร์เฟซ AIDL HAL เมื่อเทียบกับการเขียน HIDL HAL
- ไวยากรณ์ของภาษา AIDL มีความใกล้เคียงกับ Java มากกว่า ไวยากรณ์ HIDL คล้ายกับ C++
- อินเทอร์เฟซ AIDL ทั้งหมดมีสถานะข้อผิดพลาดในตัว แทนที่จะสร้างแบบกำหนดเอง
ประเภทสถานะ สร้างจำนวนเต็มคงที่ในไฟล์อินเทอร์เฟซและใช้
EX_SERVICE_SPECIFIC
ในแบ็กเอนด์ CPP/NDK และServiceSpecificException
ในแบ็กเอนด์ Java ดูข้อผิดพลาด การใช้งาน - AIDL จะไม่เริ่มต้น Threadpool โดยอัตโนมัติเมื่อส่งออบเจ็กต์ Binder ซึ่งต้องเริ่มต้นด้วยตนเอง (โปรดดู ชุดข้อความ การจัดการ)
- AIDL ไม่ได้ล้มเลิกข้อผิดพลาดในการรับส่งที่ไม่ได้ตรวจสอบ (HIDL
Return
ล้มเลิกเมื่อ ข้อผิดพลาดที่ไม่ได้ตรวจสอบ) - AIDL ประกาศได้เพียง 1 ประเภทต่อไฟล์เท่านั้น
- อาร์กิวเมนต์ AIDL สามารถระบุเป็นเข้า/ออก/เข้า นอกเหนือจากเอาต์พุตได้ (ไม่มี "การติดต่อกลับแบบซิงโครนัส")
- AIDL ใช้ fd เป็นประเภทดั้งเดิมแทนแฮนเดิล
- HIDL ใช้เวอร์ชันหลักสำหรับการเปลี่ยนแปลงที่เข้ากันไม่ได้และเวอร์ชันย่อยสำหรับ
การเปลี่ยนแปลงที่เข้ากันได้ ระบบดำเนินการเปลี่ยนแปลงที่เข้ากันได้แบบย้อนหลังใน AIDL
AIDL ไม่มีแนวคิดที่ชัดเจนเกี่ยวกับเวอร์ชันหลัก แต่เป็น
รวมอยู่ในชื่อแพ็กเกจ เช่น AIDL อาจใช้ชื่อแพ็กเกจ
bluetooth2
- AIDL จะไม่รับค่าลำดับความสำคัญแบบเรียลไทม์โดยค่าเริ่มต้น
setInheritRt
ต้องใช้ต่อไฟล์ต่อไฟล์เพื่อเปิดใช้การรับค่าลำดับความสำคัญแบบเรียลไทม์