HIDL กำหนดให้อินเทอร์เฟซทั้งหมดที่เขียนใน HIDL ต้องมีเวอร์ชัน หลังจบกิจกรรม HAL อินเทอร์เฟซถูกเผยแพร่แล้ว มีการระงับไว้ และต้องมีการเปลี่ยนแปลงเพิ่มเติม เวอร์ชันใหม่ของอินเทอร์เฟซนั้น แม้ว่าอินเทอร์เฟซที่เผยแพร่หนึ่งๆ จะไม่สามารถ อาจขยายได้โดยอินเทอร์เฟซอื่น
โครงสร้างรหัส HIDL
มีการจัดระเบียบรหัส HIDL ตามที่ผู้ใช้กำหนด ประเภท อินเทอร์เฟซ และแพ็กเกจ
- ประเภทที่กำหนดโดยผู้ใช้ (UDT) HIDL ให้สิทธิ์เข้าถึงชุด ประเภทข้อมูลพื้นฐานที่สามารถใช้สร้างประเภทที่ซับซ้อนขึ้นผ่าน โครงสร้าง สหภาพ และการแจงนับ มีการส่ง UDT ไปยังเมธอดของ และสามารถกำหนดในระดับของแพ็กเกจ (มักจะใช้ใน อินเทอร์เฟซ) หรือภายในไปยังอินเทอร์เฟซ
- อินเทอร์เฟซ ในฐานะที่เป็นองค์ประกอบพื้นฐานของ HIDL ซึ่งเป็นอินเทอร์เฟซ ประกอบด้วยการประกาศของ UDT และเมธอด อินเทอร์เฟซยังสามารถรับค่าจาก อินเทอร์เฟซอื่น
- แพ็กเกจ จัดระเบียบอินเทอร์เฟซ HIDL และข้อมูลที่เกี่ยวข้อง
ประเภทการดำเนินงาน แพ็กเกจจะระบุตามชื่อและเวอร์ชัน
ได้แก่
- ไฟล์คำจำกัดความของประเภทข้อมูลที่ชื่อ
types.hal
- ไม่มีอินเทอร์เฟซอย่างน้อย 1 รายการ โดยแต่ละรายการอยู่ในไฟล์
.hal
ของตนเอง
- ไฟล์คำจำกัดความของประเภทข้อมูลที่ชื่อ
ไฟล์คำจำกัดความประเภทข้อมูล types.hal
มีเฉพาะ UDT (ทั้งหมด
UDT ระดับแพ็กเกจเก็บไว้ในไฟล์เดียว) การรับรองในเป้าหมาย
สำหรับทุกอินเทอร์เฟซในแพ็กเกจ
ปรัชญาการกำหนดเวอร์ชัน
แพ็กเกจ HIDL (เช่น android.hardware.nfc
) หลังจากถูก
เผยแพร่สำหรับเวอร์ชันที่ระบุ (เช่น 1.0
) จะเปลี่ยนแปลงไม่ได้ รายการดังกล่าว
ไม่สามารถเปลี่ยนได้ การแก้ไขอินเทอร์เฟซในแพ็กเกจหรือ
การเปลี่ยนแปลง UDT ทำได้เฉพาะในแพ็กเกจอื่นเท่านั้น
ใน HIDL การกำหนดเวอร์ชันจะมีผลที่ระดับแพ็กเกจ ไม่ใช่ที่ระดับอินเทอร์เฟซ โดยอินเทอร์เฟซและ UDT ทั้งหมดในแพ็กเกจจะใช้เวอร์ชันเดียวกัน พัสดุ เวอร์ชันจะตามด้วยความหมาย การกำหนดเวอร์ชัน โดยไม่ใช้ระดับแพตช์และคอมโพเนนต์ข้อมูลของบิลด์ ภายใน แพ็กเกจที่กำหนด แถบเวอร์ชันย่อย แสดงถึงเวอร์ชันใหม่ของ แพ็กเกจนี้จะทำงานย้อนหลังได้กับแพ็กเกจเก่าและหลัก จุดเวอร์ชัน บ่งบอกว่าแพ็กเกจเวอร์ชันใหม่ไม่ใช่เวอร์ชัน ย้อนไปได้กับแพ็กเกจเก่า
โดยหลักการแล้ว แพ็กเกจอาจเกี่ยวข้องกับแพ็กเกจอื่นได้หลายวิธี ดังนี้
- ไม่เลย
- ความสามารถในการขยายการใช้งานที่เข้ากันได้แบบย้อนหลังระดับแพ็กเกจ ช่วงเวลานี้
เกิดขึ้นสำหรับการอัปรีฟเวอร์ชันย่อยใหม่ (การแก้ไขเพิ่มเติมครั้งถัดไป) ของแพ็กเกจ
แพ็กเกจใหม่มีชื่อและเวอร์ชันหลักเหมือนกับแพ็กเกจเก่า แต่
เวอร์ชันย่อยที่สูงกว่า ฟังก์ชันการทำงาน แพ็กเกจใหม่เป็นซูเปอร์เซ็ตของเวอร์ชันเก่า
แพ็กเกจ ความหมาย:
- อินเทอร์เฟซระดับบนสุดของแพ็กเกจหลักมีอยู่ในแพ็กเกจใหม่
แม้ว่าอินเทอร์เฟซอาจมีวิธีการใหม่ๆ เช่น UDT ของอินเทอร์เฟซท้องถิ่น (
ส่วนขยายระดับอินเทอร์เฟซดังที่อธิบายไว้ด้านล่าง) และ UDT ใหม่ใน
types.hal
- นอกจากนี้ คุณยังเพิ่มอินเทอร์เฟซใหม่ลงในแพ็กเกจใหม่ได้ด้วย
- ประเภทข้อมูลทั้งหมดของแพ็กเกจหลักจะปรากฏในแพ็กเกจใหม่และ ด้วยเมธอด (ซึ่งสามารถนำกลับมาใช้ใหม่) จากแพ็กเกจเก่าได้
- สามารถเพิ่มประเภทข้อมูลใหม่เพื่อการใช้งานโดยวิธีการใหม่ในการเพิ่มคะแนน อินเทอร์เฟซที่มีอยู่ หรือโดยอินเทอร์เฟซใหม่
- อินเทอร์เฟซระดับบนสุดของแพ็กเกจหลักมีอยู่ในแพ็กเกจใหม่
แม้ว่าอินเทอร์เฟซอาจมีวิธีการใหม่ๆ เช่น UDT ของอินเทอร์เฟซท้องถิ่น (
ส่วนขยายระดับอินเทอร์เฟซดังที่อธิบายไว้ด้านล่าง) และ UDT ใหม่ใน
- ความสามารถในการขยายการใช้งานที่เข้ากันได้แบบย้อนหลังระดับอินเทอร์เฟซ ฟิลด์
แพ็กเกจยังสามารถขยายแพ็กเกจเดิมได้ด้วย
การแยกประเภทอย่างเป็นเหตุเป็นผล
ที่มีเพียงฟังก์ชันเพิ่มเติม ซึ่งไม่ใช่ฟังก์ชันหลัก
สําหรับวัตถุประสงค์ดังกล่าว สิ่งที่อาจเหมาะสมมีดังนี้
- อินเทอร์เฟซในแพ็กเกจใหม่ต้องเกี่ยวข้องกับประเภทข้อมูล ใหม่
- อินเทอร์เฟซในแพ็กเกจใหม่สามารถขยายอินเทอร์เฟซเดิมของอินเทอร์เฟซเก่าได้ตั้งแต่ 1 รายการขึ้นไป แพ็กเกจของคุณ
- ขยายความเข้ากันไม่ได้กับเวอร์ชันเดิม นี่คือ การเพิ่มขึ้นของแพ็กเกจเวอร์ชันหลัก และไม่จำเป็นต้องมีความสัมพันธ์ระหว่าง ทั้ง 2 อย่าง หากมี สามารถแสดงด้วยชุดค่าผสมของ ประเภทจากแพ็กเกจเวอร์ชันเก่า และการรับช่วงต่อ ของอินเทอร์เฟซเวอร์ชันเก่า
การกำหนดโครงสร้างอินเทอร์เฟซ
สำหรับอินเทอร์เฟซที่มีโครงสร้างดี การเพิ่มฟังก์ชันประเภทใหม่ๆ ที่ ไม่ได้เป็นส่วนหนึ่งของการออกแบบเดิม ควรแก้ไข HIDL ของ Google ในทางกลับกัน หากคุณสามารถหรือคาดหวังว่าจะเปลี่ยนแปลงทั้ง อินเทอร์เฟซที่นำเสนอฟังก์ชันใหม่ๆ โดยไม่ต้องเปลี่ยนอินเทอร์เฟซ อินเทอร์เฟซก็จะไม่มีโครงสร้าง
Treble รองรับผู้ให้บริการและคอมโพเนนต์ของระบบที่คอมไพล์แยกกัน ซึ่งองค์ประกอบ
vendor.img
ในอุปกรณ์และsystem.img
ที่คอมไพล์แยกกัน การโต้ตอบทั้งหมดระหว่าง vendor.img
กับ
คุณต้องระบุ system.img
อย่างชัดเจนและละเอียดถี่ถ้วนเพื่อให้
จะยังทำงานต่อไปอีกหลายปี ซึ่งรวมถึงแพลตฟอร์ม API จำนวนมาก
คือกลไก IPC ที่ HIDL ใช้เพื่อสื่อสารระหว่างโปรเซส
ขอบเขต system.img
/vendor.img
ขอบเขต
ข้อกำหนด
ข้อมูลทั้งหมดที่ส่งผ่าน HIDL ต้องได้รับการกำหนดอย่างชัดเจน เพื่อให้มั่นใจว่า และลูกค้าสามารถทำงานร่วมกันได้ต่อไป แม้ในขณะที่ แยกต่างหากหรือพัฒนาขึ้นโดยอิสระ ข้อมูลต้องเป็นไปตามหลักเกณฑ์ต่อไปนี้ ข้อกำหนด
- สามารถอธิบายใน HIDL ได้โดยตรง (โดยใช้ Struct enum เป็นต้น) ชื่อและความหมาย
- สามารถอธิบายตามมาตรฐานสาธารณะ เช่น ISO/IEC 7816
- อธิบายได้โดยใช้มาตรฐานฮาร์ดแวร์หรือเลย์เอาต์ทางกายภาพของฮาร์ดแวร์
- อาจเป็นข้อมูลที่ไม่ชัดเจน (เช่น คีย์สาธารณะ รหัส ฯลฯ) หากจำเป็น
หากใช้ข้อมูลแบบทึบ HIDL จะต้องอ่านค่าในด้านใดด้านหนึ่งเท่านั้น
ของ Google ตัวอย่างเช่น หากโค้ด vendor.img
ให้คอมโพเนนต์ใน
system.img
ข้อความสตริงหรือvec<uint8_t>
ข้อมูลนั้นไม่สามารถแยกวิเคราะห์โดย system.img
ได้ สามารถทำได้
จะส่งกลับไปยัง vendor.img
เท่านั้นเพื่อตีความ เมื่อใด
การส่งค่าจาก vendor.img
ไปยังโค้ดของผู้ให้บริการเปิดอยู่
system.img
หรืออุปกรณ์อื่น รูปแบบของข้อมูล และวิธีการที่ข้อมูล
ในการตีความ ต้องมีการอธิบายอย่างละเอียดและยังคงเป็นส่วนหนึ่งของ
ของ AdSense
หลักเกณฑ์
คุณควรจะสามารถเขียนการติดตั้งใช้งานหรือไคลเอ็นต์สำหรับ HAL ได้โดยใช้ ไฟล์ .hal (กล่าวคือ คุณไม่จำเป็นต้องดูซอร์สโค้ดของ Android หรือสาธารณะ มาตรฐาน) เราขอแนะนำให้ระบุลักษณะการทำงานที่จำเป็น ข้อความ เช่น "การใช้งานอาจทำ A หรือ B" ส่งเสริมให้มีการนำไปใช้งาน ได้สัมพันธ์กับลูกค้าที่พัฒนาด้วย
เลย์เอาต์รหัส HIDL
HIDL ประกอบด้วยแพ็กเกจหลักและแพ็กเกจผู้ให้บริการ
อินเทอร์เฟซ HIDL หลักคืออินเทอร์เฟซที่ Google ระบุไว้ พัสดุภัณฑ์ที่พวกเขาอยู่
จะเริ่มต้นด้วย android.hardware.
และตั้งชื่อตามระบบย่อย
ซึ่งมีโอกาสในระดับการตั้งชื่อที่ซ้อนอยู่ ตัวอย่างเช่น ชื่อแพ็กเกจ NFC
android.hardware.nfc
และแพ็กเกจกล้อง
android.hardware.camera
โดยทั่วไป แพ็กเกจหลักจะมีชื่อ
android.hardware.
[name1
][name2
]....
แพ็กเกจ HIDL จะมีเวอร์ชันอื่นนอกเหนือจากชื่อด้วย เช่น แพ็กเกจ
android.hardware.camera
อาจอยู่ที่เวอร์ชัน 3.4
นี่คือ
สำคัญ เนื่องจากเวอร์ชันของแพ็กเกจมีผลต่อตำแหน่งของแพ็กเกจในโครงสร้างต้นทาง
แพ็กเกจหลักทั้งหมดอยู่ภายใต้ hardware/interfaces/
ในส่วน
ระบบบิลด์ แพ็กเกจ
android.hardware.
[name1
][name2
]...
ที่เวอร์ชัน $m.$n
ต่ำกว่า
hardware/interfaces/name1/name2/
.../$m.$n/
;
พัสดุ
android.hardware.camera
เวอร์ชัน 3.4
อยู่ในไดเรกทอรี
hardware/interfaces/camera/3.4/.
มีการแมปแบบฮาร์ดโค้ดอยู่
ระหว่างคำนำหน้าแพ็กเกจ android.hardware.
และเส้นทาง
hardware/interfaces/
แพ็กเกจที่ไม่ใช่แพ็กเกจหลัก (ผู้ให้บริการ) คือแพ็กเกจที่ผลิตโดยผู้ให้บริการ SoC หรือ ODM
คำนำหน้าสำหรับแพ็กเกจที่ไม่ใช่แพ็กเกจหลักคือ vendor.$(VENDOR).hardware.
โดยที่
$(VENDOR)
กล่าวถึงผู้ให้บริการ SoC หรือ OEM/ODM เส้นทางนี้จะจับคู่กับเส้นทาง
vendor/$(VENDOR)/interfaces
ในโครงสร้าง (การแมปนี้ยัง
ฮาร์ดโค้ด)
ชื่อประเภทที่ผู้ใช้กำหนดซึ่งตรงตามเกณฑ์ทั้งหมด
ใน HIDL UDT ทั้งหมดจะมีชื่อที่สมบูรณ์ในตัวเอง ซึ่งประกอบด้วยชื่อ UDT,
ชื่อแพ็กเกจที่มีการกำหนด UDT และเวอร์ชันของแพ็กเกจไว้
ชื่อที่มีคุณสมบัติครบถ้วนจะใช้ก็ต่อเมื่อมีการประกาศอินสแตนซ์ของประเภท และ
ไม่ใช่ตำแหน่งที่มีการกำหนดประเภทไว้ เช่น สมมติว่าเป็นแพ็กเกจ
android.hardware.nfc,
เวอร์ชัน 1.0
กำหนดโครงสร้าง
ชื่อ NfcData
ที่เว็บไซต์ของคำประกาศ (ไม่ว่าจะใน
types.hal
หรือภายในการประกาศของอินเทอร์เฟซ) การประกาศ
เพียงระบุว่า
struct NfcData { vec<uint8_t> data; };
เมื่อประกาศอินสแตนซ์ประเภทนี้ (ไม่ว่าจะภายในโครงสร้างข้อมูลหรือ เป็นพารามิเตอร์เมธอด) ให้ใช้ชื่อประเภทที่สมบูรณ์ในตัวเอง:
android.hardware.nfc@1.0::NfcData
ไวยากรณ์ทั่วไปคือ
PACKAGE@VERSION::UDT
โดยที่
PACKAGE
คือชื่อที่คั่นด้วยจุดของแพ็กเกจ HIDL (เช่นandroid.hardware.nfc
)VERSION
คือMajor.minor-version ที่คั่นด้วยจุด รูปแบบของแพ็กเกจ (เช่น1.0
)UDT
คือชื่อที่คั่นด้วยจุดของ HIDL UDT เนื่องจาก HIDL สนับสนุนอินเทอร์เฟซ UDT และ HIDL ที่ฝังอยู่อาจมี UDT (ประเภทของ การประกาศแบบซ้อน) จะใช้จุดเพื่อเข้าถึงชื่อ
ตัวอย่างเช่น ถ้าการกำหนดข้อความเชิงซ้อนต่อไปนี้มีการกำหนดไว้ใน
ประเภทไฟล์ในแพ็กเกจ android.hardware.example
เวอร์ชัน
1.0
:
// types.hal package android.hardware.example@1.0; struct Foo { struct Bar { // … }; Bar cheers; };
ชื่อที่มีคุณสมบัติครบถ้วนของ Bar
คือ
android.hardware.example@1.0::Foo.Bar
นอกจากการอยู่ใน
แพ็กเกจข้างต้น การประกาศที่ฝังอยู่ในอินเทอร์เฟซที่เรียกว่า
IQuux
:
// IQuux.hal package android.hardware.example@1.0; interface IQuux { struct Foo { struct Bar { // … }; Bar cheers; }; doSomething(Foo f) generates (Foo.Bar fb); };
ชื่อที่มีคุณสมบัติครบถ้วนของ Bar
คือ
android.hardware.example@1.0::IQuux.Foo.Bar
ในทั้ง 2 กรณี จะเรียก Bar
ว่า Bar
ได้เท่านั้น
ภายในขอบเขตของการประกาศFoo
ที่พัสดุหรือ
ระดับอินเทอร์เฟซ คุณต้องอ้างอิง Bar
ผ่าน Foo
Foo.Bar
ตามการประกาศเมธอด doSomething
ที่ด้านบน หรือคุณจะประกาศเมธอดให้ชัดเจนมากขึ้นก็ได้ ดังนี้
// IQuux.hal doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb);
ค่าการแจงนับที่มีคุณสมบัติครบถ้วน
หาก UDT เป็นประเภท enum แต่ละค่าของประเภท enum จะมีค่า
ชื่อที่มีคุณสมบัติครบถ้วนที่ขึ้นต้นด้วยชื่อแบบเต็มของประเภท enum
ตามด้วยเครื่องหมายทวิภาคแล้วตามด้วยชื่อของค่า enum ตัวอย่างเช่น
สมมติว่าแพ็กเกจ android.hardware.nfc,
เวอร์ชัน 1.0
กำหนดประเภท enum NfcStatus
ดังนี้
enum NfcStatus { STATUS_OK, STATUS_FAILED };
เมื่ออ้างถึง STATUS_OK
ชื่อที่ตรงตามเกณฑ์ทั้งหมดคือ
android.hardware.nfc@1.0::NfcStatus:STATUS_OK
ไวยากรณ์ทั่วไปคือ
PACKAGE@VERSION::UDT:VALUE
,
โดยมี
PACKAGE@VERSION::UDT
คือ ชื่อที่ตรงกันทุกประการสำหรับประเภท enumVALUE
คือชื่อของค่า
กฎการอนุมานอัตโนมัติ
ไม่จำเป็นต้องระบุชื่อ UDT แบบเต็ม ชื่อ UDT สามารถ ละเว้นสิ่งต่อไปนี้อย่างปลอดภัย
- แพ็กเกจ เช่น
@1.0::IFoo.Type
- ทั้งแพ็กเกจและเวอร์ชัน เช่น
IFoo.Type
HIDL พยายามเติมชื่อให้สมบูรณ์โดยใช้กฎการแทรกแซงอัตโนมัติ (กฎที่ต่ำกว่า ตัวเลขหมายถึงลำดับความสำคัญที่สูงกว่า)
กฎข้อ 1
หากไม่ได้ระบุแพ็กเกจและเวอร์ชัน ระบบจะพยายามค้นหาชื่อในเครื่อง ตัวอย่าง
interface Nfc { typedef string NfcErrorMessage; send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m); };
ค้นหา NfcErrorMessage
ในเครื่อง และ typedef
เหนือแท็กดังกล่าว ค้นหา NfcData
ในเครื่องเช่นกัน แต่ในความเป็นจริง
ไม่ได้กำหนดไว้ภายในเครื่อง ระบบจะใช้กฎ 2 และ 3 @1.0::NfcStatus
ระบุเวอร์ชัน ดังนั้นกฎ 1 จะไม่มีผล
กฎข้อ 2
หากกฎ 1 ล้มเหลวและคอมโพเนนต์ของชื่อที่สมบูรณ์ในตัวเองขาดหายไป
(แพ็กเกจ เวอร์ชัน หรือแพ็กเกจและเวอร์ชัน) ระบบจะป้อนข้อความอัตโนมัติให้คอมโพเนนต์
จากแพ็กเกจปัจจุบัน จากนั้นคอมไพเลอร์ HIDL จะค้นหาใน
ไฟล์ปัจจุบัน (และการนำเข้าทั้งหมด) เพื่อหาชื่อแบบเต็มที่ป้อนอัตโนมัติ
ใช้ตัวอย่างด้านบน สมมติว่ามีการประกาศ ExtendedNfcData
ดำเนินการในแพ็กเกจเดียวกัน (android.hardware.nfc
)
(1.0
) เป็น NfcData
ดังนี้
struct ExtendedNfcData { NfcData base; // … additional members };
คอมไพเลอร์ HIDL จะกรอกข้อมูลชื่อแพ็กเกจและชื่อเวอร์ชันจาก
แพ็กเกจปัจจุบันเพื่อสร้างชื่อ UDT ที่สมบูรณ์ในตัวเอง
android.hardware.nfc@1.0::NfcData
ตามชื่อมีอยู่ใน
แพ็กเกจปัจจุบัน (สมมติว่านำเข้าอย่างถูกต้อง) ใช้สำหรับ
ประกาศ
ระบบจะนำเข้าชื่อในแพ็กเกจปัจจุบัน ก็ต่อเมื่อหนึ่งในรายการต่อไปนี้คือ true:
- มีการนำเข้าอย่างชัดเจนด้วยคำสั่ง
import
- มีการกำหนดไว้ในภาษา
types.hal
ในแพ็กเกจปัจจุบัน
ก็จะเป็นไปตามกระบวนการเดียวกันนี้ หาก NfcData
ผ่านการรับรอง
หมายเลขเวอร์ชัน
struct ExtendedNfcData { // autofill the current package name (android.hardware.nfc) @1.0::NfcData base; // … additional members };
กฎข้อ 3
หากกฎ 2 สร้างการจับคู่ไม่สำเร็จ (ไม่ได้กำหนด UDT ไว้ในฟิลด์
) คอมไพเลอร์ HIDL จะสแกนหารายการที่ตรงกันภายในแพ็กเกจที่นำเข้าทั้งหมด
จากตัวอย่างด้านบน สมมติว่ามีการประกาศ ExtendedNfcData
ใน
เวอร์ชัน 1.1
ของแพ็กเกจ android.hardware.nfc
1.1
นำเข้า 1.0
ตามที่ควรจะเป็น (ดู
ส่วนขยายระดับแพ็กเกจ) และคำจำกัดความ
ระบุเฉพาะชื่อ UDT เท่านั้น
struct ExtendedNfcData { NfcData base; // … additional members };
คอมไพเลอร์จะค้นหา UDT ที่ชื่อ NfcData
และพบ UDT ใน
android.hardware.nfc
ในเวอร์ชัน 1.0
ส่งผลให้
UDT ที่สมบูรณ์ของ android.hardware.nfc@1.0::NfcData
หากมีมากกว่านั้น
พบผลการค้นหาที่ตรงกันมากกว่า 1 รายการสำหรับ UDT ที่มีคุณสมบัติบางส่วน นั่นคือคอมไพเลอร์ HIDL
เกิดข้อผิดพลาด
ตัวอย่าง
เมื่อใช้กฎ 2 ประเภทที่นำเข้าที่กำหนดไว้ในแพ็กเกจปัจจุบันจะชอบมากกว่า ประเภทที่นำเข้าจากแพ็กเกจอื่น:
// hardware/interfaces/foo/1.0/types.hal package android.hardware.foo@1.0; struct S {}; // hardware/interfaces/foo/1.0/IFooCallback.hal package android.hardware.foo@1.0; interface IFooCallback {}; // hardware/interfaces/bar/1.0/types.hal package android.hardware.bar@1.0; typedef string S; // hardware/interfaces/bar/1.0/IFooCallback.hal package android.hardware.bar@1.0; interface IFooCallback {}; // hardware/interfaces/bar/1.0/IBar.hal package android.hardware.bar@1.0; import android.hardware.foo@1.0; interface IBar { baz1(S s); // android.hardware.bar@1.0::S baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback };
S
จะได้รับการประมาณค่าเป็นandroid.hardware.bar@1.0::S
และพบในbar/1.0/types.hal
(เนื่องจากtypes.hal
ทำงานอัตโนมัติ นำเข้าแล้ว)IFooCallback
จะได้รับการประมาณค่าเป็นandroid.hardware.bar@1.0::IFooCallback
โดยใช้กฎ 2 แต่ ไม่พบ เนื่องจากไม่ได้นำเข้าbar/1.0/IFooCallback.hal
โดยอัตโนมัติ (เนื่องจากtypes.hal
) ดังนั้น กฎ 3 จะแปลค่าเป็นandroid.hardware.foo@1.0::IFooCallback
แทน ซึ่งมีการนำเข้า ผ่านimport android.hardware.foo@1.0;
)
Type.hal
แพ็กเกจ HIDL ทุกรายการจะมีไฟล์ types.hal
ที่มี UDT
ซึ่งจะใช้ร่วมกันระหว่างอินเทอร์เฟซทั้งหมดที่เข้าร่วมแพ็กเกจนั้น ประเภท HIDL
เป็นแบบสาธารณะเสมอ ไม่ว่าจะมีการประกาศ UDT ใน
types.hal
หรือภายในการประกาศอินเทอร์เฟซ ประเภท
เข้าถึงได้นอกขอบเขตที่ระบุไว้ types.hal
ไม่ได้มีไว้เพื่ออธิบาย API สาธารณะของแพ็กเกจ แต่ใช้เพื่อโฮสต์ UDT
อินเทอร์เฟซทั้งหมดภายในแพ็กเกจจะใช้ เนื่องด้วยธรรมชาติของ HIDL, UDT ทั้งหมด
เป็นส่วนหนึ่งของอินเทอร์เฟซ
types.hal
ประกอบด้วยคำสั่ง UDT และ import
เนื่องจาก types.hal
ใช้ได้กับทุกอินเทอร์เฟซของ
แพ็กเกจ (เป็นการนำเข้าโดยนัย) คำสั่ง import
เหล่านี้
ระดับแพ็กเกจตามคำจำกัดความ UDT ใน types.hal
สามารถรวม
ดังนั้น UDT และอินเทอร์เฟซจึงนำเข้ามา
ตัวอย่างเช่น สำหรับ IFoo.hal
package android.hardware.foo@1.0; // whole package import import android.hardware.bar@1.0; // types only import import android.hardware.baz@1.0::types; // partial imports import android.hardware.qux@1.0::IQux.Quux; // partial imports import android.hardware.quuz@1.0::Quuz;
ระบบนําเข้ารายการต่อไปนี้
android.hidl.base@1.0::IBase
(โดยนัย)android.hardware.foo@1.0::types
(โดยนัย)- ทุกอย่างใน
android.hardware.bar@1.0
(รวมทั้งหมด อินเทอร์เฟซและtypes.hal
) types.hal
จากandroid.hardware.baz@1.0::types
(ระบบจะไม่นำเข้าอินเทอร์เฟซในandroid.hardware.baz@1.0
)IQux.hal
และtypes.hal
จากandroid.hardware.qux@1.0
Quuz
จากandroid.hardware.quuz@1.0
(สมมติว่าQuuz
กำหนดไว้ในtypes.hal
ทั้ง ไฟล์types.hal
ได้รับการแยกวิเคราะห์ แต่ประเภทอื่นที่ไม่ใช่Quuz
ไม่ได้นำเข้า)
การกำหนดเวอร์ชันระดับอินเทอร์เฟซ
อินเทอร์เฟซแต่ละรายการในแพ็กเกจจะอยู่ในไฟล์ของตัวเอง แพ็กเกจ
อินเทอร์เฟซเป็นของ จะแสดงไว้ที่ด้านบนของอินเทอร์เฟซโดยใช้
คำสั่ง package
หลังจากการประกาศแพ็กเกจ ไม่มีหรือมากกว่า
การนำเข้าระดับอินเทอร์เฟซ (บางส่วนหรือทั้งหมด) อาจแสดงอยู่ในรายการ เช่น
package android.hardware.nfc@1.0;
ใน HIDL อินเทอร์เฟซสามารถรับค่าจากอินเทอร์เฟซอื่นๆ โดยใช้
คีย์เวิร์ด extends
รายการ หากต้องการให้อินเทอร์เฟซขยายอีกอินเทอร์เฟซหนึ่ง
ต้องมีสิทธิ์เข้าถึงคีย์ดังกล่าวผ่านคำสั่ง import
ชื่อของ
อินเทอร์เฟซที่กำลังขยาย (อินเทอร์เฟซพื้นฐาน) เป็นไปตามกฎสำหรับชื่อประเภท
คุณสมบัติที่อธิบายข้างต้น อินเทอร์เฟซหนึ่งรับค่าจากอินเทอร์เฟซได้เพียง 1 รายการเท่านั้น
HIDL ไม่รองรับการสืบทอดหลายรายการ
ตัวอย่างการกำหนดเวอร์ชัน Uprev ด้านล่างใช้แพ็กเกจต่อไปนี้
// types.hal package android.hardware.example@1.0 struct Foo { struct Bar { vec<uint32_t> val; }; }; // IQuux.hal package android.hardware.example@1.0 interface IQuux { fromFooToBar(Foo f) generates (Foo.Bar b); }
กฎ Uprev
หากต้องการกำหนดแพ็กเกจ package@major.minor
ให้เลือก A หรือ B ทั้งหมด
ต้องเป็นจริง
กฎ A | "เป็นเวอร์ชันย่อยที่เริ่มใหม่": เวอร์ชันย่อยก่อนหน้าทั้งหมด
package@major.0 , package@major.1 , ...
ต้องไม่กำหนด package@major.(minor-1)
|
---|
กฎ ข | เงื่อนไขต่อไปนี้เป็นจริงทั้งหมด
|
---|
เนื่องจากกฎ A:
- แพ็กเกจอาจเริ่มต้นด้วยหมายเลขเวอร์ชันย่อย (เช่น
android.hardware.biometrics.fingerprint
เริ่มต้นที่@2.1
) - ข้อกำหนด "ไม่ได้กำหนด
android.hardware.foo@1.0
" หมายความว่า ไดเรกทอรีhardware/interfaces/foo/1.0
ก็ไม่ควรอยู่
อย่างไรก็ตาม กฎ ก จะไม่มีผลกับแพ็กเกจที่มีชื่อแพ็กเกจเดียวกัน แต่มี
เวอร์ชันหลักที่แตกต่างกัน (เช่น
android.hardware.camera.device
มีทั้ง @1.0
และ
คำจำกัดความของ @3.2
@3.2
ไม่จำเป็นต้องโต้ตอบกับ
@1.0
) ดังนั้น @3.2::IExtFoo
จึงสามารถขยาย
@1.0::IFoo
หากชื่อแพ็กเกจระบุไว้เป็นอย่างอื่น
package@major.minor::IBar
สามารถขยายจากอินเทอร์เฟซที่มี
ชื่ออื่น (เช่น android.hardware.bar@1.0::IBar
สามารถ
ขยาย android.hardware.baz@2.2::IBaz
) หากอินเทอร์เฟซไม่
ประกาศประเภทขั้นสูงด้วยคีย์เวิร์ด extend
อย่างชัดเจน
ขยาย android.hidl.base@1.0::IBase
(ยกเว้น IBase
เอง)
ข.2 และ ข.3 ต้องปฏิบัติตามพร้อมกัน ตัวอย่างเช่น แม้ว่า
android.hardware.foo@1.1::IFoo
ต่อเวลา
android.hardware.foo@1.0::IFoo
เพื่อให้ผ่านกฎ ข.2 หาก
android.hardware.foo@1.1::IExtBar
ขยาย
android.hardware.foo@1.0::IBar
ยังไม่ใช่จำนวนเงินที่ถูกต้อง
อินเทอร์เฟซ Uprev
เพื่อเพิ่ม android.hardware.example@1.0
(ตามคำจำกัดความด้านบน) เป็น
@1.1
:
// types.hal package android.hardware.example@1.1; import android.hardware.example@1.0; // IQuux.hal package android.hardware.example@1.1 interface IQuux extends @1.0::IQuux { fromBarToFoo(Foo.Bar b) generates (Foo f); }
นี่คือ import
ระดับแพ็กเกจของเวอร์ชัน 1.0
ของ
android.hardware.example
ใน types.hal
ในขณะที่ไม่มี
เพิ่ม UDT ไว้ในแพ็กเกจเวอร์ชัน 1.1
การอ้างอิงถึง UDT ใน
ยังต้องใช้เวอร์ชัน 1.0
อยู่ ดังนั้น การนำเข้าระดับแพ็กเกจ
ใน types.hal
(ผลลัพธ์เดียวกันนี้อาจได้รับจาก
การนำเข้าระดับอินเทอร์เฟซใน IQuux.hal
)
ในextends @1.0::IQuux
ในการประกาศ
IQuux
เราได้ระบุเวอร์ชันของ IQuux
ที่
รับค่าเดิม (ต้องมีคำอธิบาย เนื่องจาก IQuux
ใช้เพื่อ
ประกาศอินเทอร์เฟซและรับค่าจากอินเทอร์เฟซ) ตามที่ประกาศไว้
เพียงชื่อที่รับช่วงแอตทริบิวต์แพ็กเกจและเวอร์ชันทั้งหมดในเว็บไซต์ของ
ข้อความชี้แจงต้องเป็นชื่อของอินเทอร์เฟซพื้นฐาน เรา
ที่จะใช้ UDT ที่มีคุณสมบัติครบถ้วนเช่นกัน แต่นั่นจะเป็น
ซ้ำซ้อน
อินเทอร์เฟซใหม่ IQuux
ไม่ประกาศเมธอดอีกครั้ง
fromFooToBar()
พร็อพเพอร์ตี้จะรับค่ามาจาก @1.0::IQuux
ง่ายๆ
แสดงวิธีการใหม่ที่เพิ่ม fromBarToFoo()
ใน HIDL จะรับค่าเดิม
ไม่อาจประกาศอีกครั้งในอินเทอร์เฟซย่อยได้
อินเทอร์เฟซ IQuux
จะไม่สามารถประกาศ fromFooToBar()
อย่างชัดเจน
การประชุมสุดยอด
บางครั้งชื่ออินเทอร์เฟซต้องเปลี่ยนชื่ออินเทอร์เฟซส่วนขยาย คำแนะนำจากเรา ว่าส่วนขยาย โครงสร้าง และสหภาพของ enum มีชื่อเหมือนกับสิ่งที่ขยาย เว้นแต่จะแตกต่างกันมากพอที่จะรับประกันชื่อใหม่ ตัวอย่าง
// in parent hal file enum Brightness : uint32_t { NONE, WHITE }; // in child hal file extending the existing set with additional similar values enum Brightness : @1.0::Brightness { AUTOMATIC }; // extending the existing set with values that require a new, more descriptive name: enum Color : @1.0::Brightness { HW_GREEN, RAINBOW };
หากเมธอดมีชื่อความหมายใหม่ (ตัวอย่างเช่น
fooWithLocation
) ก็ควรเป็นเช่นนั้น มิเช่นนั้นระบบควรทำดังนี้
ตั้งชื่อที่คล้ายกับสิ่งที่ส่วนขยายนั้นอยู่ ตัวอย่างเช่น เมธอด
foo_1_1
ใน @1.1::IFoo
สามารถแทนที่ฟังก์ชันการทำงานได้
ของเมธอด foo
ใน @1.0::IFoo
ถ้าไม่มีวิธีที่ดีกว่า
ชื่อสำรอง
การกำหนดเวอร์ชันระดับแพ็กเกจ
การกำหนดเวอร์ชัน HIDL เกิดขึ้นที่ระดับแพ็กเกจ หลังจากเผยแพร่แพ็กเกจ เปลี่ยนแปลงไม่ได้ (ชุดอินเทอร์เฟซและ UDT จะเปลี่ยนแปลงไม่ได้) แพ็กเกจสามารถ มีความเกี่ยวข้องกันในหลายวิธี ซึ่งทั้งหมดนี้สามารถแสดงออกผ่าน การผสมผสานการสืบทอดระดับอินเทอร์เฟซและการสร้าง UDT ตามองค์ประกอบ
อย่างไรก็ตาม มีการกำหนดความสัมพันธ์ประเภทหนึ่งไว้อย่างเคร่งครัดและต้องมีการบังคับใช้ ดังนี้ การรับช่วงค่าที่เข้ากันได้แบบย้อนหลังในระดับแพ็กเกจ ในสถานการณ์นี้ พารามิเตอร์ แพ็กเกจ parent คือแพ็กเกจที่รับช่วงมาจาก และ แพ็กเกจย่อยคือแพ็กเกจที่ขยายหน่วยโฆษณาหลัก ระดับแพ็กเกจ กฎการรับค่าที่เข้ากันได้แบบย้อนหลังมีดังนี้
- อินเทอร์เฟซระดับบนสุดทั้งหมดของแพ็กเกจหลักจะรับค่ามาจากอินเทอร์เฟซใน แพ็กเกจย่อย
- อินเทอร์เฟซใหม่ยังสามารถเพิ่มแพ็กเกจใหม่ (ไม่มีข้อจำกัดเกี่ยวกับ ความสัมพันธ์กับอินเทอร์เฟซอื่นๆ ในแพ็กเกจอื่น)
- สามารถเพิ่มประเภทข้อมูลใหม่เพื่อการใช้งานโดยวิธีการใหม่ในการเพิ่มคะแนน อินเทอร์เฟซที่มีอยู่ หรือโดยอินเทอร์เฟซใหม่
คุณสามารถใช้กฎเหล่านี้ได้โดยใช้การสืบทอดระดับอินเทอร์เฟซ HIDL และ UDT แต่ต้องใช้ความรู้ระดับเมตาเพื่อทำความรู้จักความสัมพันธ์เหล่านี้ ประกอบขึ้นเป็นส่วนขยายแพ็กเกจที่เข้ากันได้แบบย้อนหลัง ระบบอนุมานความรู้นี้ ดังนี้
หากแพ็กเกจเป็นไปตามข้อกำหนดนี้ hidl-gen
จะบังคับใช้
ความเข้ากันได้แบบย้อนหลัง