อินเทอร์เฟซและแพ็กเกจ

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/* ระบบ/ ที่เกี่ยวข้อง
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 ในเวอร์ชัน 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 (ผู้ให้บริการ)

การกำหนดเวอร์ชัน

แพ็กเกจมีการระบุเวอร์ชัน และอินเทอร์เฟซจะแสดงเวอร์ชันของแพ็กเกจ เวอร์ชันจะแสดงด้วยจำนวนเต็ม 2 ตัว ได้แก่ major.minor

  • เวอร์ชันหลักจะเข้ากันไม่ได้แบบย้อนหลัง การเพิ่ม หมายเลขเวอร์ชันหลักจะรีเซ็ตหมายเลขเวอร์ชันย่อยเป็น 0
  • ส่วนเวอร์ชันรองนั้นเข้ากันได้แบบย้อนหลัง การเพิ่ม จำนวนรองบ่งบอกว่าเวอร์ชันใหม่สามารถทำงานร่วมกับ เวอร์ชันก่อนหน้า สามารถเพิ่มโครงสร้างและวิธีการข้อมูลใหม่ได้ แต่จะไม่มี โครงสร้างข้อมูลหรือลายเซ็นวิธีการ อาจเปลี่ยนแปลงได้

อาจมี HAL เวอร์ชันหลักหรือเวอร์ชันย่อยได้หลายเวอร์ชันในอุปกรณ์ พร้อมกัน อย่างไรก็ตาม คุณควรเลือกใช้เวอร์ชันย่อยก่อนเวอร์ชันหลัก เนื่องจากรหัสไคลเอ็นต์ที่ใช้งานได้กับอินเทอร์เฟซเวอร์ชันย่อยก่อนหน้านี้ จะใช้งานกับอินเทอร์เฟซเดียวกันนี้ในเวอร์ชันย่อยๆ ได้ด้วย สำหรับข้อมูลเพิ่มเติม สำหรับรายละเอียดเกี่ยวกับการกำหนดเวอร์ชันและส่วนขยายผู้ให้บริการ โปรดดู การกำหนดเวอร์ชัน HIDL

สรุปเลย์เอาต์อินเทอร์เฟซ

ส่วนนี้จะสรุปวิธีจัดการแพ็กเกจอินเทอร์เฟซ HIDL (เช่น hardware/interfaces) และรวมข้อมูลที่นำเสนอ ตลอดทั้งส่วน HIDL ก่อนอ่าน โปรดตรวจดูว่าคุณคุ้นเคยกับ การกำหนดเวอร์ชัน HIDL แฮชกับ hidl-gen รายละเอียดเกี่ยวกับการทำงานร่วมกับ HIDL โดยทั่วไปและคำจำกัดความต่อไปนี้

คำศัพท์ คำจำกัดความ
อินเทอร์เฟซแบบไบนารีของแอปพลิเคชัน (ABI) Application Programming Interface และการเชื่อมต่อแบบไบนารีที่จำเป็น
ชื่อที่มีคุณสมบัติครบถ้วน (fqName) ชื่อเพื่อแยกประเภทการซ่อน ตัวอย่าง 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)

อินเทอร์เฟซจะทำงานโดยไม่ขึ้นอยู่กับอุปกรณ์ สถานที่ตั้ง

ในทางปฏิบัติ เราแนะนำให้แชร์อินเทอร์เฟซระหว่างสาขา ช่วงเวลานี้ ทำให้สามารถนำโค้ดมาใช้ซ้ำได้สูงสุดและการทดสอบโค้ดสูงสุดใน อุปกรณ์และกรณีการใช้งาน