HIDL สร้างขึ้นจากอินเทอร์เฟซ ซึ่งเป็นประเภทนามธรรมที่ใช้ในภาษาเชิงออบเจ็กต์เพื่อกำหนดลักษณะการทำงาน อินเทอร์เฟซแต่ละรายการเป็นส่วนหนึ่งของแพ็กเกจ
แพ็กเกจ
ชื่อแพ็กเกจอาจมีระดับย่อย เช่น package.subpackage
ไดเรกทอรีรูทสำหรับแพ็กเกจ HIDL ที่เผยแพร่คือ hardware/interfaces
หรือ vendor/vendorName
(เช่น vendor/google
สำหรับอุปกรณ์ Pixel) ชื่อแพ็กเกจจะสร้างไดเรกทอรีย่อยอย่างน้อย 1 ไดเรกทอรีในไดเรกทอรีรูท โดยไฟล์ทั้งหมดที่กําหนดแพ็กเกจจะอยู่ในไดเรกทอรีเดียวกัน เช่น package android.hardware.example.extension.light@2.0
จะอยู่ในhardware/interfaces/example/extension/light/2.0
ตารางต่อไปนี้แสดงรายการคำนำหน้าและตำแหน่งของแพ็กเกจ
คำนำหน้าแพ็กเกจ | ตำแหน่ง | ประเภทอินเทอร์เฟซ |
---|---|---|
android.hardware.* |
hardware/interfaces/* |
HAL |
android.frameworks.* |
frameworks/hardware/interfaces/* |
เฟรมเวิร์ก/ ที่เกี่ยวข้อง |
android.system.* |
system/hardware/interfaces/* |
system/ related |
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
จะเกี่ยวข้องกับเอนทิตี 2 รายการ ได้แก่
- เอนทิตีที่นําเข้า ซึ่งอาจเป็นแพ็กเกจหรืออินเทอร์เฟซก็ได้
- เอนทิตีที่นําเข้า ซึ่งอาจเป็นแพ็กเกจหรืออินเทอร์เฟซ
เอนทิตีที่นำเข้าจะกำหนดโดยตำแหน่งของคำสั่ง 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 ของแพ็กเกจนั้นไว้
- อินเทอร์เฟซสามารถนําเข้าประเภทจากแพ็กเกจหรือจากอินเทอร์เฟซที่เฉพาะเจาะจง
อินเทอร์เฟซจะขยายอินเทอร์เฟซอื่นได้เพียงอินเทอร์เฟซเดียวเท่านั้น (ไม่มีการรับช่วงหลายรายการ)
อินเทอร์เฟซแต่ละรายการในแพ็กเกจที่มีหมายเลขเวอร์ชันย่อยที่ไม่ใช่ 0 จะต้องขยายอินเทอร์เฟซในแพ็กเกจเวอร์ชันก่อนหน้า ตัวอย่างเช่น หากอินเทอร์เฟซ IBar
ในแพ็กเกจ derivative
เวอร์ชัน 4.0 อิงตาม (ขยาย) อินเทอร์เฟซ IFoo
ในแพ็กเกจ original
เวอร์ชัน 1.2 และมีการสร้างแพ็กเกจ original
เวอร์ชัน 1.3 IBar
เวอร์ชัน 4.1 จะขยาย IFoo
เวอร์ชัน 1.3 ไม่ได้ แต่ IBar
เวอร์ชัน 4.1 ต้องขยายจากIBar
เวอร์ชัน 4.0 ซึ่งเชื่อมโยงกับ IFoo
เวอร์ชัน 1.2
IBar
เวอร์ชัน 5.0 อาจขยาย IFoo
เวอร์ชัน 1.3 ได้ หากต้องการ
ส่วนขยายอินเทอร์เฟซไม่ได้บ่งบอกถึงการพึ่งพาไลบรารีหรือการรวม HAL หลายรายการในโค้ดที่สร้างขึ้น เพียงแต่นําเข้าโครงสร้างข้อมูลและคําจํากัดความของเมธอดที่ระดับ HIDL วิธีการทุกรายการใน HAL ต้องติดตั้งใช้งานใน HAL นั้น
ส่วนขยายของผู้ให้บริการ
ในบางกรณี ระบบจะใช้ส่วนขยายของผู้ให้บริการเป็นคลาสย่อยของออบเจ็กต์พื้นฐานที่แสดงอินเทอร์เฟซหลักที่ขยาย ออบเจ็กต์เดียวกันจะลงทะเบียนภายใต้ชื่อและเวอร์ชัน HAL ของฐาน และภายใต้ชื่อและเวอร์ชัน HAL ของส่วนขยาย (ผู้ให้บริการ)
การกำหนดเวอร์ชัน
แพ็กเกจมีเวอร์ชัน และอินเทอร์เฟซจะมีเวอร์ชันของแพ็กเกจ เวอร์ชันจะแสดงเป็นจำนวนเต็มที่แบ่งออกเป็น 2 ส่วน ได้แก่ หลักรอง
- เวอร์ชันหลักจะใช้กับเวอร์ชันเก่าไม่ได้ การเพิ่มหมายเลขเวอร์ชันหลักจะรีเซ็ตหมายเลขเวอร์ชันย่อยเป็น 0
- เวอร์ชันย่อยจะใช้งานร่วมกับเวอร์ชันเก่าได้ การเพิ่มหมายเลขย่อยบ่งบอกว่าเวอร์ชันใหม่ใช้งานร่วมกับเวอร์ชันก่อนหน้าได้อย่างเต็มที่ คุณสามารถเพิ่มโครงสร้างข้อมูลและเมธอดใหม่ได้ แต่จะเปลี่ยนแปลงโครงสร้างข้อมูลหรือลายเซ็นเมธอดที่มีอยู่ไม่ได้
อุปกรณ์หนึ่งๆ อาจมี HAL หลายเวอร์ชันหลักหรือรองอยู่พร้อมกันได้ อย่างไรก็ตาม คุณควรใช้เวอร์ชันย่อยแทนเวอร์ชันหลัก เนื่องจากโค้ดไคลเอ็นต์ที่ทำงานกับอินเทอร์เฟซเวอร์ชันย่อยก่อนหน้าจะทำงานกับอินเทอร์เฟซเวอร์ชันย่อยเวอร์ชันถัดไปของอินเทอร์เฟซเดียวกันนั้นได้ ดูรายละเอียดเพิ่มเติมเกี่ยวกับการกำหนดเวอร์ชันและส่วนขยายของผู้ให้บริการได้ที่การกำหนดเวอร์ชัน HIDL
สรุปเลย์เอาต์อินเทอร์เฟซ
ส่วนนี้จะสรุปวิธีจัดการแพ็กเกจอินเทอร์เฟซ HIDL (เช่น hardware/interfaces
) และรวบรวมข้อมูลที่แสดงในส่วน HIDL ก่อนอ่าน โปรดทําความคุ้นเคยกับแนวคิดการกำหนดเวอร์ชัน HIDL, การแฮชด้วย hild-gen, รายละเอียดของการทํางานกับ HIDL โดยทั่วไป และคำจำกัดความต่อไปนี้
คำศัพท์ | คำจำกัดความ |
---|---|
อินเทอร์เฟซแบบไบนารีของแอปพลิเคชัน (ABI) | Application Programming Interface รวมถึงการลิงก์แบบไบนารีที่จำเป็น |
ชื่อที่สมบูรณ์ในตัวเอง (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
(เรื่องนี้มีการอธิบายอย่างละเอียดในหัวข้อการแฮชด้วย hidl-gen)
อินเทอร์เฟซจะอยู่ในที่ที่ไม่ขึ้นอยู่กับอุปกรณ์
ในทางปฏิบัติ เราขอแนะนำให้แชร์อินเทอร์เฟซระหว่างสาขา วิธีนี้ช่วยให้ใช้โค้ดซ้ำได้มากที่สุดและทดสอบโค้ดในอุปกรณ์และกรณีการใช้งานต่างๆ ได้มากที่สุด