Android มีเลเยอร์การแยกแยะฮาร์ดแวร์ HIDL (HAL) ยานยนต์ที่รองรับการจับภาพและแสดงภาพตั้งแต่เนิ่นๆ ในกระบวนการบูตของ 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 และส่งเฟรมที่เสร็จแล้วเพื่อแสดงกลับไปยังผู้จัดการ EVS
คาดว่าระบบจะเริ่มต้นโดย init ทันทีที่ EVS และบริการของรถพร้อมใช้งาน โดยกำหนดเป้าหมายให้เริ่มภายใน 2 (2) วินาทีหลังจากเปิดเครื่อง OEM สามารถแก้ไขหรือแทนที่แอป EVS ได้ตามความประสงค์
ผู้จัดการ EVS
EVS Manager (/packages/services/Car/evs/manager
) มีองค์ประกอบพื้นฐานที่จําเป็นสําหรับแอป EVS เพื่อติดตั้งใช้งานตั้งแต่การแสดงผลกล้องมองหลังแบบธรรมดาไปจนถึงการแสดงผลภาพจากกล้องหลายตัวแบบ 6DOF โดยอินเทอร์เฟซของเครือข่ายจะแสดงผ่าน HIDL และสร้างขึ้นเพื่อรับไคลเอ็นต์ที่ทำงานพร้อมกันหลายราย
แอปและบริการอื่นๆ (โดยเฉพาะบริการรถยนต์) สามารถค้นหาสถานะ EVS Manager เพื่อดูว่าระบบ EVS ทำงานอยู่หรือไม่
อินเทอร์เฟซ EVS HIDL
ระบบจะระบุระบบ 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 ผ่านไดรเวอร์ฮาร์ดแวร์กล้องหรือจอแสดงผลที่มีอยู่แทนการสร้างไดรเวอร์ใหม่ การใช้ไดรเวอร์ซ้ำอาจมีประโยชน์ โดยเฉพาะอย่างยิ่งสำหรับไดรเวอร์การแสดงผลที่การแสดงภาพอาจต้องประสานงานกับเธรดอื่นๆ ที่ทำงานอยู่ 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 ของระบบโดยเฉพาะ ไคลเอ็นต์เพียง 1 เครื่องเท่านั้นที่จะเก็บอินสแตนซ์ที่ทำงานของ IEvsDisplay ได้ในแต่ละครั้ง ระบบอาจสร้างออบเจ็กต์ IEvsDisplay ใหม่ได้ทุกเมื่อและปิดใช้อินสแตนซ์ก่อนหน้า ซึ่งคล้ายกับลักษณะการเปิดแบบก้าวร้าวที่อธิบายไว้ใน openCamera
อินสแตนซ์ที่ลบล้างแล้วจะยังคงอยู่และตอบสนองต่อการเรียกฟังก์ชันจากเจ้าของ แต่ต้องไม่ดำเนินการที่ทำให้เกิดการเปลี่ยนแปลงเมื่อตาย ท้ายที่สุดแล้ว แอปไคลเอ็นต์จะสังเกตเห็นรหัสข้อผิดพลาด 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 ซึ่งไม่ต้องสนใจ
กล้อง IEv
ออบเจ็กต์นี้แสดงกล้องตัวเดียวและเป็นอินเทอร์เฟซหลักสำหรับการจับภาพ
getCameraInfo() generates (CameraDesc info);
แสดง CameraDesc
ของกล้องนี้
setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);
ระบุความลึกของเชนบัฟเฟอร์ที่ขอให้กล้องรองรับ เฟรมจำนวนมากอาจถือพร้อมกันโดยไคลเอ็นต์ของ IEvsกล้องถ่ายรูป หากมีการส่งเฟรมจำนวนมากนี้ไปยังผู้รับโดยที่doneWithFrame
ไม่ได้ส่งคืน ข้อมูลสตรีมจะข้ามเฟรมจนกว่าจะมีการส่งบัฟเฟอร์คืนเพื่อใช้ซ้ำ การเรียกใช้นี้สามารถเกิดขึ้นได้ทุกเมื่อ แม้ในขณะที่สตรีมกำลังทำงานอยู่ก็ตาม ซึ่งในกรณีนี้ คุณควรเพิ่มหรือนำบัฟเฟอร์ออกจากเชนตามความเหมาะสม ถ้าไม่มีการเรียกไปยังจุดแรกเข้านี้ IEvscamera จะรองรับอย่างน้อย 1 เฟรมโดยค่าเริ่มต้น ซึ่งยอมรับได้มากกว่า
หากรองรับ bufferCount ที่ขอไม่ได้ ฟังก์ชันจะแสดงผล BUFFER_NOT_AVAILABLE
หรือรหัสข้อผิดพลาดอื่นๆ ที่เกี่ยวข้อง ในกรณีนี้ ระบบจะยังคงทำงานต่อไปด้วยค่าที่กำหนดไว้ก่อนหน้านี้
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
ส่งคำขอการนำส่งเฟรมกล้อง EVS จากกล้องนี้ IEvsCameraStream จะเริ่มต้นรับการเรียกด้วยเฟรมรูปภาพใหม่เป็นระยะๆ จนกว่าจะมีการเรียกstopVideoStream()
ระบบต้องเริ่มส่งเฟรมภายใน 500 มิลลิวินาทีหลังจากการเรียกใช้ startVideoStream
และหลังจากเริ่มแล้ว เฟรมต้องสร้างขึ้นที่อัตราเฟรมอย่างน้อย 10 FPS เวลาที่ใช้ในการเริ่มสตรีมวิดีโอจะนับรวมในข้อกำหนดเวลาเริ่มต้นกล้องมองหลังอย่างมีประสิทธิภาพ หากสตรีมไม่เริ่มต้น ระบบจะแสดงรหัสข้อผิดพลาด มิเช่นนั้นระบบจะแสดงผลว่า "OK"
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
จำนวนพิกเซลแต่ละแถวจะใช้หน่วยความจำจริง ซึ่งพิจารณา Padding สำหรับการจัดแถวของแถว แสดงเป็นพิกเซลเพื่อให้ตรงกับรูปแบบที่ gralloc นำมาใช้สำหรับคำอธิบายบัฟเฟอร์pixelSize
. จำนวนไบต์ที่แต่ละพิกเซลใช้ไป ซึ่งช่วยให้คำนวณขนาดเป็นไบต์ที่จำเป็นในการเลื่อนระหว่างแถวในรูปภาพได้ (stride
เป็นไบต์ =stride
เป็นพิกเซล *pixelSize
)format
รูปแบบพิกเซลที่รูปภาพใช้ รูปแบบที่ระบุต้องเข้ากันได้กับการใช้งาน OpenGL ของแพลตฟอร์ม หากต้องการผ่านการทดสอบความเข้ากันได้ ควรใช้HAL_PIXEL_FORMAT_YCRCB_420_SP
สำหรับการใช้งานกล้อง และควรเลือกใช้RGBA
หรือBGRA
สำหรับจอแสดงผลusage
. Flag การใช้งานที่การตั้งค่า HAL กำหนด คาดว่าไคลเอ็นต์ HAL จะส่งค่าเหล่านี้โดยไม่มีการแก้ไข (ดูรายละเอียดได้ในGralloc.h
Flag ที่เกี่ยวข้อง)bufferId
. ค่าที่ไม่ซ้ำกันซึ่งการใช้งาน HAL ระบุไว้เพื่ออนุญาตให้ระบบจดจำบัฟเฟอร์หลังจากการไปกลับผ่าน HAL API ค่าที่เก็บในช่องนี้อาจได้รับเลือกโดยการติดตั้งใช้งาน HALmemHandle
. แฮนเดิลสำหรับบัฟเฟอร์หน่วยความจำที่อยู่เบื้องหลังซึ่งมีข้อมูลรูปภาพ การใช้งาน HAL อาจเลือกจัดเก็บตัวแฮนเดิลบัฟเฟอร์ Gralloc ไว้ที่นี่
IEvsCameraStream
ไคลเอ็นต์ใช้อินเทอร์เฟซนี้เพื่อรับการส่งเฟรมวิดีโอแบบไม่ประสานเวลา
deliverFrame(BufferDesc buffer);
รับสายจาก HAL ทุกครั้งที่เฟรมวิดีโอพร้อมสําหรับการตรวจสอบ
แฮนเดิลบัฟเฟอร์ที่ได้รับจากเมธอดนี้ต้องส่งคืนผ่านการเรียกใช้ IEvsCamera::doneWithFrame()
เมื่อสตรีมวิดีโอหยุดด้วยการเรียกใช้ IEvsCamera::stopVideoStream()
Callback นี้อาจทำงานต่อไปขณะที่ไปป์ไลน์จะระบายน้ำ แต่ละเฟรมยังคงต้องส่งคืน เมื่อมีการส่งเฟรมสุดท้ายในสตรีม ระบบจะส่ง bufferHandle
เป็นค่าว่าง ซึ่งเป็นสัญลักษณ์จุดสิ้นสุดของสตรีมและไม่มีการส่งเฟรมเพิ่มเติม คุณไม่จำเป็นต้องส่ง 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()
แม้ว่าจะไม่เห็นจอแสดงผลแล้วก็ตาม
แม้ว่ารูปแบบบัฟเฟอร์ที่เป็นกรรมสิทธิ์จะเป็นไปได้ในทางเทคนิค แต่การทดสอบความเข้ากันได้กำหนดให้บัฟเฟอร์อยู่ในรูปแบบที่รองรับ 1 ใน 4 รูปแบบ ได้แก่ NV21 (YCrCb 4: 2:0 Semi-Planar), YV12 (YCrCb 4:2:0 Planar), YUYV (YCrCb 4:2:2 บิต:RGBA:RGBA:2:2 บิต:RGBA:32 บิต:RGBA) รูปแบบที่เลือกต้องเป็นเป้าหมายการแสดงผล 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
สตริงที่ระบุจอแสดงผลที่ไม่ซ้ำกัน ซึ่งอาจเป็นชื่ออุปกรณ์เคอร์เนลของอุปกรณ์ หรือชื่อของอุปกรณ์ เช่น มองหลัง สตริงนี้จะได้รับค่าจากการใช้งาน HAL และกองซ้อนด้านบนจะใช้สตริงนี้แบบทึบvendor_flags
. วิธีการส่งข้อมูลกล้องเฉพาะจากไดรเวอร์ไปยังแอป EVS ที่กําหนดเองแบบไม่ระบุรายละเอียด โดยระบบจะส่งข้อมูลดังกล่าวจากไดรเวอร์ไปยังแอป 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
เครื่องมือจัดการ EVS มีอินเทอร์เฟซสาธารณะสำหรับระบบ EVS เพื่อรวบรวมและแสดงมุมมองจากกล้องภายนอก เมื่อไดรเวอร์ฮาร์ดแวร์อนุญาตให้มีอินเทอร์เฟซที่ใช้งานอยู่เพียงอินเทอร์เฟซเดียวต่อทรัพยากร (กล้องหรือจอแสดงผล) ผู้จัดการ EVS จะอำนวยความสะดวกในการเข้าถึงกล้องร่วมกัน แอป EVS หลักแอปเดียวคือไคลเอ็นต์แรกของเครื่องมือจัดการ EVS และเป็นไคลเอ็นต์เพียงรายเดียวที่ได้รับอนุญาตให้เขียนข้อมูลการแสดงผล (สามารถให้สิทธิ์เข้าถึงภาพจากกล้องระดับอ่านอย่างเดียวแก่ไคลเอ็นต์เพิ่มเติมได้)
EVS Manager ใช้ API เดียวกับไดรเวอร์ HAL ที่เกี่ยวข้องและให้บริการที่ขยายการให้บริการโดยรองรับไคลเอ็นต์หลายรายพร้อมกัน (ไคลเอ็นต์มากกว่า 1 รายสามารถเปิดกล้องผ่าน EVS Manager และรับสตรีมวิดีโอได้)
แอปจะไม่มีความแตกต่างกันเมื่อทำงานผ่านการติดตั้งใช้งานฮาร์ดแวร์ EVS ระดับฮาร์ดแวร์ HAL หรือ EVS Manager API ยกเว้นว่า EVS Manager API อนุญาตให้เข้าถึงการสตรีมด้วยกล้องพร้อมกัน เครื่องมือจัดการ EVS นั้นเป็นไคลเอ็นต์ที่ได้รับอนุญาตของเลเยอร์ HAL ของฮาร์ดแวร์ EVS และทำหน้าที่เป็นพร็อกซีสำหรับ HAL ของฮาร์ดแวร์ EVS
ส่วนต่อไปนี้จะอธิบายเฉพาะการเรียกที่มีลักษณะการทำงาน (เพิ่มเติม) แตกต่างจากการใช้งาน EVS Manager ส่วนการเรียกที่เหลือจะเหมือนกับคำอธิบาย HAL ของ EVS
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 ไม่สามารถเข้าใจความหมายของคําควบคุมที่กําหนดโดยผู้ให้บริการ คําควบคุมดังกล่าวจึงไม่ได้เป็นแบบเสมือนจริงและผลข้างเคียงใดๆ ก็จะมีผลกับไคลเอ็นต์ทั้งหมดของกล้องหนึ่งๆ เช่น หากผู้ให้บริการใช้การเรียกนี้เพื่อเปลี่ยนอัตราเฟรม ไคลเอ็นต์ทั้งหมดของกล้องที่มีเลเยอร์ฮาร์ดแวร์ที่ได้รับผลกระทบจะได้รับเฟรมที่อัตราใหม่
IEvsDisplay
อนุญาตให้มีเจ้าของจอแสดงผลได้เพียงคนเดียว แม้จะเป็นระดับผู้จัดการ EVS ก็ตาม ตัวแปรดังกล่าวไม่ได้เพิ่มฟังก์ชันการทำงานใดๆ เพียงแค่ส่งผ่านอินเทอร์เฟซ IEvsDisplay ไปยังการใช้งาน HAL ที่เกี่ยวข้องโดยตรง
แอป EVS
Android มีการใช้งานอ้างอิง C++ เนทีฟของแอป EVS ที่สื่อสารกับเครื่องมือจัดการ EVS และ HAL ของยานพาหนะเพื่อให้บริการฟังก์ชันพื้นฐานของกล้องมองหลัง แอปคาดว่าจะเริ่มทำงานตั้งแต่เนิ่นๆ ในกระบวนการบูตระบบ โดยจะมีวิดีโอที่เหมาะสมแสดงขึ้นโดยขึ้นอยู่กับกล้องที่ใช้ได้และสถานะของรถ (สถานะเกียร์และไฟเลี้ยว) OEM สามารถแก้ไขหรือแทนที่แอป EVS ด้วยตรรกะและการแสดงผลเฉพาะรถยนต์ของตนเองได้
เนื่องจากระบบจะแสดงข้อมูลรูปภาพต่อแอปในบัฟเฟอร์กราฟิกมาตรฐาน แอปจึงมีหน้าที่รับผิดชอบในการย้ายรูปภาพจากบัฟเฟอร์ต้นทางไปยังบัฟเฟอร์เอาต์พุต แม้ว่าวิธีนี้จะเสียค่าใช้จ่ายสำหรับการคัดลอกข้อมูล แต่ก็เปิดโอกาสให้แอปแสดงผลรูปภาพลงในบัฟเฟอร์จอแสดงผลด้วยวิธีการใดก็ได้ที่ต้องการ
เช่น แอปอาจเลือกที่จะย้ายข้อมูลพิกเซลด้วยตนเอง ซึ่งอาจมีการดําเนินการเพื่อปรับขนาดหรือหมุนในบรรทัด แอปยังเลือกที่จะใช้รูปภาพต้นฉบับเป็นพื้นผิว OpenGL และแสดงผลฉากที่ซับซ้อนไปยังบัฟเฟอร์เอาต์พุตได้ ซึ่งรวมถึงองค์ประกอบเสมือนจริง เช่น ไอคอน เส้นกํากับ และภาพเคลื่อนไหว แอปที่ซับซ้อนกว่านั้นอาจเลือกกล้องอินพุตหลายตัวพร้อมกันและผสานเข้าด้วยกันเป็นเฟรมเอาต์พุตเดียว (เช่น ใช้สําหรับมุมมองภาพเสมือนจริงจากด้านบนของสภาพแวดล้อมรอบๆ ยานพาหนะ)
ใช้ EGL/SurfaceFlinger ใน HAL ของจอแสดงผล EVS
ส่วนนี้จะอธิบายวิธีใช้ 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 Driver สำหรับ 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
หากการติดตั้งใช้งานอุปกรณ์เป็นแบบ Full Treble นั้น SELinux จะป้องกันไม่ให้กระบวนการของผู้ให้บริการใช้ /dev/binder
เช่น การติดตั้งใช้งานตัวอย่าง HAL ของ EVS ได้รับการกําหนดให้กับโดเมน hal_evs_driver
และต้องได้รับสิทธิ์อ่าน/เขียนในโดเมน 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;