อินเทอร์เฟซ & แพ็คเกจ

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 )

อินเทอร์เฟซไปในตำแหน่งที่ไม่ขึ้นอยู่กับอุปกรณ์

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