HIDL สร้างขึ้นจากอินเทอร์เฟซ ซึ่งเป็นประเภทนามธรรมที่ใช้ในภาษาเชิงวัตถุเพื่อกำหนดพฤติกรรม แต่ละอินเทอร์เฟซเป็นส่วนหนึ่งของแพ็คเกจ
แพ็คเกจ
ชื่อแพ็กเกจสามารถมีระดับย่อยได้ เช่น package.subpackage
ไดเร็กทอรีรากสำหรับแพ็คเกจ HIDL ที่เผยแพร่คือ hardware/interfaces
หรือ vendor/vendorName
(เช่น vendor/google
สำหรับอุปกรณ์ Pixel) ชื่อแพ็กเกจจะสร้างไดเร็กทอรีย่อยตั้งแต่หนึ่งไดเร็กทอรีขึ้นไปภายใต้ไดเร็กทอรีราก ไฟล์ทั้งหมดที่กำหนดแพ็คเกจอยู่ในไดเร็กทอรีเดียวกัน ตัวอย่างเช่น package android.hardware.example.extension.light@2.0
สามารถพบได้ภายใต้ hardware/interfaces/example/extension/light/2.0
ตารางต่อไปนี้แสดงรายการคำนำหน้าแพ็คเกจและที่ตั้ง:
คำนำหน้าแพ็คเกจ | ที่ตั้ง | ประเภทอินเทอร์เฟซ |
---|---|---|
android.hardware.* | hardware/interfaces/* | ฮาล |
android.frameworks.* | frameworks/hardware/interfaces/* | กรอบ/ที่เกี่ยวข้อง |
android.system.* | system/hardware/interfaces/* | ระบบ/ที่เกี่ยวข้อง |
android.hidl.* | system/libhidl/transport/* | แกนกลาง |
ไดเร็กทอรีแพ็กเกจประกอบด้วยไฟล์ที่มีนามสกุล .hal
ทุกไฟล์จะต้องมีคำสั่ง package
ที่ตั้งชื่อแพ็คเกจและเวอร์ชันของไฟล์นั้น ไฟล์ types.hal
(หากมี) ไม่ได้กำหนดอินเทอร์เฟซ แต่กำหนดประเภทข้อมูลที่สามารถเข้าถึงได้จากทุกอินเทอร์เฟซในแพ็คเกจแทน
คำจำกัดความของอินเทอร์เฟซ
นอกเหนือจาก types.hal
แล้ว ไฟล์ .hal
อื่นๆ ทุกไฟล์ยังกำหนดอินเทอร์เฟซอีกด้วย โดยทั่วไปอินเทอร์เฟซจะถูกกำหนดดังนี้:
interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/}; // interface methods create(int32_t id) generates (MyStruct s); close(); };
อินเทอร์เฟซที่ไม่มีการประกาศ extends
อย่างชัดเจนจะขยายโดยปริยายจาก android.hidl.base@1.0::IBase
(คล้ายกับ java.lang.Object
ใน Java) อินเทอร์เฟซ IBase ซึ่งนำเข้าโดยปริยาย จะประกาศวิธีที่สงวนไว้หลายวิธีที่ไม่ควรและไม่สามารถประกาศซ้ำได้ ในอินเทอร์เฟซที่ผู้ใช้กำหนดหรือใช้อย่างอื่น วิธีการเหล่านี้ได้แก่:
-
ping
-
interfaceChain
-
interfaceDescriptor
-
notifySyspropsChanged
-
linkToDeath
-
unlinkToDeath
-
setHALInstrumentation
-
getDebugInfo
-
debug
-
getHashChain
กำลังนำเข้า
คำสั่ง import
เป็นกลไก HIDL เพื่อเข้าถึงอินเทอร์เฟซแพ็คเกจและประเภทในแพ็คเกจอื่น คำชี้แจง import
เกี่ยวข้องกับสองเอนทิตี:
- เอนทิตี การนำ เข้าซึ่งอาจเป็นได้ทั้งแพ็คเกจหรืออินเทอร์เฟซ และ
- เอนทิตี ed ที่นำเข้า ซึ่งอาจเป็นได้ทั้งแพ็คเกจหรืออินเทอร์เฟซก็ได้
เอนทิตีการนำเข้าถูกกำหนดโดยตำแหน่งที่ตั้งของใบแจ้งยอด import
เมื่อคำสั่งอยู่ในแพ็คเกจ types.hal
สิ่งที่กำลังนำเข้าจะมองเห็นได้จากแพ็คเกจทั้งหมด นี่คือการนำเข้า ระดับแพ็คเกจ เมื่อคำสั่งอยู่ในไฟล์อินเทอร์เฟซ เอนทิตีที่นำเข้าจะเป็นอินเทอร์เฟซนั้นเอง นี่คือการนำเข้า ระดับอินเทอร์เฟ ซ
เอนทิตีที่นำเข้าถูกกำหนดโดยค่าหลังคำสำคัญ import
ค่าไม่จำเป็นต้องเป็นชื่อที่มีคุณสมบัติครบถ้วน หากละเว้นส่วนประกอบ ส่วนประกอบนั้นจะถูกเติมด้วยข้อมูลจากแพ็คเกจปัจจุบันโดยอัตโนมัติ สำหรับค่าที่มีคุณสมบัติครบถ้วน รองรับกรณีการนำเข้าต่อไปนี้:
- นำเข้าทั้งชุด . หากค่าเป็นชื่อแพ็คเกจและเวอร์ชัน (ไวยากรณ์ที่อธิบายด้านล่าง) แพ็คเกจทั้งหมดจะถูกนำเข้าไปยังเอนทิตีการนำเข้า
- การนำเข้าบางส่วน . หากค่าเป็น:
- อินเทอร์เฟซ
types.hal
ของแพ็คเกจ และอินเทอร์เฟซนั้นจะถูกนำเข้าไปยังเอนทิตีการนำเข้า - UDT ที่กำหนดใน
types.hal
จากนั้นเฉพาะ UDT เท่านั้นที่จะถูกนำเข้าไปยังเอนทิตีการนำเข้า (ประเภทอื่นในtypes.hal
จะไม่ถูกนำเข้า)
- อินเทอร์เฟซ
- การนำเข้าเฉพาะประเภท หากค่าใช้ไวยากรณ์ของการนำเข้าบางส่วนที่อธิบายไว้ข้างต้น แต่ใช้
types
คีย์เวิร์ดแทนชื่ออินเทอร์เฟซ เฉพาะ UDT ในtypes.hal
ของแพ็คเกจที่กำหนดเท่านั้นที่จะถูกนำเข้า
เอนทิตีผู้นำเข้าจะสามารถเข้าถึงชุดค่าผสมของ:
- UDT ทั่วไปของแพ็คเกจที่นำเข้าซึ่งกำหนดใน
types.hal
; - อินเทอร์เฟซของแพ็คเกจที่นำเข้า (สำหรับการนำเข้าทั้งแพ็คเกจ) หรืออินเทอร์เฟซที่ระบุ (สำหรับการนำเข้าบางส่วน) เพื่อวัตถุประสงค์ในการเรียกใช้ ส่งต่อการจัดการไปยังแพ็คเกจเหล่านั้น และ/หรือสืบทอดจากแพ็คเกจเหล่านั้น
คำสั่งนำเข้าใช้ไวยากรณ์ชื่อประเภทที่มีคุณสมบัติครบถ้วนเพื่อจัดเตรียมชื่อและเวอร์ชันของแพ็คเกจหรืออินเทอร์เฟซที่กำลังนำเข้า:
import android.hardware.nfc@1.0; // import a whole package import android.hardware.example@1.0::IQuux; // import an interface and types.hal import android.hardware.example@1.0::types; // import just types.hal
การสืบทอดอินเทอร์เฟซ
อินเทอร์เฟซสามารถเป็นส่วนขยายของอินเทอร์เฟซที่กำหนดไว้ก่อนหน้านี้ได้ ส่วนขยายสามารถเป็นหนึ่งในสามประเภทต่อไปนี้:
- อินเทอร์เฟซสามารถเพิ่มฟังก์ชันการทำงานให้กับอีกอันหนึ่ง โดยรวม API ของมันไว้ไม่เปลี่ยนแปลง
- แพ็คเกจสามารถเพิ่มฟังก์ชันการทำงานให้กับอีกอันหนึ่ง โดยรวม API ไว้ไม่เปลี่ยนแปลง
- อินเทอร์เฟซสามารถนำเข้าประเภทจากแพ็คเกจหรือจากอินเทอร์เฟซเฉพาะ
อินเทอร์เฟซสามารถขยายอินเทอร์เฟซอื่นได้เพียงหนึ่งอินเทอร์เฟซเท่านั้น (ไม่มีการสืบทอดหลายรายการ) แต่ละอินเทอร์เฟซในแพ็คเกจที่มีหมายเลขเวอร์ชันรองที่ไม่ใช่ศูนย์จะต้องขยายอินเทอร์เฟซในแพ็คเกจเวอร์ชันก่อนหน้า ตัวอย่างเช่น หากอินเทอร์ IBar
ในเวอร์ชัน 4.0 ของ derivative
ของแพ็คเกจนั้นใช้ (ขยาย) อินเทอร์เฟ IFoo
ในเวอร์ชัน 1.2 ของแพ็คเกจ original
และเวอร์ชัน 1.3 ของแพ็คเกจ original
ถูกสร้างขึ้น IBar
เวอร์ชัน 4.1 จะไม่สามารถขยายเวอร์ชัน 1.3 ของ IFoo
ได้ แต่ IBar
เวอร์ชัน 4.1 จะต้องขยาย IBar
เวอร์ชัน 4.0 ซึ่งเชื่อมโยงกับ IFoo
เวอร์ชัน 1.2 แทน IBar
เวอร์ชัน 5.0 สามารถขยาย IFoo
เวอร์ชัน 1.3 ได้ หากต้องการ
ส่วนขยายอินเทอร์เฟซไม่ได้หมายความถึงการพึ่งพาไลบรารีหรือการรวมข้าม HAL ในโค้ดที่สร้างขึ้น เพียงนำเข้าโครงสร้างข้อมูลและคำจำกัดความของวิธีการในระดับ HIDL ทุกวิธีใน HAL จะต้องถูกนำมาใช้ใน HAL นั้น
ส่วนขยายของผู้ขาย
ในบางกรณี ส่วนขยายของผู้ขายจะถูกนำไปใช้เป็นคลาสย่อยของออบเจ็กต์ฐานที่แสดงถึงอินเทอร์เฟซหลักที่ขยาย ออบเจ็กต์เดียวกันจะถูกลงทะเบียนภายใต้ชื่อและเวอร์ชัน HAL พื้นฐาน และภายใต้ชื่อและเวอร์ชัน HAL ของส่วนขยาย (ผู้จำหน่าย)
การกำหนดเวอร์ชัน
แพ็คเกจมีการกำหนดเวอร์ชัน และอินเทอร์เฟซมีเวอร์ชันของแพ็คเกจ เวอร์ชันจะแสดงเป็นจำนวนเต็มสองจำนวน หลัก ส่วนน้อย .
- เวอร์ชัน หลัก เข้ากันไม่ได้แบบย้อนหลัง การเพิ่มหมายเลขเวอร์ชันหลักจะรีเซ็ตหมายเลขเวอร์ชันรองเป็น 0
- เวอร์ชัน รอง สามารถใช้งานร่วมกันได้แบบย้อนหลัง การเพิ่มตัวเลขรองแสดงว่าเวอร์ชันที่ใหม่กว่าสามารถใช้งานร่วมกับเวอร์ชันก่อนหน้าได้อย่างสมบูรณ์ สามารถเพิ่มโครงสร้างข้อมูลและวิธีการใหม่ได้ แต่ไม่สามารถเปลี่ยนแปลงโครงสร้างข้อมูลหรือลายเซ็นวิธีการที่มีอยู่ได้
HAL เวอร์ชันหลักหรือรองหลายเวอร์ชันสามารถปรากฏบนอุปกรณ์พร้อมกันได้ อย่างไรก็ตาม ควรเลือกใช้เวอร์ชันรองมากกว่าเวอร์ชันหลัก เนื่องจากรหัสไคลเอ็นต์ที่ทำงานกับอินเทอร์เฟซเวอร์ชันรองก่อนหน้าก็จะทำงานกับอินเทอร์เฟซเดียวกันเวอร์ชันรองที่ใหม่กว่าด้วย สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการกำหนดเวอร์ชันและส่วนขยายของผู้จำหน่าย โปรดดูที่ การกำหนดเวอร์ชัน HIDL
สรุปเค้าโครงอินเทอร์เฟซ
ส่วนนี้จะสรุปวิธีการจัดการแพ็คเกจอินเทอร์เฟซ HIDL (เช่น hardware/interfaces
) และรวบรวมข้อมูลที่นำเสนอทั่วทั้งส่วน HIDL ก่อนที่จะอ่าน ตรวจสอบให้แน่ใจว่าคุณคุ้นเคยกับ HIDL Versioning แนวคิดการแฮชใน การแฮชด้วย hidl-gen รายละเอียด การทำงานกับ HIDL โดยทั่วไป และคำจำกัดความต่อไปนี้:
ภาคเรียน | คำนิยาม |
---|---|
อินเทอร์เฟซไบนารีของแอปพลิเคชัน (ABI) | อินเทอร์เฟซการเขียนโปรแกรมแอปพลิเคชัน + การเชื่อมโยงไบนารีใดๆ ที่จำเป็น |
ชื่อที่มีคุณสมบัติครบถ้วน (fqName) | ชื่อเพื่อแยกแยะประเภท hidl ตัวอย่าง: android.hardware.foo@1.0::IFoo |
บรรจุุภัณฑ์ | แพ็คเกจที่มีอินเตอร์เฟสและประเภท HIDL ตัวอย่าง: android.hardware.foo@1.0 |
รูทแพ็คเกจ | แพ็คเกจรูทที่มีอินเตอร์เฟส HIDL ตัวอย่าง: อินเทอร์เฟซ HIDL android.hardware อยู่ในรูทแพ็กเกจ android.hardware.foo@1.0 |
เส้นทางรูทของแพ็กเกจ | ตำแหน่งในแผนผังต้นทางของ Android ที่รูทของแพ็คเกจแมปไป |
สำหรับคำจำกัดความเพิ่มเติม โปรดดูที่ คำศัพท์เฉพาะ ของ HIDL
ทุกไฟล์สามารถพบได้จากการแมปรูทแพ็คเกจและชื่อที่มีคุณสมบัติครบถ้วน
แพ็กเกจรูทถูกระบุเป็น hidl-gen
เป็นอาร์กิวเมนต์ -r android.hardware:hardware/interfaces
ตัวอย่างเช่น หากแพ็คเกจคือ vendor.awesome.foo@1.0::IFoo
และ hidl-gen
ถูกส่ง -r vendor.awesome:some/device/independent/path/interfaces
ดังนั้นไฟล์อินเทอร์เฟซควรอยู่ใน $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal
ในทางปฏิบัติ ขอแนะนำสำหรับผู้จำหน่ายหรือ OEM ที่ชื่อ awesome
ให้ใส่อินเทอร์เฟซมาตรฐานของตนใน vendor.awesome
หลังจากเลือกเส้นทางแพ็คเกจแล้ว จะต้องไม่เปลี่ยนแปลง เนื่องจากเส้นทางนี้ถูกอบเข้าสู่ ABI ของอินเทอร์เฟซ
การแมปเส้นทางแพ็กเกจไม่ควรซ้ำกัน
ตัวอย่างเช่น ถ้าคุณมี -rsome.package:$PATH_A
และ -rsome.package:$PATH_B
, $PATH_A
จะต้องเท่ากับ $PATH_B
สำหรับไดเร็กทอรีอินเทอร์เฟซที่สอดคล้องกัน (ซึ่งทำให้ การกำหนดเวอร์ชันอินเทอร์เฟซ ง่ายขึ้นมาก)
แพ็คเกจรูทต้องมีไฟล์การกำหนดเวอร์ชัน
หากคุณสร้างพาธแพ็กเกจ เช่น -r vendor.awesome:vendor/awesome/interfaces
คุณควรสร้างไฟล์ $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt
ซึ่งควรมีแฮชของอินเทอร์เฟซที่สร้างโดยใช้ -Lhash
ตัวเลือกใน hidl-gen
(จะมีการกล่าวถึงอย่างกว้างขวางใน Hashing ด้วย hidl-gen )
อินเทอร์เฟซไปในตำแหน่งที่ไม่ขึ้นอยู่กับอุปกรณ์
ในทางปฏิบัติ ขอแนะนำให้แชร์อินเทอร์เฟซระหว่างสาขา ซึ่งช่วยให้สามารถนำโค้ดกลับมาใช้ซ้ำได้สูงสุดและทดสอบโค้ดได้สูงสุดบนอุปกรณ์และกรณีการใช้งานต่างๆ