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;