HIDL

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

ภาษานิยามอินเทอร์เฟซ HAL หรือ HIDL (ออกเสียงว่า "hide-l") เป็นภาษาคำอธิบายอินเทอร์เฟซ (IDL) เพื่อระบุอินเทอร์เฟซระหว่าง HAL และผู้ใช้ อนุญาตให้ระบุประเภทและการเรียกใช้เมธอด รวบรวมไว้ในอินเทอร์เฟซและแพ็กเกจ กว้างกว่านั้น HIDL คือระบบสำหรับการสื่อสารระหว่าง codebases ที่อาจรวบรวมโดยอิสระ สำหรับ Android 10 นั้น HIDL เลิกใช้แล้ว และ Android กำลังโยกย้ายไปใช้ AIDL ทุกที่

HIDL มีวัตถุประสงค์เพื่อใช้สำหรับการสื่อสารระหว่างกระบวนการ (IPC) การสื่อสารระหว่างกระบวนการเรียกว่า Binderized สำหรับไลบรารีที่ต้องเชื่อมโยงกับกระบวนการ โหมด passthrough ก็มีให้เช่นกัน (ไม่รองรับใน Java)

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

การออกแบบ HIDL

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

การออกแบบ HIDL สร้างสมดุลให้กับข้อกังวลต่อไปนี้:

  • การทำงานร่วมกัน สร้างอินเทอร์เฟซที่ทำงานร่วมกันได้อย่างน่าเชื่อถือระหว่างกระบวนการ ซึ่งอาจคอมไพล์ด้วยสถาปัตยกรรม เครื่องมือโซ่ และการกำหนดค่าบิลด์ต่างๆ อินเทอร์เฟซ HIDL เป็นเวอร์ชันและไม่สามารถเปลี่ยนแปลงได้หลังจากเผยแพร่แล้ว
  • ประสิทธิภาพ . HIDL พยายามลดจำนวนการดำเนินการคัดลอกให้เหลือน้อยที่สุด ข้อมูลที่กำหนดโดย HIDL จะถูกส่งไปยังโค้ด C++ ในโครงสร้างข้อมูลโครงร่างมาตรฐาน C++ ที่สามารถใช้งานได้โดยไม่ต้องเปิดออก HIDL ยังมีอินเทอร์เฟซหน่วยความจำที่ใช้ร่วมกันและเนื่องจาก RPC ค่อนข้างช้าโดยเนื้อแท้ HIDL จึงสนับสนุนสองวิธีในการถ่ายโอนข้อมูลโดยไม่ต้องใช้การโทร RPC: หน่วยความจำที่ใช้ร่วมกันและ Fast Message Queue (FMQ)
  • ใช้งานง่าย HIDL หลีกเลี่ยงปัญหาการเป็นเจ้าของหน่วยความจำที่ยุ่งยากโดยใช้เฉพาะ in พารามิเตอร์สำหรับ RPC (ดู Android Interface Definition Language (AIDL) ); ค่าที่ไม่สามารถส่งคืนได้อย่างมีประสิทธิภาพจากเมธอดจะถูกส่งคืนผ่านฟังก์ชันเรียกกลับ การส่งข้อมูลไปยัง HIDL เพื่อการถ่ายโอนหรือการรับข้อมูลจาก HIDL จะไม่เปลี่ยนแปลงการเป็นเจ้าของข้อมูล ความเป็นเจ้าของจะคงอยู่กับฟังก์ชันการโทรเสมอ ข้อมูลจำเป็นต้องคงอยู่ในช่วงเวลาของฟังก์ชันที่เรียกเท่านั้น และอาจถูกทำลายทันทีหลังจากที่ฟังก์ชันที่เรียกกลับมา

การใช้โหมดทะลุผ่าน

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

โหมด Passthrough ใช้ได้เฉพาะกับไคลเอนต์ C++ และการนำไปใช้งาน อุปกรณ์ที่ใช้ Android เวอร์ชันก่อนหน้าไม่มี HAL เขียนเป็นภาษา Java ดังนั้น Java HAL จะถูกผูกมัดโดยเนื้อแท้

เมื่อมีการคอมไพล์ไฟล์ .hal .hal hidl-gen จะสร้างไฟล์ส่วนหัว passthrough พิเศษ BsFoo.h นอกเหนือจากส่วนหัวที่ใช้สำหรับการสื่อสารสารยึดเกาะ ส่วนหัวนี้กำหนดฟังก์ชันที่จะ dlopen ed เนื่องจาก HAL ที่ส่งผ่านทำงานในกระบวนการเดียวกับที่มีการเรียกใช้ ในกรณีส่วนใหญ่ วิธีการส่งผ่านจะถูกเรียกใช้โดยการเรียกใช้ฟังก์ชันโดยตรง (เธรดเดียวกัน) oneway รันในเธรดของตัวเอง เนื่องจากไม่ได้มีวัตถุประสงค์เพื่อรอให้ HAL ประมวลผล (ซึ่งหมายความว่า HAL ใดๆ ที่ใช้วิธีทาง oneway ในโหมดพาสทรูจะต้องปลอดภัยสำหรับเธรด)

เมื่อได้รับ IFoo.hal นั้น BsFoo.h จะรวมเมธอดที่สร้างโดย HIDL เพื่อจัดเตรียมคุณสมบัติเพิ่มเติม (เช่น การทำธุรกรรมทาง oneway ให้รันในเธรดอื่น) ไฟล์นี้คล้ายกับ BpFoo.h อย่างไรก็ตาม แทนที่จะส่งผ่านการโทร IPC โดยใช้เครื่องผูก ฟังก์ชันที่ต้องการจะถูกเรียกใช้โดยตรง การใช้งาน HAL ในอนาคต อาจมี การใช้งานหลายอย่าง เช่น FooFast HAL และ FooAccurate HAL ในกรณีดังกล่าว ไฟล์สำหรับการใช้งานเพิ่มเติมแต่ละรายการจะถูกสร้างขึ้น (เช่น PTFooFast.cpp และ PTFooAccurate.cpp )

ประสานผ่าน HALs

คุณสามารถรวมการใช้งาน HAL ที่สนับสนุนโหมดส่งผ่าน รับอินเทอร์เฟซ HAL abcd@MN::IFoo สองแพ็คเกจถูกสร้างขึ้น:

  • abcd@MN::IFoo-impl มีการใช้งาน HAL และแสดงฟังก์ชัน IFoo* HIDL_FETCH_IFoo(const char* name) บนอุปกรณ์รุ่นเก่า แพ็คเกจนี้ dlopen ed และการใช้งานจะถูกสร้างอินสแตนซ์โดยใช้ HIDL_FETCH_IFoo คุณสามารถสร้างรหัสฐานโดยใช้ hidl-gen และ -Lc++-impl และ -Landroidbp-impl
  • abcd@MN::IFoo-service . เปิด passthrough HAL และลงทะเบียนตัวเองเป็นบริการ binderized ทำให้การนำ HAL ไปใช้งานแบบเดียวกันนั้นเป็นทั้ง passthrough และ binderized

ด้วยประเภท IFoo คุณสามารถเรียก sp<IFoo> IFoo::getService(string name, bool getStub) เพื่อเข้าถึงอินสแตนซ์ของ IFoo หาก getStub เป็นจริง getService จะพยายามเปิด HAL ในโหมดส่งผ่านเท่านั้น ถ้า getStub เป็นเท็จ getService จะพยายามค้นหาบริการที่ผูกมัด หากล้มเหลวก็จะพยายามค้นหาบริการส่งผ่าน ไม่ควรใช้พารามิเตอร์ getStub ยกเว้นใน defaultPassthroughServiceImplementation (อุปกรณ์ที่เปิดตัวด้วย Android O เป็นอุปกรณ์ที่ผูกมัดอย่างสมบูรณ์ ดังนั้นจึงไม่อนุญาตการเปิดบริการในโหมดส่งผ่าน)

ไวยากรณ์ HIDL

โดยการออกแบบ ภาษา HIDL จะคล้ายกับ C (แต่ไม่ได้ใช้ตัวประมวลผลล่วงหน้า C) เครื่องหมายวรรคตอนทั้งหมดที่ไม่ได้อธิบายไว้ด้านล่าง (นอกเหนือจากการใช้ = และ | อย่างชัดเจน) เป็นส่วนหนึ่งของไวยากรณ์

หมายเหตุ: สำหรับรายละเอียดเกี่ยวกับลักษณะโค้ด HIDL โปรดดูที่ คู่มือรูปแบบโค้ด

  • /** */ หมายถึงความคิดเห็นในเอกสาร สิ่งเหล่านี้สามารถใช้ได้เฉพาะกับการประกาศประเภท วิธี ฟิลด์ และค่า enum
  • /* */ หมายถึงความคิดเห็นแบบหลายบรรทัด
  • // ระบุความคิดเห็นที่ท้ายบรรทัด นอกเหนือจาก // การขึ้นบรรทัดใหม่จะเหมือนกับช่องว่างอื่นๆ
  • ในตัวอย่างไวยากรณ์ด้านล่าง ข้อความจาก // ถึงท้ายบรรทัดไม่ได้เป็นส่วนหนึ่งของไวยากรณ์ แต่เป็นความคิดเห็นเกี่ยวกับไวยากรณ์แทน
  • [empty] หมายความว่าคำนั้นอาจว่างเปล่า
  • ? ตามตัวอักษรหรือคำหมายความว่าเป็นทางเลือก
  • ... หมายถึงลำดับที่มีรายการตั้งแต่ศูนย์ขึ้นไปโดยมีเครื่องหมายวรรคตอนคั่นตามที่ระบุ ไม่มีอาร์กิวเมนต์ที่หลากหลายใน HIDL
  • เครื่องหมายจุลภาคแยกองค์ประกอบลำดับ
  • อัฒภาคยุติแต่ละองค์ประกอบ รวมถึงองค์ประกอบสุดท้าย
  • ตัวพิมพ์ใหญ่ไม่ใช่เทอร์มินัล
  • italics คือตระกูลโทเค็น เช่น integer หรือ identifier (กฎการแยกวิเคราะห์ C มาตรฐาน)
  • constexpr คือนิพจน์คงที่สไตล์ C (เช่น 1 + 1 และ 1L << 3 )
  • import_name คือชื่อแพ็กเกจหรืออินเทอร์เฟซ ซึ่งมีคุณสมบัติตามที่อธิบายไว้ใน HIDL Versioning
  • words ตัวพิมพ์เล็กเป็นโทเค็นตามตัวอักษร

ตัวอย่าง:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

คำศัพท์

ส่วนนี้ใช้คำศัพท์ที่เกี่ยวข้องกับ HIDL ต่อไปนี้:

ผูกมัด บ่งชี้ว่ากำลังใช้ HIDL สำหรับการเรียกโพรซีเดอร์ระยะไกลระหว่างกระบวนการ ใช้งานผ่านกลไกคล้าย Binder ดูเพิ่มเติมที่ ทาง ผ่าน
โทรกลับแบบอะซิงโครนัส อินเทอร์เฟซที่ให้บริการโดยผู้ใช้ HAL ส่งผ่านไปยัง HAL (ผ่านวิธี HIDL) และเรียกโดย HAL เพื่อส่งคืนข้อมูลเมื่อใดก็ได้
โทรกลับ, ซิงโครนัส ส่งกลับข้อมูลจากการใช้วิธีการ HIDL ของเซิร์ฟเวอร์ไปยังไคลเอนต์ ไม่ได้ใช้สำหรับวิธีการที่คืนค่าเป็นโมฆะหรือค่าดั้งเดิมเพียงค่าเดียว
ลูกค้า กระบวนการที่เรียกใช้เมธอดของอินเทอร์เฟซเฉพาะ กระบวนการ HAL หรือเฟรมเวิร์กอาจเป็นไคลเอ็นต์ของอินเทอร์เฟซหนึ่งและเซิร์ฟเวอร์ของอีกเซิร์ฟเวอร์หนึ่ง ดูเพิ่มเติมที่ ทาง ผ่าน
ยืดออก ระบุอินเทอร์เฟซที่เพิ่มวิธีการและ/หรือประเภทให้กับอินเทอร์เฟซอื่น อินเทอร์เฟซสามารถขยายอินเทอร์เฟซอื่นได้เพียงหนึ่งอินเทอร์เฟซ สามารถใช้สำหรับรุ่นรองที่เพิ่มขึ้นในชื่อแพ็คเกจเดียวกันหรือสำหรับแพ็คเกจใหม่ (เช่น ส่วนขยายของผู้ขาย) เพื่อสร้างบนแพ็คเกจที่เก่ากว่า
สร้าง ระบุเมธอดของอินเตอร์เฟสที่คืนค่าไปยังไคลเอนต์ ในการส่งคืนค่าที่ไม่ใช่ค่าพื้นฐาน หรือมากกว่า 1 ค่า ฟังก์ชันการเรียกกลับแบบซิงโครนัสจะถูกสร้างขึ้น
อินเตอร์เฟซ การรวบรวมวิธีการและประเภท แปลเป็นคลาสในภาษา C++ หรือ Java เมธอดทั้งหมดในอินเทอร์เฟซถูกเรียกไปในทิศทางเดียวกัน: กระบวนการไคลเอนต์เรียกใช้วิธีการที่ดำเนินการโดยกระบวนการเซิร์ฟเวอร์
ทางเดียว เมื่อนำไปใช้กับวิธี HIDL แสดงว่าวิธีการนั้นไม่มีค่าและไม่บล็อก
บรรจุุภัณฑ์ การรวบรวมอินเทอร์เฟซและประเภทข้อมูลที่ใช้เวอร์ชันร่วมกัน
ทะลุผ่าน โหมดของ HIDL ที่เซิร์ฟเวอร์เป็นไลบรารีที่ใช้ร่วมกัน dlopen ed โดยไคลเอนต์ ในโหมดส่งผ่าน ไคลเอนต์และเซิร์ฟเวอร์เป็นกระบวนการเดียวกันแต่แยกฐานรหัส ใช้เพื่อนำ codebase ดั้งเดิมมาสู่โมเดล HIDL เท่านั้น ดูเพิ่มเติม ที่ ผูกมัด
เซิร์ฟเวอร์ กระบวนการที่ใช้วิธีการของอินเทอร์เฟซ ดูเพิ่มเติมที่ ทาง ผ่าน
ขนส่ง โครงสร้างพื้นฐาน HIDL ที่ย้ายข้อมูลระหว่างเซิร์ฟเวอร์และไคลเอนต์
รุ่น เวอร์ชันของแพ็คเกจ ประกอบด้วยจำนวนเต็มสองจำนวนหลักและรอง เวอร์ชันรองที่เพิ่มขึ้นอาจเพิ่ม (แต่ไม่เปลี่ยนแปลง) ประเภทและวิธีการ