หน้านี้จะอธิบายวิธีลงทะเบียนและสำรวจบริการและวิธีส่ง
ข้อมูลไปยังบริการโดยวิธีการเรียกใช้ที่กำหนดไว้ในอินเทอร์เฟซใน .hal
ลงทะเบียนบริการ
ลงทะเบียนเซิร์ฟเวอร์อินเทอร์เฟซ HIDL (ออบเจ็กต์ที่ใช้อินเทอร์เฟซ) ได้ ว่าเป็นบริการที่มีชื่อ ชื่อที่จดทะเบียนไม่จำเป็นต้องเกี่ยวข้องกับอินเทอร์เฟซหรือ ชื่อแพ็กเกจ หากไม่ได้ระบุชื่อไว้ จะมีชื่อว่า "ค่าเริ่มต้น" ควร ใช้สำหรับ HAL ที่ไม่จำเป็นต้องลงทะเบียนเป็นการใช้งาน 2 แบบ ของ Google ตัวอย่างเช่น การเรียก C++ สำหรับการลงทะเบียนบริการที่กำหนดไว้ในแต่ละ คือ
status_t status = myFoo->registerAsService(); status_t anotherStatus = anotherFoo->registerAsService("another_foo_service"); // if needed
เวอร์ชันของอินเทอร์เฟซ HIDL จะรวมอยู่ในตัวอินเทอร์เฟซเอง ใช่เลย
เชื่อมโยงโดยอัตโนมัติกับการลงทะเบียนบริการ และสามารถดึงข้อมูลผ่าน
การเรียกเมธอด (android::hardware::IInterface::getInterfaceVersion()
)
ในทุกอินเทอร์เฟซ HIDL ออบเจ็กต์เซิร์ฟเวอร์ไม่จำเป็นต้องลงทะเบียนและสามารถส่งได้
ผ่านพารามิเตอร์เมธอด HIDL ไปยังกระบวนการอื่นที่ทำให้เรียกใช้เมธอด HIDL
ไว้ในเซิร์ฟเวอร์
สำรวจบริการ
คำขอตามโค้ดของไคลเอ็นต์สร้างขึ้นสำหรับอินเทอร์เฟซที่กำหนด ตามชื่อและ
โดยเรียก getService
ในคลาส HAL ที่ต้องการ:
// C++ sp<V1_1::IFooService> service = V1_1::IFooService::getService(); sp<V1_1::IFooService> alternateService = V1_1::IFooService::getService("another_foo_service"); // Java V1_1.IFooService service = V1_1.IFooService.getService(true /* retry */); V1_1.IFooService alternateService = V1_1.IFooService.getService("another", true /* retry */);
อินเทอร์เฟซ HIDL แต่ละเวอร์ชันถือเป็นอินเทอร์เฟซที่แยกจากกัน ดังนั้น
IFooService
เวอร์ชัน 1.1 และ IFooService
เวอร์ชัน 2.2
สามารถลงทะเบียนเป็น "foo_service" ทั้งคู่ และ
getService("foo_service")
ในอินเทอร์เฟซใดอินเทอร์เฟซหนึ่งจะได้รับการลงทะเบียน
สำหรับอินเทอร์เฟซนั้น ดังนั้นในกรณีส่วนใหญ่จึงไม่จำเป็นต้องมีพารามิเตอร์ชื่อ
ได้รับเพื่อการลงทะเบียนหรือการค้นพบ (หมายถึงชื่อ "ค่าเริ่มต้น")
นอกจากนี้ ออบเจ็กต์อินเทอร์เฟซผู้ให้บริการยังมีส่วนในวิธีการขนส่งของ
อินเทอร์เฟซที่แสดงกลับมา สำหรับอินเทอร์เฟซ IFoo
ในแพ็กเกจ
android.hardware.foo@1.0
แสดงอินเทอร์เฟซโดย
IFoo::getService
จะใช้วิธีการรับส่งข้อมูลที่ประกาศไว้เสมอสำหรับ
android.hardware.foo
ในไฟล์ Manifest ของอุปกรณ์หากมีรายการนั้น
และหากวิธี Transport ไม่พร้อมใช้งาน ระบบจะแสดงผล nullptr
ในบางกรณี คุณอาจจำเป็นต้องดำเนินการต่อทันทีแม้จะไม่มี
กำลังรับบริการ กรณีนี้อาจเกิดขึ้นได้ (ตัวอย่างเช่น) เมื่อลูกค้าต้องการ
จัดการการแจ้งเตือนบริการด้วยตนเอง หรือในโปรแกรมการวินิจฉัย (เช่น
atrace
) ซึ่งต้องได้รับ Hwservices ทั้งหมดและเรียกดู ใน
ในกรณีนี้ มีการระบุ API เพิ่มเติม เช่น tryGetService
ใน C++ หรือ
getService("instance-name", false)
ใน Java API เดิม
ต้องใช้ getService
ที่ให้ไว้ใน Java กับบริการ
การแจ้งเตือน การใช้ API นี้ไม่ได้หลีกเลี่ยงเงื่อนไขการแข่งขันที่เซิร์ฟเวอร์
ลงทะเบียนตัวเองหลังจากที่ไคลเอ็นต์ส่งคำขอโดยใช้ API ที่ไม่ทดลองซ้ำรายการใดรายการหนึ่งเหล่านี้
การแจ้งเตือนการเสียชีวิตของบริการ
ลูกค้าที่ต้องการรับการแจ้งเตือนเมื่อบริการเสียชีวิตอาจได้รับการเสียชีวิต ที่ส่งมาตามเฟรมเวิร์ก หากต้องการรับการแจ้งเตือน ลูกค้า ต้อง
- คลาสย่อยของคลาส/อินเทอร์เฟซ HIDL
hidl_death_recipient
(ใน C++ ไม่ใช่ใน HIDL) - ลบล้างเมธอด
serviceDied()
ของเมธอด - สร้างอินสแตนซ์ออบเจ็กต์ของคลาสย่อย
hidl_death_recipient
- เรียกใช้เมธอด
linkToDeath()
ในบริการเพื่อตรวจสอบ ส่งในออบเจ็กต์อินเทอร์เฟซของIDeathRecipient
โปรดทราบว่า วิธีการนี้ไม่ถือครองกรรมสิทธิ์ของผู้รับที่เสียชีวิตหรือผู้รับมอบอำนาจที่ผู้รับมอบสิทธิ์นั้น จะถูกเรียก
ตัวอย่าง Pseudocode (C++ และ Java มีความคล้ายคลึงกัน)
class IMyDeathReceiver : hidl_death_recipient { virtual void serviceDied(uint64_t cookie, wp<IBase>& service) override { log("RIP service %d!", cookie); // Cookie should be 42 } }; .... IMyDeathReceiver deathReceiver = new IMyDeathReceiver(); m_importantService->linkToDeath(deathReceiver, 42);
ผู้รับเสียชีวิตรายเดียวกันสามารถลงทะเบียนในหลายบริการได้
การโอนข้อมูล
สามารถส่งข้อมูลไปยังบริการได้โดยวิธีการเรียกใช้ที่กำหนดไว้ในอินเทอร์เฟซใน
.hal
ไฟล์ โดยมีวิธีการ 2 ประเภทดังนี้
- การบล็อกจะรอจนกว่าเซิร์ฟเวอร์จะสร้าง ผลลัพธ์
- วิธีการแบบทางเดียวจะส่งข้อมูลในทิศทางเดียวเท่านั้น และไม่ส่งข้อมูล บล็อก หากปริมาณข้อมูลที่กำลังทำงานอยู่ในการเรียกใช้ RPC เกินการใช้งาน ขีดจำกัด การเรียกอาจบล็อกหรือส่งคืนสัญญาณระบุข้อผิดพลาด (ลักษณะการทำงานคือ ยังไม่ได้ระบุ)
เมธอดที่ไม่แสดงผลค่าแต่ไม่ได้ประกาศว่าเป็น
oneway
ยังบล็อกอยู่
เมธอดทั้งหมดที่ประกาศในอินเทอร์เฟซ HIDL จะเรียกในทิศทางเดียว จาก HAL หรือ HAL ก็ได้ อินเทอร์เฟซไม่ได้ระบุว่า ทิศทางที่เรียกใช้ สถาปัตยกรรมที่ต้องมีการเรียกเพื่อเริ่มต้น HAL ควรมีอินเทอร์เฟซ 2 แบบ (หรือมากกว่า) ในแพ็กเกจ HAL และแสดง ที่เหมาะสมจากแต่ละกระบวนการ คำว่า client และ server จะใช้ตามทิศทางการเรียกของอินเทอร์เฟซ (กล่าวคือ HAL อาจเป็นเซิร์ฟเวอร์ของอินเทอร์เฟซหนึ่งและไคลเอ็นต์ของอีกอินเทอร์เฟซหนึ่ง อินเทอร์เฟซ)
Callback
คำว่า callback หมายถึงแนวคิด 2 แบบที่แตกต่างกัน โดยแยกตาม synchronous Callback และ asynchronous Callback
การติดต่อกลับแบบซิงโครนัสใช้ในเมธอด HIDL บางอย่างที่ให้ผลลัพธ์ เมธอด HIDL ที่แสดงค่ามากกว่า 1 ค่า (หรือแสดง 1 ค่าของ ไม่ใช่ประเภทพื้นฐาน) จะแสดงผลลัพธ์ผ่านฟังก์ชัน Callback หากมีเพียงรายการเดียว แสดงผลและเป็นประเภทพื้นฐาน จะไม่มีการใช้ Callback และ จะแสดงผลจากเมธอด เซิร์ฟเวอร์จะนำวิธีการ HIDL ไปใช้และ ไคลเอ็นต์จะใช้ Callback
การติดต่อกลับแบบไม่พร้อมกันทำให้เซิร์ฟเวอร์ของอินเทอร์เฟซ HIDL ดำเนินการต่อไปนี้ได้
ทำให้เกิดการโทร ซึ่งทำได้โดยการส่งผ่านอินสแตนซ์ของอินเทอร์เฟซที่ 2
ผ่านอินเทอร์เฟซแรก ไคลเอ็นต์ของอินเทอร์เฟซแรกต้องทำหน้าที่เป็น
ของคนที่ 2 เซิร์ฟเวอร์ของอินเทอร์เฟซแรกสามารถเรียกใช้เมธอดใน
ออบเจ็กต์อินเทอร์เฟซที่ 2 ตัวอย่างเช่น การใช้งาน HAL สามารถส่งข้อมูล
แบบไม่พร้อมกันกลับไปยังกระบวนการที่กำลังใช้งานอยู่ด้วยการเรียกใช้เมธอดใน
ที่สร้างและแสดงโดยกระบวนการนั้น วิธีการในอินเทอร์เฟซที่ใช้
สำหรับการติดต่อกลับแบบไม่พร้อมกันอาจบล็อก (และอาจส่งคืนค่าไปยังผู้โทร)
หรือ oneway
ตัวอย่างเช่น โปรดดู "การติดต่อกลับแบบไม่พร้อมกัน" ใน
HIDL C++
เพื่อให้การเป็นเจ้าของหน่วยความจำง่ายขึ้น การเรียกเมธอดและ Callback จะใช้เพียง
มีพารามิเตอร์ in
รายการและไม่รองรับ out
หรือ
inout
พารามิเตอร์
ขีดจำกัดต่อธุรกรรม
ระบบไม่ได้กำหนดขีดจำกัดต่อธุรกรรมให้กับจำนวนข้อมูลที่ส่งใน HIDL
เมธอดและ Callback อย่างไรก็ตาม การโทรที่เกิน 4KB ต่อธุรกรรม
ถือว่าเกินความจำเป็น หากคุณเห็นข้อความนี้ ให้ลองปรับอินเทอร์เฟซ HIDL ใหม่อีกครั้ง
แนะนำ ข้อจำกัดอีกประการหนึ่งคือทรัพยากรที่มีให้สำหรับ HIDL
เพื่อรองรับการทำธุรกรรมหลายรายการพร้อมกัน หลายสกุลเงิน
ธุรกรรมอาจอยู่ระหว่างดำเนินการพร้อมกันเนื่องจากมีชุดข้อความหลายรายการ หรือ
กระบวนการส่งการโทรไปยังกระบวนการหรือการเรียก oneway
หลายครั้งที่
ไม่ได้รับการจัดการอย่างรวดเร็วจากกระบวนการรับ พื้นที่รวมสูงสุด
ใช้ได้กับการทำธุรกรรมพร้อมกันทั้งหมดคือ 1MB โดยค่าเริ่มต้น
ในอินเทอร์เฟซที่ออกแบบมาอย่างดี การใช้เกินขีดจำกัดทรัพยากรเหล่านี้ เกิดขึ้น หากเกิน การโทรที่เกินเกณฑ์อาจบล็อกจนกว่า ทรัพยากรพร้อมใช้งานหรือเป็นสัญญาณแสดงข้อผิดพลาดในการขนส่ง การแสดงแต่ละครั้งของ เกินขีดจำกัดต่อธุรกรรม หรือมีทรัพยากรการใช้งาน HIDL ล้นโดย ข้อมูลรวมของธุรกรรมในการบินจะได้รับการบันทึกเพื่ออำนวยความสะดวกในการแก้ไขข้อบกพร่อง
การติดตั้งใช้งานเมธอด
HIDL สร้างไฟล์ส่วนหัวซึ่งระบุประเภท เมธอด และ Callback ในภาษาเป้าหมาย (C++ หรือ Java) ต้นแบบของ HIDL เมธอดและ Callback จะเหมือนกันสำหรับทั้งโค้ดของไคลเอ็นต์และเซิร์ฟเวอร์ HIDL ระบบให้บริการพร็อกซีสำหรับเมธอดใน ฝั่งผู้โทรที่จัดการข้อมูลสำหรับการส่ง IPC และ stub ในฝั่งผู้โทรซึ่งส่งผ่านข้อมูลไปยังการติดตั้งใช้งาน วิธีการ
ผู้โทรของฟังก์ชัน (เมธอด HIDL หรือ Callback) เป็นเจ้าของข้อมูล ที่ส่งผ่านไปยังฟังก์ชัน และยังคงเป็นเจ้าของหลังการโทร ใน ทุกกรณีที่ผู้โทรไม่จำเป็นต้องเพิ่มพื้นที่ว่างหรือปล่อยพื้นที่เก็บข้อมูล
- ใน C++ ข้อมูลอาจเป็นแบบอ่านอย่างเดียว (การพยายามเขียนข้อมูลอาจทำให้เกิด ความผิดพลาดของการแบ่งกลุ่มลูกค้า) และสามารถใช้ได้ตลอดระยะเวลาการโทร ลูกค้าสามารถ คัดลอกข้อมูลให้แพร่หลายไปมากกว่าการโทร
- ใน Java โค้ดจะได้รับสำเนาข้อมูลในเครื่อง (ออบเจ็กต์ Java ปกติ) ซึ่งอาจเก็บและแก้ไข หรืออนุญาตให้เก็บขยะได้
การโอนข้อมูลที่ไม่ใช่ RPC
HIDL มี 2 วิธีในการโอนข้อมูลโดยไม่ต้องใช้การเรียก RPC ได้แก่แบบที่แชร์ หน่วยความจำและคิวข้อความด่วน (FMQ) ทั้ง 2 อย่างนี้รองรับเฉพาะใน C++ เท่านั้น
- ความทรงจำที่แชร์ ประเภท HIDL ในตัวคือ
memory
ใช้เพื่อส่งผ่านออบเจ็กต์ที่แสดงถึงหน่วยความจำที่ใช้ร่วมกันซึ่งได้รับการจัดสรรแล้ว ใช้ในกระบวนการรับข้อมูลเพื่อแมปหน่วยความจำที่แชร์ได้ - Fast Message Queue (FMQ) HIDL จะแสดงข้อความที่ใช้เทมเพลต
ประเภทคิวที่ใช้การส่งผ่านข้อความโดยไม่ต้องรอ ไม่ได้ใช้เคอร์เนล
หรือเครื่องจัดตารางเวลาในโหมดส่งผ่านหรือโหมด Binderized (การสื่อสารระหว่างอุปกรณ์ไม่
มีคุณสมบัติเหล่านี้) ตามปกติ HAL จะเป็นผู้ตั้งค่าช่วงท้ายของคิว
การสร้างออบเจ็กต์ที่สามารถส่งผ่าน RPC ผ่านพารามิเตอร์ในตัว
HIDL ประเภท
MQDescriptorSync
หรือMQDescriptorUnsync
ช่วงเวลานี้ กระบวนการรับของออบเจ็กต์สามารถใช้เพื่อตั้งค่าปลายอีกด้านของคิวได้- ไม่อนุญาตให้เพิ่มคิวการซิงค์ และมีคิวได้เพียงรายการเดียวเท่านั้น ผู้อ่าน
- คิวยกเลิกการซิงค์จะได้รับอนุญาตให้ล้นเกิน และสามารถมีโปรแกรมอ่านได้หลายคน ข้อมูลแต่ละประเภทจะต้องอ่านข้อมูลทันเวลาหรือสูญหาย
ดูรายละเอียดเพิ่มเติมเกี่ยวกับ FMQ ได้ที่ Fast Message Queue (FMQ)