Google is committed to advancing racial equity for Black communities. See how.
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

HIDL

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

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

ใช้โหมด passthrough

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

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

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

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

Binderizing passthrough HALs

คุณสามารถประสานการใช้งาน HAL ที่รองรับโหมด passthrough ด้วยอินเทอร์เฟซ 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 และ -Landroidbp-impl
  • abcd@MN::IFoo-service . เปิด passthrough HAL และลงทะเบียนตัวเองเป็นบริการที่มีการผูกมัดทำให้สามารถใช้งาน HAL เดียวกันได้ทั้งแบบส่งผ่านและแบบ binderized

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

HIDL ไวยากรณ์

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

หมายเหตุ: สำหรับรายละเอียดเกี่ยวกับสไตล์โค้ด HIDL โปรดดู Code Style Guide

  • /** */ ระบุความคิดเห็นของเอกสาร สิ่งเหล่านี้สามารถใช้ได้กับการประกาศประเภทเมธอดฟิลด์และ enum เท่านั้น
  • /* */ แสดงความคิดเห็นหลายบรรทัด
  • // ระบุความคิดเห็นที่ท้ายบรรทัด นอกเหนือจาก // แล้วขึ้นบรรทัดใหม่จะเหมือนกับช่องว่างอื่น ๆ
  • ในตัวอย่างไวยากรณ์ด้านล่างข้อความจาก // ถึงท้ายบรรทัดไม่ได้เป็นส่วนหนึ่งของไวยากรณ์ แต่เป็นการแสดงความคิดเห็นเกี่ยวกับไวยากรณ์แทน
  • [empty] หมายความว่าคำนั้นอาจว่างเปล่า
  • ? ตามตัวอักษรหรือคำหมายความว่าเป็นทางเลือก
  • ... แสดงลำดับที่มีรายการตั้งแต่ศูนย์ขึ้นไปโดยมีเครื่องหมายวรรคตอนคั่นตามที่ระบุ ไม่มีอาร์กิวเมนต์ตัวแปรใน HIDL
  • องค์ประกอบลำดับที่แยกกันด้วยจุลภาค
  • อัฒภาคจะยุติแต่ละองค์ประกอบรวมถึงองค์ประกอบสุดท้าย
  • UPPERCASE คือ nonterminal
  • italics คือตระกูลโทเค็นเช่น integer หรือ identifier (กฎการแยกวิเคราะห์มาตรฐาน C)
  • constexpr คือนิพจน์คงที่สไตล์ C (เช่น 1 + 1 และ 1L << 3 )
  • import_name เป็นชื่อแพ็กเกจหรืออินเทอร์เฟซซึ่งมีคุณสมบัติตามที่อธิบายไว้ใน การกำหนดเวอร์ชัน HIDL
  • 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 ดูเพิ่มเติม passthrough
โทรกลับแบบอะซิงโครนัส อินเทอร์เฟซที่ให้บริการโดยผู้ใช้ HAL ส่งผ่านไปยัง HAL (ผ่านวิธี HIDL) และเรียกโดย HAL เพื่อส่งคืนข้อมูลได้ตลอดเวลา
โทรกลับซิงโครนัส ส่งคืนข้อมูลจากการใช้งานเมธอด HIDL ของเซิร์ฟเวอร์ไปยังไคลเอนต์ ไม่ได้ใช้สำหรับเมธอดที่คืนค่าโมฆะหรือค่าดั้งเดิมเพียงค่าเดียว
ลูกค้า กระบวนการที่เรียกใช้เมธอดของอินเทอร์เฟซเฉพาะ กระบวนการ HAL หรือเฟรมเวิร์กอาจเป็นไคลเอนต์ของอินเทอร์เฟซหนึ่งและเซิร์ฟเวอร์ของอีกเซิร์ฟเวอร์หนึ่ง ดูเพิ่มเติม passthrough
ขยาย ระบุอินเตอร์เฟสที่เพิ่มเมธอดและ / หรือชนิดให้กับอินเทอร์เฟซอื่น อินเทอร์เฟซสามารถขยายอินเทอร์เฟซอื่นได้เพียงหนึ่งรายการ สามารถใช้สำหรับการเพิ่มเวอร์ชันรองในชื่อแพ็กเกจเดียวกันหรือสำหรับแพ็กเกจใหม่ (เช่นส่วนขยายผู้จำหน่าย) เพื่อสร้างแพ็กเกจรุ่นเก่า
สร้าง ระบุวิธีการเชื่อมต่อที่ส่งคืนค่าให้กับไคลเอ็นต์ หากต้องการส่งคืนค่าที่ไม่ใช่ค่าดั้งเดิมหนึ่งค่าหรือมากกว่าหนึ่งค่าฟังก์ชันการเรียกกลับแบบซิงโครนัสจะถูกสร้างขึ้น
อินเตอร์เฟซ การรวบรวมวิธีการและประเภท แปลเป็นคลาสใน C ++ หรือ Java วิธีการทั้งหมดในอินเทอร์เฟซถูกเรียกไปในทิศทางเดียวกัน: กระบวนการไคลเอ็นต์เรียกใช้เมธอดที่ดำเนินการโดยกระบวนการเซิร์ฟเวอร์
ทางเดียว เมื่อนำไปใช้กับเมธอด HIDL ระบุว่าเมธอดส่งคืนค่าและไม่บล็อก
แพ็คเกจ การรวบรวมอินเทอร์เฟซและชนิดข้อมูลที่แชร์เวอร์ชัน
ทะลุผ่าน โหมดของ HIDL ซึ่งเซิร์ฟเวอร์เป็นไลบรารีแบบแบ่งใช้โดยไคลเอนต์ dlopen ed ในโหมด passthrough ไคลเอนต์และเซิร์ฟเวอร์เป็นกระบวนการเดียวกัน แต่แยกโค้ดเบส ใช้เพื่อนำโค้ดพื้นฐานมาสู่โมเดล HIDL เท่านั้น ดู Binderized ด้วย
เซิร์ฟเวอร์ กระบวนการที่ใช้เมธอดของอินเทอร์เฟซ ดูเพิ่มเติม passthrough
ขนส่ง โครงสร้างพื้นฐาน HIDL ที่ย้ายข้อมูลระหว่างเซิร์ฟเวอร์และไคลเอนต์
รุ่น เวอร์ชันของแพ็คเกจ ประกอบด้วยจำนวนเต็มสองจำนวนหลักและรอง การเพิ่มเวอร์ชันรองอาจเพิ่มประเภทและวิธีการ (แต่ไม่เปลี่ยนแปลง)