Android มี Hardware Abstraction Layer (HAL) ของ HIDL สำหรับยานยนต์ที่ รองรับการจับภาพและแสดงภาพตั้งแต่ช่วงแรกๆ ของกระบวนการบูต Android และจะทำงานต่อไปตลอดอายุการใช้งานของระบบ HAL มีสแต็กระบบมุมมองภายนอก (EVS) และโดยทั่วไปจะใช้เพื่อรองรับกล้องมองหลังและจอแสดงผลภาพรอบทิศทางในยานพาหนะที่มีระบบสาระบันเทิงในรถยนต์ (IVI) ที่ใช้ Android นอกจากนี้ EVS ยังช่วยให้สามารถใช้ฟีเจอร์ขั้นสูง ในแอปของผู้ใช้ได้ด้วย
นอกจากนี้ Android ยังมีอินเทอร์เฟซไดรเวอร์การจับภาพและการแสดงผลเฉพาะ EVS (ใน /hardware/interfaces/automotive/evs/1.0
) แม้ว่าคุณจะสร้างแอปกล้องมองหลังบนบริการกล้องและการแสดงผลที่มีอยู่ของ Android
ได้ แต่แอปดังกล่าวอาจทำงานช้าเกินไปในกระบวนการบูตของ Android
การใช้ HAL เฉพาะจะช่วยให้มีอินเทอร์เฟซที่คล่องตัว
และทำให้ทราบอย่างชัดเจนว่า OEM ต้องใช้การติดตั้งใช้งานใดเพื่อรองรับสแต็ก EVS
ส่วนประกอบของระบบ
EVS ประกอบด้วยคอมโพเนนต์ของระบบต่อไปนี้

แอป EVS
แอป EVS ใน C++ ตัวอย่าง
(/packages/services/Car/evs/app
) ทำหน้าที่เป็นข้อมูลอ้างอิง
การใช้งาน แอปนี้มีหน้าที่ขอเฟรมวิดีโอจาก
EVS Manager และส่งเฟรมที่เสร็จสมบูรณ์เพื่อแสดงกลับไปยัง EVS Manager
โดยคาดว่า init จะเริ่มทำงานทันทีที่ EVS และ Car Service พร้อมใช้งาน
ซึ่งมีเป้าหมายภายใน 2 วินาทีหลังจากเปิดเครื่อง OEM สามารถแก้ไขหรือแทนที่แอป EVS
ได้ตามต้องการ
EVS Manager
EVS Manager (/packages/services/Car/evs/manager
) มี
องค์ประกอบพื้นฐานที่แอป EVS ต้องใช้เพื่อติดตั้งใช้งานทุกอย่างตั้งแต่
การแสดงกล้องมองหลังอย่างง่ายไปจนถึงการแสดงผลแบบหลายกล้อง 6DOF อินเทอร์เฟซ
ของอุปกรณ์จะแสดงผ่าน HIDL และสร้างขึ้นเพื่อรองรับไคลเอ็นต์หลายรายพร้อมกัน
แอปและบริการอื่นๆ (โดยเฉพาะบริการรถยนต์) สามารถค้นหาสถานะของ EVS
Manager เพื่อดูว่าระบบ EVS ทำงานอยู่เมื่อใด
อินเทอร์เฟซ HIDL ของ EVS
ระบบ EVS ทั้งกล้องและองค์ประกอบการแสดงผลจะกำหนดไว้ในแพ็กเกจ android.hardware.automotive.evs
การติดตั้งใช้งานตัวอย่าง
ที่ใช้ประโยชน์จากอินเทอร์เฟซ (สร้างรูปภาพทดสอบสังเคราะห์และตรวจสอบว่า
รูปภาพไปและกลับ) มีให้ใน
/hardware/interfaces/automotive/evs/1.0/default
OEM มีหน้าที่ติดตั้งใช้งาน API ที่แสดงโดยไฟล์ .hal
ใน /hardware/interfaces/automotive/evs
การติดตั้งใช้งานดังกล่าวมีหน้าที่กำหนดค่าและรวบรวมข้อมูลจากกล้องจริง รวมถึงส่งข้อมูลผ่านบัฟเฟอร์หน่วยความจำที่ใช้ร่วมกันซึ่ง Gralloc รู้จัก ฝั่งจอแสดงผลของการติดตั้งใช้งานมีหน้าที่จัดเตรียมบัฟเฟอร์หน่วยความจำที่ใช้ร่วมกัน
ซึ่งแอปสามารถเติมได้ (โดยปกติจะใช้การแสดงผล EGL) และแสดง
เฟรมที่เสร็จสมบูรณ์ก่อนสิ่งอื่นใดที่อาจต้องการปรากฏบน
จอแสดงผลจริง การติดตั้งใช้งานอินเทอร์เฟซ EVS ของผู้ให้บริการอาจจัดเก็บไว้ใน /vendor/… /device/…
หรือ hardware/…
(เช่น
/hardware/[vendor]/[platform]/evs
)
ไดรเวอร์เคอร์เนล
อุปกรณ์ที่รองรับสแต็ก EVS ต้องใช้ไดรเวอร์เคอร์เนล OEM มีตัวเลือกในการรองรับฟีเจอร์ที่ EVS กำหนดผ่าน
ไดรเวอร์ฮาร์ดแวร์กล้องหรือจอแสดงผลที่มีอยู่แทนการ
สร้างไดรเวอร์ใหม่ การใช้ไดรเวอร์ซ้ำอาจเป็นประโยชน์ โดยเฉพาะไดรเวอร์ Display ที่การนำเสนอรูปภาพอาจต้องประสานงานกับเธรดอื่นๆ ที่ทำงานอยู่ Android 8.0 มีไดรเวอร์ตัวอย่างที่อิงตาม v4l2 (ใน packages/services/Car/evs/sampleDriver
) ซึ่ง
ขึ้นอยู่กับเคอร์เนลสำหรับการรองรับ v4l2 และขึ้นอยู่กับ SurfaceFlinger สำหรับการนำเสนอ
รูปภาพเอาต์พุต
คำอธิบายอินเทอร์เฟซฮาร์ดแวร์ EVS
ส่วนนี้อธิบาย HAL ผู้ให้บริการควรจัดหา การใช้งาน API นี้ที่ปรับให้เหมาะกับฮาร์ดแวร์ของตน
IEvsEnumerator
ออบเจ็กต์นี้มีหน้าที่แสดงรายการฮาร์ดแวร์ EVS ที่พร้อมใช้งานใน ระบบ (กล้องอย่างน้อย 1 ตัวและอุปกรณ์แสดงผล 1 เครื่อง)
getCameraList() generates (vec<CameraDesc> cameras);
แสดงเวกเตอร์ที่มีคำอธิบายสำหรับกล้องทั้งหมดในระบบ ระบบ
ถือว่าชุดกล้องคงที่และทราบได้ในเวลาบูต ดูรายละเอียดเกี่ยวกับ
คำอธิบายกล้องได้ที่ CameraDesc
openCamera(string camera_id) generates (IEvsCamera camera);
รับออบเจ็กต์อินเทอร์เฟซที่ใช้โต้ตอบกับกล้องที่เฉพาะเจาะจง
ซึ่งระบุโดยสตริง camera_id ที่ไม่ซ้ำ แสดงผล NULL เมื่อล้มเหลว
ความพยายามที่จะเปิดกล้องที่เปิดอยู่แล้วจะสำเร็จเสมอ หากต้องการหลีกเลี่ยงสภาวะแข่งขันที่เกี่ยวข้องกับการเริ่มต้นและปิดแอป การเปิดกล้องอีกครั้งควรปิดอินสแตนซ์ก่อนหน้าเพื่อให้คำขอใหม่ดำเนินการได้ อินสแตนซ์กล้องที่ถูกขัดจังหวะด้วยวิธีนี้ต้องอยู่ในสถานะไม่ได้ใช้งาน
รอการทำลายขั้นสุดท้ายและตอบสนองต่อคำขอใดๆ ที่ส่งผลต่อ
สถานะกล้องด้วยรหัสคืนค่า OWNERSHIP_LOST
closeCamera(IEvsCamera camera);
ปล่อยอินเทอร์เฟซ IEvsCamera (และเป็นส่วนตรงข้ามของ
openCamera()
) ต้องหยุดสตรีมวิดีโอจากกล้องโดยการเรียกใช้ stopVideoStream()
ก่อนเรียกใช้ closeCamera
openDisplay() generates (IEvsDisplay display);
รับออบเจ็กต์อินเทอร์เฟซที่ใช้เพื่อโต้ตอบกับจอแสดงผล EVS ของระบบโดยเฉพาะ
มีไคลเอ็นต์ได้เพียงรายเดียวเท่านั้นที่สามารถมีอินสแตนซ์ที่ใช้งานได้ของ IEvsDisplay ในเวลาใดก็ตาม เช่นเดียวกับลักษณะการเปิดที่รวดเร็วที่อธิบายไว้ใน openCamera
ระบบอาจสร้างออบเจ็กต์ IEvsDisplay ใหม่ได้ทุกเมื่อและปิดใช้อินสแตนซ์ก่อนหน้า
อินสแตนซ์ที่ถูกทำให้ใช้ไม่ได้จะยังคงอยู่และตอบสนองต่อการเรียกใช้ฟังก์ชัน
จากเจ้าของ แต่ต้องไม่ดำเนินการเปลี่ยนแปลงใดๆ เมื่อไม่ได้ใช้งาน ในที่สุด
แอปไคลเอ็นต์ควรสังเกตรหัสข้อผิดพลาด OWNERSHIP_LOST
ที่ส่งคืน ปิด และปล่อยอินเทอร์เฟซที่ไม่ได้ใช้งาน
closeDisplay(IEvsDisplay display);
ปล่อยอินเทอร์เฟซ IEvsDisplay (และตรงข้ามกับ
openDisplay()
) ต้องส่งคืนบัฟเฟอร์ที่ค้างอยู่ซึ่งได้รับพร้อมกับ
getTargetBuffer()
ไปยังจอแสดงผลก่อน
ปิดจอแสดงผล
getDisplayState() generates (DisplayState state);
รับสถานะการแสดงผลปัจจุบัน การติดตั้งใช้งาน HAL ควรรายงาน
สถานะปัจจุบันที่แท้จริง ซึ่งอาจแตกต่างจากสถานะที่ขอครั้งล่าสุด
ตรรกะที่รับผิดชอบในการเปลี่ยนสถานะการแสดงผลควรอยู่เหนือเลเยอร์อุปกรณ์ ซึ่งทำให้การติดตั้งใช้งาน HAL ไม่ควรเปลี่ยนสถานะการแสดงผลโดยพลการ หากไม่มีไคลเอ็นต์ใดถือครองจอแสดงผลในขณะนี้ (โดยการเรียกใช้
openDisplay) ฟังก์ชันนี้จะแสดงผลเป็น NOT_OPEN
หรือจะรายงานสถานะปัจจุบันของจอแสดงผล EVS ก็ได้ (ดูIEvsDisplay API)
struct CameraDesc { string camera_id; int32 vendor_flags; // Opaque value }
camera_id
สตริงที่ระบุกล้องที่กำหนดแบบไม่ซ้ำ อาจเป็นชื่ออุปกรณ์เคอร์เนลของอุปกรณ์หรือชื่อสำหรับอุปกรณ์ เช่น rearview การติดตั้งใช้งาน HAL จะเลือกค่าสำหรับสตริงนี้ และสแต็กด้านบนจะใช้ค่านี้อย่างไม่โปร่งใสvendor_flags
วิธีส่งข้อมูลกล้องเฉพาะทาง แบบทึบแสงจากไดรเวอร์ไปยังแอป EVS ที่กำหนดเอง โดยจะส่ง โดยไม่มีการตีความจากไดรเวอร์ไปยังแอป EVS ซึ่งสามารถเลือกที่จะไม่สนใจ ได้
IEvsCamera
ออบเจ็กต์นี้แสดงถึงกล้องเดียวและเป็นอินเทอร์เฟซหลักสำหรับ การจับภาพ
getCameraInfo() generates (CameraDesc info);
ส่งคืน CameraDesc
ของกล้องนี้
setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);
ระบุความลึกของห่วงโซ่บัฟเฟอร์ที่ระบบขอให้กล้องรองรับ ไคลเอ็นต์ของ IEvsCamera อาจเก็บเฟรมได้สูงสุดเท่านี้พร้อมกัน หากมีการส่งเฟรมจำนวนนี้ไปยังเครื่องรับโดยที่
doneWithFrame
ไม่ได้ส่งเฟรมกลับมา สตรีมจะข้ามเฟรมจนกว่าจะมีการส่งบัฟเฟอร์กลับมา
เพื่อนำไปใช้ซ้ำ การเรียกนี้สามารถเกิดขึ้นได้ทุกเมื่อ แม้ในขณะที่สตรีมกำลังทำงานอยู่ ซึ่งในกรณีนี้ควรเพิ่มหรือนำบัฟเฟอร์ออกจากเชนตามความเหมาะสม หากไม่มีการเรียกไปยังจุดแรกเข้านี้ IEvsCamera จะรองรับ
อย่างน้อย 1 เฟรมโดยค่าเริ่มต้น และรองรับได้มากขึ้น
หากไม่สามารถรองรับ bufferCount ที่ขอได้ ฟังก์ชันจะแสดงผล
BUFFER_NOT_AVAILABLE
หรือรหัสข้อผิดพลาดอื่นๆ ที่เกี่ยวข้อง ในกรณีนี้
ระบบจะยังคงทำงานด้วยค่าที่ตั้งไว้ก่อนหน้านี้
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
ขอให้ส่งเฟรมกล้อง EVS จากกล้องนี้ IEvsCameraStream
จะเริ่มรับการเรียกเป็นระยะๆ พร้อมเฟรมรูปภาพใหม่จนกว่าจะมีการเรียก
stopVideoStream()
ต้องเริ่มส่งเฟรม
ภายใน 500 มิลลิวินาทีหลังจากเรียกใช้ startVideoStream
และหลังจากเริ่มแล้ว ต้อง
สร้างเฟรมอย่างน้อย 10 FPS เวลาที่ต้องใช้ในการเริ่มสตรีมวิดีโอจะนับรวมกับข้อกำหนดเวลาเริ่มต้นของกล้องมองหลัง หากไม่ได้เริ่มสตรีม จะต้องแสดงรหัสข้อผิดพลาด มิฉะนั้นจะแสดง "ตกลง"
oneway doneWithFrame(BufferDesc buffer);
แสดงผลเฟรมที่ส่งโดย IEvsCameraStream เมื่อใช้เฟรมที่ส่งไปยังอินเทอร์เฟซ IEvsCameraStream เสร็จแล้ว ต้องส่งเฟรมกลับไปยัง IEvsCamera เพื่อนำไปใช้ซ้ำ
มีบัฟเฟอร์จำนวนจำกัดเล็กๆ
พร้อมใช้งาน (อาจมีเพียง 1 รายการ) และหากบัฟเฟอร์หมด ระบบจะไม่ส่ง
เฟรมเพิ่มเติมจนกว่าจะมีการส่งคืนบัฟเฟอร์ ซึ่งอาจส่งผลให้
เฟรมถูกข้ามไป (บัฟเฟอร์ที่มีแฮนเดิลเป็น Null จะแสดงถึงจุดสิ้นสุดของสตรีมและ
ไม่จำเป็นต้องส่งคืนผ่านฟังก์ชันนี้) แสดงผล OK เมื่อสำเร็จ หรือรหัสข้อผิดพลาดที่เหมาะสมซึ่งอาจรวมถึง INVALID_ARG
หรือ BUFFER_NOT_AVAILABLE
stopVideoStream();
หยุดการแสดงเฟรมกล้อง EVS เนื่องจากการนำส่งเป็นแบบไม่พร้อมกัน เฟรมจึงอาจยังคงมาถึงอีกสักระยะหลังจากที่การเรียกนี้แสดงผล ต้องส่งคืนแต่ละเฟรมจนกว่าจะมีการส่งสัญญาณปิดสตรีมไปยัง
IEvsCameraStream การเรียก stopVideoStream
ในสตรีมที่หยุดไปแล้วหรือยังไม่เริ่มถือเป็นเรื่องที่ถูกต้องตามกฎหมาย ในกรณีดังกล่าว ระบบจะไม่สนใจการเรียก
getExtendedInfo(int32 opaqueIdentifier) generates (int32 value);
ขอข้อมูลเฉพาะไดรเวอร์จากการใช้งาน HAL ค่า
ที่อนุญาตสำหรับ opaqueIdentifier
จะขึ้นอยู่กับไดรเวอร์ แต่หากไม่มีค่า
ที่ส่งมา ไดรเวอร์อาจขัดข้อง ไดรเวอร์ควรแสดงผลเป็น 0 สำหรับ opaqueIdentifier
ที่ไม่รู้จัก
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
ส่งค่าเฉพาะของไดรเวอร์ไปยังการติดตั้งใช้งาน HAL ส่วนขยายนี้มีไว้เพื่ออำนวยความสะดวกในการใช้ส่วนขยายเฉพาะยานพาหนะเท่านั้น และการติดตั้งใช้งาน HAL ไม่ควรต้องใช้การเรียกนี้เพื่อให้ทำงานในสถานะเริ่มต้น หาก
ไดรเวอร์รู้จักและยอมรับค่า ควรแสดงผล OK ไม่เช่นนั้นควรแสดงผล
INVALID_ARG
หรือรหัสข้อผิดพลาดอื่นๆ ที่เป็นตัวแทน
struct BufferDesc { uint32 width; // Units of pixels uint32 height; // Units of pixels uint32 stride; // Units of pixels uint32 pixelSize; // Size of single pixel in bytes uint32 format; // May contain values from android_pixel_format_t uint32 usage; // May contain values from Gralloc.h uint32 bufferId; // Opaque value handle memHandle; // gralloc memory buffer handle }
อธิบายรูปภาพที่ส่งผ่าน API ไดรฟ์ HAL มีหน้าที่
กรอกข้อมูลในโครงสร้างนี้เพื่ออธิบายบัฟเฟอร์รูปภาพ และไคลเอ็นต์ HAL
ควรถือว่าโครงสร้างนี้เป็นแบบอ่านอย่างเดียว ฟิลด์มีข้อมูลเพียงพอ
ที่จะช่วยให้ไคลเอ็นต์สร้างออบเจ็กต์ ANativeWindowBuffer
ขึ้นใหม่ได้
ตามที่อาจจำเป็นต้องใช้รูปภาพกับ EGL ด้วยส่วนขยาย eglCreateImageKHR()
width
ความกว้างของรูปภาพที่แสดงเป็นพิกเซลheight
ความสูงเป็นพิกเซลของรูปภาพที่แสดงstride
. จำนวนพิกเซลที่แต่ละแถวใช้จริงในหน่วยความจำ โดยคำนึงถึงการเว้นวรรคใดๆ เพื่อการจัดแนวแถว แสดงเป็นพิกเซลเพื่อให้ตรงกับ รูปแบบที่ gralloc ใช้สำหรับคำอธิบายบัฟเฟอร์pixelSize
จำนวนไบต์ที่แต่ละพิกเซลใช้ ซึ่งช่วยให้คำนวณขนาดเป็นไบต์ที่จำเป็นต่อการเลื่อนระหว่างแถวใน รูปภาพได้ (stride
เป็นไบต์ =stride
เป็นพิกเซล *pixelSize
)format
รูปแบบพิกเซลที่รูปภาพใช้ รูปแบบที่ระบุ ต้องใช้ได้กับการติดตั้งใช้งาน OpenGL ของแพลตฟอร์ม หากต้องการผ่านการทดสอบความเข้ากันได้HAL_PIXEL_FORMAT_YCRCB_420_SP
ควรเป็นตัวเลือกที่ต้องการสำหรับการใช้งานกล้อง และRGBA
หรือBGRA
ควรเป็นตัวเลือกที่ต้องการสำหรับจอแสดงผลusage
. แฟล็กการใช้งานที่ตั้งค่าโดยการติดตั้งใช้งาน HAL ไคลเอ็นต์ HAL ควรส่งผ่านค่าเหล่านี้โดยไม่มีการแก้ไข (ดูรายละเอียดได้ที่Gralloc.h
แฟล็กที่เกี่ยวข้อง)bufferId
ค่าที่ไม่ซ้ำกันซึ่งการติดตั้งใช้งาน HAL ระบุเพื่อ อนุญาตให้ระบบจดจำบัฟเฟอร์ได้หลังจากไปกลับผ่าน HAL API การติดตั้งใช้งาน HAL อาจเลือกค่าที่จัดเก็บไว้ในฟิลด์นี้ได้โดยพลการmemHandle
แฮนเดิลสำหรับบัฟเฟอร์หน่วยความจำพื้นฐานที่มี ข้อมูลรูปภาพ การใช้งาน HAL อาจเลือกจัดเก็บแฮนเดิลบัฟเฟอร์ Gralloc ไว้ที่นี่
IEvsCameraStream
ไคลเอ็นต์จะใช้การเชื่อมต่อนี้เพื่อรับการนำส่งเฟรมวิดีโอแบบไม่พร้อมกัน
deliverFrame(BufferDesc buffer);
รับการเรียกจาก HAL ทุกครั้งที่เฟรมวิดีโอพร้อมสำหรับการตรวจสอบ
ต้องส่งคืนบัฟเฟอร์ที่จัดการโดยเมธอดนี้ผ่านการเรียก IEvsCamera::doneWithFrame()
เมื่อหยุดสตรีมวิดีโอด้วยการเรียกใช้ IEvsCamera::stopVideoStream()
คอลแบ็กนี้อาจทำงานต่อไป
ขณะที่ไปป์ไลน์ระบายข้อมูล คุณยังคงต้องส่งคืนแต่ละเฟรม เมื่อส่งเฟรมสุดท้าย
ในสตรีมแล้ว ระบบจะส่ง bufferHandle
ที่เป็น NULL
ซึ่งหมายถึงจุดสิ้นสุดของสตรีมและจะไม่มีการส่งเฟรมเพิ่มเติม ไม่จำเป็นต้องส่ง NULL
bufferHandle
กลับพร้อมกับ
doneWithFrame()
แต่ต้องส่งคืนแฮนเดิลอื่นๆ ทั้งหมด
แม้ว่าในทางเทคนิคแล้วจะใช้รูปแบบบัฟเฟอร์ที่เป็นกรรมสิทธิ์ได้ แต่การทดสอบความเข้ากันได้ กำหนดให้บัฟเฟอร์ต้องอยู่ในรูปแบบใดรูปแบบหนึ่งที่รองรับ 4 รูปแบบ ได้แก่ NV21 (YCrCb 4:2:0 Semi-Planar), YV12 (YCrCb 4:2:0 Planar), YUYV (YCrCb 4:2:2 Interleaved) RGBA (32 บิต R:G:B:x), BGRA (32 บิต B:G:R:x) รูปแบบที่เลือกต้องเป็นแหล่งที่มาของเท็กซ์เจอร์ GL ที่ถูกต้องในการใช้งาน GLES ของแพลตฟอร์ม
แอปไม่ควรอาศัยการจับคู่ใดๆ
ระหว่างฟิลด์ bufferId
กับ memHandle
ในโครงสร้าง BufferDesc
ค่า bufferId
เป็นค่าส่วนตัวสำหรับการติดตั้งใช้งานไดรเวอร์ HAL และอาจใช้ (และนำกลับมาใช้ใหม่)
ได้ตามความเหมาะสม
IEvsDisplay
ออบเจ็กต์นี้แสดงถึงจอแสดงผล EVS ควบคุมสถานะของจอแสดงผล และจัดการการนำเสนอรูปภาพจริง
getDisplayInfo() generates (DisplayDesc info);
แสดงข้อมูลพื้นฐานเกี่ยวกับจอแสดงผล EVS ที่ระบบจัดหาให้ (ดู DisplayDesc)
setDisplayState(DisplayState state) generates (EvsResult result);
กำหนดสถานะการแสดงผล ไคลเอ็นต์อาจตั้งค่าสถานะการแสดงผลเพื่อแสดงสถานะที่ต้องการ และการติดตั้งใช้งาน HAL ต้องยอมรับคำขอสำหรับสถานะใดก็ตามอย่างราบรื่นขณะอยู่ในสถานะอื่นๆ แม้ว่าการตอบสนองอาจเป็นการเพิกเฉยต่อคำขอก็ตาม
เมื่อเริ่มต้นใช้งาน ระบบจะกำหนดให้จอแสดงผลเริ่มในสถานะ NOT_VISIBLE
หลังจากนั้นไคลเอ็นต์จะต้องขอสถานะ VISIBLE_ON_NEXT_FRAME
และเริ่มแสดงวิดีโอ เมื่อไม่จำเป็นต้องแสดงอีกต่อไป ลูกค้าควรขอสถานะ NOT_VISIBLE
หลังจากส่งเฟรมวิดีโอสุดท้าย
โดยสามารถขอได้ทุกรัฐทุกเมื่อ หากจอแสดงผลมองเห็นอยู่แล้ว จอแสดงผลควรยังคงมองเห็นได้หากตั้งค่าเป็น
VISIBLE_ON_NEXT_FRAME
จะแสดงผล OK เสมอ เว้นแต่สถานะที่ขอ
จะเป็นค่า enum ที่ไม่รู้จัก ในกรณีนี้ระบบจะแสดงผล INVALID_ARG
getDisplayState() generates (DisplayState state);
รับสถานะการแสดงผล การใช้งาน HAL ควรรายงานสถานะปัจจุบันจริง ซึ่งอาจแตกต่างจากสถานะที่ขอครั้งล่าสุด ตรรกะที่รับผิดชอบในการเปลี่ยนสถานะการแสดงผลควรอยู่เหนือเลเยอร์อุปกรณ์ ซึ่งทำให้การติดตั้งใช้งาน HAL ไม่ควรเปลี่ยนสถานะการแสดงผล โดยพลการ
getTargetBuffer() generates (handle bufferHandle);
แสดงผลแฮนเดิลไปยังเฟรมบัฟเฟอร์ที่เชื่อมโยงกับจอแสดงผล ซอฟต์แวร์และ/หรือ GL อาจล็อกและเขียนบัฟเฟอร์นี้
ต้องส่งคืนบัฟเฟอร์นี้
พร้อมการเรียกใช้ returnTargetBufferForDisplay()
แม้ว่าจะมองไม่เห็นจอแสดงผลแล้วก็ตาม
แม้ว่าในทางเทคนิคแล้วจะใช้รูปแบบบัฟเฟอร์ที่เป็นกรรมสิทธิ์ได้ แต่การทดสอบความเข้ากันได้ กำหนดให้บัฟเฟอร์ต้องอยู่ในรูปแบบที่รองรับ 4 รูปแบบ ได้แก่ NV21 (YCrCb 4:2:0 Semi-Planar), YV12 (YCrCb 4:2:0 Planar), YUYV (YCrCb 4:2:2 Interleaved), RGBA (32 bit R:G:B:x), BGRA (32 bit B:G:R:x) รูปแบบที่เลือกต้องเป็นเป้าหมายการแสดงผล GL ที่ถูกต้องในการติดตั้งใช้งาน GLES ของแพลตฟอร์ม
เมื่อเกิดข้อผิดพลาด ระบบจะแสดงผลบัฟเฟอร์ที่มีแฮนเดิลเป็น Null แต่ไม่จำเป็นต้องส่งบัฟเฟอร์ดังกล่าวกลับไปยัง returnTargetBufferForDisplay
returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
บอกจอแสดงผลว่าบัฟเฟอร์พร้อมแสดงแล้ว บัฟเฟอร์ที่เรียกข้อมูลผ่านการเรียก getTargetBuffer()
เท่านั้นจึงจะใช้ได้กับการเรียกนี้
และแอปไคลเอ็นต์จะแก้ไขเนื้อหาของ BufferDesc
ไม่ได้ หลังจากเรียกนี้แล้ว บัฟเฟอร์จะใช้ไม่ได้อีกต่อไป
แสดงผล OK เมื่อสำเร็จ หรือรหัสข้อผิดพลาดที่เหมาะสมซึ่งอาจรวมถึง INVALID_ARG
หรือ BUFFER_NOT_AVAILABLE
struct DisplayDesc { string display_id; int32 vendor_flags; // Opaque value }
อธิบายคุณสมบัติพื้นฐานของจอแสดงผล EVS และข้อกำหนดในการติดตั้งใช้งาน EVS HAL มีหน้าที่กรอกข้อมูลในโครงสร้างนี้เพื่ออธิบายจอแสดงผล EVS อาจเป็นจอแสดงผลจริงหรือจอแสดงผลเสมือนที่ ซ้อนทับหรือผสมกับอุปกรณ์การนำเสนออื่น
display_id
สตริงที่ระบุค่าเฉพาะของจอแสดงผลที่ไม่ซ้ำกัน ซึ่งอาจเป็นชื่ออุปกรณ์เคอร์เนลของอุปกรณ์ หรือชื่อสำหรับอุปกรณ์ เช่น rearview HAL จะเป็นผู้เลือกค่าสำหรับสตริงนี้ และสแต็กด้านบนจะใช้ค่านี้อย่างไม่โปร่งใสvendor_flags
วิธีส่งข้อมูลกล้องเฉพาะทาง จากไดรเวอร์ไปยังแอป EVS ที่กำหนดเอง โดยจะส่ง โดยไม่มีการตีความจากไดรเวอร์ไปยังแอป EVS ซึ่งสามารถเลือกที่จะไม่สนใจ ได้
enum DisplayState : uint32 { NOT_OPEN, // Display has not been “opened” yet NOT_VISIBLE, // Display is inhibited VISIBLE_ON_NEXT_FRAME, // Will become visible with next frame VISIBLE, // Display is currently active DEAD, // Display is not available. Interface should be closed }
อธิบายสถานะของจอแสดงผล EVS ซึ่งอาจปิดใช้ (ไม่แสดงต่อผู้ขับขี่) หรือเปิดใช้ (แสดงรูปภาพต่อผู้ขับขี่)
รวมถึงสถานะชั่วคราวที่ยังมองไม่เห็นจอแสดงผล แต่เตรียมพร้อม
ที่จะมองเห็นได้เมื่อมีการส่งเฟรมถัดไปของภาพพร้อมการเรียกใช้ returnTargetBufferForDisplay()
EVS Manager
EVS Manager มีอินเทอร์เฟซสาธารณะสำหรับระบบ EVS เพื่อ รวบรวมและนำเสนอมุมมองจากกล้องภายนอก ในกรณีที่ไดรเวอร์ฮาร์ดแวร์อนุญาต ให้มีอินเทอร์เฟซที่ใช้งานอยู่เพียงอินเทอร์เฟซเดียวต่อทรัพยากร (กล้องหรือจอแสดงผล) EVS Manager จะช่วยให้เข้าถึงกล้องร่วมกันได้ แอป EVS หลักแอปเดียวคือไคลเอ็นต์แรกของ EVS Manager และเป็นไคลเอ็นต์เดียวที่ได้รับอนุญาตให้เขียนข้อมูลการแสดงผล (ไคลเอ็นต์เพิ่มเติมอาจได้รับสิทธิ์เข้าถึงแบบอ่านอย่างเดียวสำหรับรูปภาพจากกล้อง)
EVS Manager ใช้ API เดียวกันกับไดรเวอร์ HAL พื้นฐานและ ให้บริการที่ขยายออกไปโดยรองรับไคลเอ็นต์หลายรายที่ทำงานพร้อมกัน (ไคลเอ็นต์มากกว่า 1 รายสามารถเปิดกล้องผ่าน EVS Manager และรับสตรีมวิดีโอได้)

แอปจะไม่เห็นความแตกต่างเมื่อทำงานผ่านการติดตั้งใช้งาน EVS Hardware HAL หรือ EVS Manager API ยกเว้นว่า EVS Manager API อนุญาต การเข้าถึงสตรีมกล้องพร้อมกัน ตัวจัดการ EVS เป็นไคลเอ็นต์ที่ได้รับอนุญาตของเลเยอร์ HAL ของฮาร์ดแวร์ EVS และทำหน้าที่เป็นพร็อกซีสำหรับ HAL ของฮาร์ดแวร์ EVS
ส่วนต่อไปนี้จะอธิบายเฉพาะการเรียกที่มีลักษณะการทำงานที่แตกต่างกัน (ขยาย) ในการใช้งาน EVS Manager ส่วนการเรียกที่เหลือจะเหมือนกับคำอธิบาย EVS HAL
IEvsEnumerator
openCamera(string camera_id) generates (IEvsCamera camera);
รับออบเจ็กต์อินเทอร์เฟซที่ใช้โต้ตอบกับกล้องที่เฉพาะเจาะจง
ซึ่งระบุโดยสตริง camera_id ที่ไม่ซ้ำ แสดงผล NULL เมื่อล้มเหลว
ที่เลเยอร์ EVS Manager ตราบใดที่มีทรัพยากรระบบเพียงพอ
กระบวนการอื่นอาจเปิดกล้องที่เปิดอยู่แล้วอีกครั้งได้ ซึ่งจะช่วยให้
ส่งสตรีมวิดีโอไปยังแอปสำหรับผู้บริโภคหลายแอปได้ สตริง camera_id
ที่เลเยอร์ EVS Manager จะเหมือนกับสตริงที่รายงานไปยังเลเยอร์ฮาร์ดแวร์ EVS
IEvsCamera
การติดตั้งใช้งาน IEvsCamera ที่ EVS Manager จัดเตรียมให้จะได้รับการจำลองเสมือนภายใน ดังนั้นการดำเนินการในกล้องโดยไคลเอ็นต์รายหนึ่งจะไม่ส่งผลต่อไคลเอ็นต์รายอื่นๆ ซึ่ง ยังคงมีสิทธิ์เข้าถึงกล้องของตนเองได้อย่างอิสระ
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
เริ่มสตรีมวิดีโอ ไคลเอ็นต์อาจเริ่มและหยุดสตรีมวิดีโอแยกกัน ในกล้องพื้นฐานเดียวกัน กล้องพื้นฐานจะเริ่มทำงานเมื่อไคลเอ็นต์ตัวแรกเริ่มทำงาน
doneWithFrame(uint32 frameId, handle bufferHandle) generates (EvsResult result);
แสดงผลเฟรม ลูกค้าแต่ละรายต้องส่งคืนเฟรมเมื่อใช้งานเสร็จ แต่ สามารถเก็บเฟรมไว้ได้นานเท่าที่ต้องการ เมื่อจำนวนเฟรมที่ไคลเอ็นต์ถือครองถึงขีดจำกัดที่กำหนดค่าไว้ ไคลเอ็นต์จะไม่ได้รับเฟรมอีกจนกว่าจะส่งคืนเฟรม การข้ามเฟรมนี้จะไม่ส่งผลต่อไคลเอ็นต์อื่นๆ ซึ่งจะยังคงได้รับเฟรมทั้งหมดตามที่คาดไว้
stopVideoStream();
หยุดสตรีมวิดีโอ ไคลเอ็นต์แต่ละรายสามารถหยุดสตรีมวิดีโอได้ทุกเมื่อโดยไม่ส่งผลกระทบต่อไคลเอ็นต์รายอื่นๆ ระบบจะหยุดสตรีมกล้องพื้นฐานที่เลเยอร์ฮาร์ดแวร์ เมื่อไคลเอ็นต์สุดท้ายของกล้องที่กำหนดหยุดสตรีม
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
ส่งค่าที่เฉพาะเจาะจงสำหรับคนขับ ซึ่งอาจทำให้ไคลเอ็นต์รายหนึ่งส่งผลต่อไคลเอ็นต์อีกราย เนื่องจาก EVS Manager ไม่เข้าใจผลกระทบของ คำควบคุมที่ผู้ให้บริการกำหนด จึงไม่ได้จำลองเสมือน และผลข้างเคียงใดๆ จะมีผลกับไคลเอ็นต์ทั้งหมดของกล้องที่กำหนด ตัวอย่างเช่น หากผู้ให้บริการใช้การเรียกนี้ เพื่อเปลี่ยนอัตราเฟรม ไคลเอ็นต์ทั้งหมดของกล้องเลเยอร์ฮาร์ดแวร์ที่ได้รับผลกระทบจะ ได้รับเฟรมในอัตราใหม่
IEvsDisplay
อนุญาตให้มีเจ้าของจอแสดงผลได้เพียงคนเดียว แม้ในระดับผู้จัดการ EVS Manager ไม่ได้เพิ่มฟังก์ชันการทำงานใดๆ และเพียงส่งต่ออินเทอร์เฟซ IEvsDisplay ไปยังการติดตั้งใช้งาน HAL พื้นฐานโดยตรง
แอป EVS
Android มีการใช้งานอ้างอิง C++ ดั้งเดิมของแอป EVS ที่สื่อสารกับ EVS Manager และ Vehicle HAL เพื่อ ให้ฟังก์ชันพื้นฐานของกล้องมองหลัง คาดว่าแอปจะเริ่มทำงาน ตั้งแต่ช่วงแรกๆ ของกระบวนการบูตระบบ โดยจะแสดงวิดีโอที่เหมาะสมตาม กล้องที่พร้อมใช้งานและสถานะของรถ (สถานะเกียร์และสัญญาณไฟเลี้ยว) OEM สามารถแก้ไขหรือแทนที่แอป EVS ด้วยตรรกะและการนำเสนอเฉพาะรถยนต์ของตนเอง


เนื่องจากระบบจะแสดงข้อมูลรูปภาพต่อแอปในบัฟเฟอร์กราฟิกมาตรฐาน แอปจึงมีหน้าที่ย้ายรูปภาพจากบัฟเฟอร์ต้นทาง ไปยังบัฟเฟอร์เอาต์พุต แม้ว่าวิธีนี้จะทำให้เกิดค่าใช้จ่ายในการคัดลอกข้อมูล แต่ก็เปิดโอกาสให้แอปแสดงรูปภาพใน บัฟเฟอร์การแสดงผลในรูปแบบใดก็ได้ตามต้องการ
ตัวอย่างเช่น แอปอาจเลือกที่จะย้ายข้อมูลพิกเซลเอง ซึ่งอาจมีการดำเนินการปรับขนาดหรือหมุนในบรรทัด นอกจากนี้ แอปยังเลือกใช้รูปภาพต้นฉบับเป็นเท็กซ์เจอร์ OpenGL และแสดงผลฉากที่ซับซ้อนไปยังบัฟเฟอร์เอาต์พุตได้ด้วย ซึ่งรวมถึงองค์ประกอบเสมือนจริง เช่น ไอคอน เส้นบอกแนว และภาพเคลื่อนไหว แอปที่ซับซ้อนกว่าอาจเลือกกล้องอินพุตพร้อมกันหลายตัวและผสานรวมเป็นเฟรมเอาต์พุตเดียว (เช่น ใช้ในมุมมองเสมือนจริงจากด้านบนของสภาพแวดล้อมรอบๆ ยานพาหนะ)
ใช้ EGL/SurfaceFlinger ใน EVS Display HAL
ส่วนนี้จะอธิบายวิธีใช้ EGL เพื่อแสดงผลการใช้งาน HAL ของจอแสดงผล EVS ใน Android 10
การใช้งานอ้างอิงของ EVS
HAL ใช้ EGL เพื่อแสดงตัวอย่างกล้องบนหน้าจอและใช้ libgui
เพื่อสร้างพื้นผิวการแสดงผล EGL เป้าหมาย ใน Android 8 (และสูงกว่า) libgui
จะจัดเป็น VNDK-private
ซึ่งหมายถึงกลุ่มไลบรารีที่พร้อมใช้งานสำหรับไลบรารี VNDK ซึ่งกระบวนการของผู้ให้บริการจะใช้ไม่ได้
เนื่องจากการใช้งาน HAL ต้องอยู่ในพาร์ติชันของผู้ให้บริการ ผู้ให้บริการจึงไม่สามารถใช้
Surface ในการใช้งาน HAL ได้
สร้าง libgui สำหรับกระบวนการของผู้ให้บริการ
การใช้ libgui
เป็นตัวเลือกเดียวในการใช้ EGL/SurfaceFlinger
ในการติดตั้งใช้งาน HAL ของจอแสดงผล EVS วิธีที่ตรงไปตรงมาที่สุดในการติดตั้งใช้งาน libgui
คือ
ผ่าน
frameworks/native/libs/gui
โดยตรงโดยใช้เป้าหมายการสร้างเพิ่มเติมในสคริปต์การสร้าง เป้าหมายนี้เหมือนกับเป้าหมาย libgui
ทุกประการ ยกเว้นการเพิ่ม 2 ฟิลด์ต่อไปนี้
name
vendor_available
cc_library_shared { name: "libgui_vendor", vendor_available: true, vndk: { enabled: false, }, double_loadable: true,
defaults: ["libgui_bufferqueue-defaults"],
srcs: [ … // bufferhub is not used when building libgui for vendors target: { vendor: { cflags: [ "-DNO_BUFFERHUB", "-DNO_INPUT", ], …
หมายเหตุ: เป้าหมายของผู้ให้บริการสร้างขึ้นด้วยมาโคร NO_INPUT
ซึ่งจะนำคำ 32 บิต 1 คำออกจากข้อมูลพัสดุ เนื่องจาก SurfaceFlinger คาดหวังฟิลด์นี้ที่ถูกนำออกไปแล้ว SurfaceFlinger จึงแยกวิเคราะห์พัสดุไม่สำเร็จ ซึ่งสังเกตได้ว่าfcntl
ล้มเหลว
W Parcel : Attempt to read object from Parcel 0x78d9cffad8 at offset 428 that is not in the object list E Parcel : fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is 0, fd_count is 20, error: Unknown error 2147483647 W Parcel : Attempt to read object from Parcel 0x78d9cffad8 at offset 544 that is not in the object list
วิธีแก้ไขปัญหานี้
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6066421fa..25cf5f0ce 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -54,6 +54,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.b); #ifndef NO_INPUT inputInfo.write(output); +#else + // Write a dummy 32-bit word. + output.writeInt32(0); #endif output.write(transparentRegion); output.writeUint32(transform);
วิธีการสร้าง
ตัวอย่างมีอยู่ที่ด้านล่าง คุณจะได้รับ
$(ANDROID_PRODUCT_OUT)/system/lib64/libgui_vendor.so
$ cd <your_android_source_tree_top> $ . ./build/envsetup. $ lunch <product_name>-<build_variant> ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=10 TARGET_PRODUCT=<product_name> TARGET_BUILD_VARIANT=<build_variant> TARGET_BUILD_TYPE=release TARGET_ARCH=arm64 TARGET_ARCH_VARIANT=armv8-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH=arm TARGET_2ND_ARCH_VARIANT=armv7-a-neon TARGET_2ND_CPU_VARIANT=cortex-a9 HOST_ARCH=x86_64 HOST_2ND_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=<host_linux_version> HOST_CROSS_OS=windows HOST_CROSS_ARCH=x86 HOST_CROSS_2ND_ARCH=x86_64 HOST_BUILD_TYPE=release BUILD_ID=QT OUT_DIR=out ============================================
$ m -j libgui_vendor … $ find $ANDROID_PRODUCT_OUT/system -name "libgui_vendor*" .../out/target/product/hawk/system/lib64/libgui_vendor.so .../out/target/product/hawk/system/lib/libgui_vendor.so
ใช้ Binder ในการติดตั้งใช้งาน EVS HAL
ใน Android 8 (และสูงกว่า) /dev/binder
โหนดอุปกรณ์จะกลายเป็นเฉพาะสำหรับ
กระบวนการเฟรมเวิร์ก และด้วยเหตุนี้ กระบวนการของผู้ให้บริการจึงเข้าถึงไม่ได้ แต่กระบวนการของผู้ให้บริการควรใช้ /dev/hwbinder
และต้องแปลงอินเทอร์เฟซ AIDL
เป็น HIDL สำหรับผู้ที่ต้องการใช้อินเทอร์เฟซ AIDL ระหว่างกระบวนการของผู้ให้บริการต่อไป
ให้ใช้โดเมน Binder, /dev/vndbinder
โดเมน IPC | คำอธิบาย |
---|---|
/dev/binder |
IPC ระหว่างกระบวนการของเฟรมเวิร์ก/แอปที่มีอินเทอร์เฟซ AIDL |
/dev/hwbinder |
IPC ระหว่างกระบวนการของเฟรมเวิร์ก/ผู้ให้บริการที่มีอินเทอร์เฟซ HIDL IPC ระหว่างกระบวนการของผู้ให้บริการที่มีอินเทอร์เฟซ HIDL |
/dev/vndbinder |
IPC ระหว่างกระบวนการของผู้ให้บริการ/ผู้ให้บริการที่มีอินเทอร์เฟซ AIDL |
แม้ว่า SurfaceFlinger จะกำหนดอินเทอร์เฟซ AIDL แต่กระบวนการของผู้ให้บริการจะใช้ได้เฉพาะอินเทอร์เฟซ HIDL เพื่อ
สื่อสารกับกระบวนการของเฟรมเวิร์ก การแปลงอินเทอร์เฟซ AIDL ที่มีอยู่เป็น HIDL ต้องใช้ความพยายามอย่างมาก โชคดีที่ Android มีวิธีเลือกไดรเวอร์ Binder สำหรับ libbinder
ซึ่งลิงก์กับกระบวนการไลบรารีในพื้นที่ผู้ใช้
diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp index d8fb3166..5fd02935 100644 --- a/evs/sampleDriver/service.cpp +++ b/evs/sampleDriver/service.cpp @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> #include <utils/Log.h> +#include <binder/ProcessState.h> #include "ServiceNames.h" #include "EvsEnumerator.h" @@ -43,6 +44,9 @@ using namespace android; int main() { ALOGI("EVS Hardware Enumerator service is starting"); + // Use /dev/binder for SurfaceFlinger + ProcessState::initWithDriver("/dev/binder"); + // Start a thread to listen to video device addition events. std::atomic<bool> running { true }; std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));
หมายเหตุ: กระบวนการของผู้ให้บริการควรเรียกใช้ฟังก์ชันนี้ก่อนที่จะเรียกใช้
Process
หรือ IPCThreadState
หรือก่อนที่จะทำการเรียกใช้ Binder
นโยบาย SELinux
หากการติดตั้งใช้งานอุปกรณ์เป็น Treble แบบเต็ม SELinux จะป้องกันไม่ให้กระบวนการของผู้ให้บริการ
ใช้ /dev/binder
เช่น มีการกำหนดการใช้งานตัวอย่าง EVS HAL ให้กับโดเมน hal_evs_driver
และต้องมีสิทธิ์ r/w ในโดเมน binder_device
W ProcessState: Opening '/dev/binder' failed: Permission denied F ProcessState: Binder driver could not be opened. Terminating. F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 9145 (android.hardwar), pid 9145 (android.hardwar) W android.hardwar: type=1400 audit(0.0:974): avc: denied { read write } for name="binder" dev="tmpfs" ino=2208 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:binder_device:s0 tclass=chr_file permissive=0
อย่างไรก็ตาม การเพิ่มสิทธิ์เหล่านี้จะทำให้การสร้างล้มเหลวเนื่องจากละเมิดกฎ neverallow ต่อไปนี้ที่กำหนดไว้ใน system/sepolicy/domain.te
สำหรับอุปกรณ์ที่ใช้ Treble เต็มรูปแบบ
libsepol.report_failure: neverallow on line 631 of system/sepolicy/public/domain.te (or line 12436 of policy.conf) violated by allow hal_evs_driver binder_device:chr_file { read write }; libsepol.check_assertions: 1 neverallow failures occurred
full_treble_only(` neverallow { domain -coredomain -appdomain -binder_in_vendor_violators } binder_device:chr_file rw_file_perms; ')
binder_in_vendor_violators
เป็นแอตทริบิวต์ที่ใช้เพื่อตรวจจับข้อบกพร่องและเป็นแนวทางในการพัฒนา นอกจากนี้ ยังใช้เพื่อ
แก้ไขการละเมิดใน Android 10 ที่อธิบายไว้ข้างต้นได้ด้วย
diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te index f1f31e9fc..6ee67d88e 100644 --- a/evs/sepolicy/evs_driver.te +++ b/evs/sepolicy/evs_driver.te @@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain; hal_server_domain(hal_evs_driver, hal_evs) hal_client_domain(hal_evs_driver, hal_evs) +# Allow to use /dev/binder +typeattribute hal_evs_driver binder_in_vendor_violators; + # allow init to launch processes in this context type hal_evs_driver_exec, exec_type, file_type, system_file_type; init_daemon_domain(hal_evs_driver)
สร้างการใช้งานอ้างอิง EVS HAL เป็นกระบวนการของผู้ให้บริการ
คุณสามารถใช้การเปลี่ยนแปลงต่อไปนี้กับ
packages/services/Car/evs/Android.mk
เพื่อเป็นข้อมูลอ้างอิง โปรดตรวจสอบว่าการเปลี่ยนแปลงทั้งหมดที่อธิบายไว้ใช้ได้กับการติดตั้งใช้งานของคุณ
diff --git a/evs/sampleDriver/Android.mk b/evs/sampleDriver/Android.mk index 734feea7d..0d257214d 100644 --- a/evs/sampleDriver/Android.mk +++ b/evs/sampleDriver/Android.mk @@ -16,7 +16,7 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ android.hardware.automotive.evs@1.0 \ libui \ - libgui \ + libgui_vendor \ libEGL \ libGLESv2 \ libbase \ @@ -33,6 +33,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-sample.rc LOCAL_MODULE := android.hardware.automotive.evs@1.0-sample +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional LOCAL_STRIP_MODULE := keep_symbols @@ -40,6 +41,7 @@ LOCAL_STRIP_MODULE := keep_symbols LOCAL_CFLAGS += -DLOG_TAG=\"EvsSampleDriver\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code +LOCAL_CFLAGS += -Iframeworks/native/include #NOTE: It can be helpful, while debugging, to disable optimizations #LOCAL_CFLAGS += -O0 -g diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp index d8fb31669..5fd029358 100644 --- a/evs/sampleDriver/service.cpp +++ b/evs/sampleDriver/service.cpp @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> #include <utils/Log.h> +#include <binder/ProcessState.h> #include "ServiceNames.h" #include "EvsEnumerator.h" @@ -43,6 +44,9 @@ using namespace android; int main() { ALOGI("EVS Hardware Enumerator service is starting"); + // Use /dev/binder for SurfaceFlinger + ProcessState::initWithDriver("/dev/binder"); + // Start a thread to listen video device addition events. std::atomic<bool> running { true }; std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running)); diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te index f1f31e9fc..632fc7337 100644 --- a/evs/sepolicy/evs_driver.te +++ b/evs/sepolicy/evs_driver.te @@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain; hal_server_domain(hal_evs_driver, hal_evs) hal_client_domain(hal_evs_driver, hal_evs) +# allow to use /dev/binder +typeattribute hal_evs_driver binder_in_vendor_violators; + # allow init to launch processes in this context type hal_evs_driver_exec, exec_type, file_type, system_file_type; init_daemon_domain(hal_evs_driver) @@ -22,3 +25,7 @@ allow hal_evs_driver ion_device:chr_file r_file_perms; # Allow the driver to access kobject uevents allow hal_evs_driver self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl; + +# Allow the driver to use the binder device +allow hal_evs_driver binder_device:chr_file rw_file_perms;