HAL กล้องของยานพาหนะ

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

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

ส่วนประกอบของระบบ

EVS มีส่วนประกอบของระบบต่อไปนี้

ระบบ EVS
แผนภูมิส่วนประกอบ
รูปที่ 1. ภาพรวมส่วนประกอบของระบบ EVS

แอป EVS

ตัวอย่างแอป C++ EVS (/packages/services/Car/evs/app) ทำหน้าที่เป็นข้อมูลอ้างอิง การใช้งานของคุณ แอปนี้มีหน้าที่ขอเฟรมวิดีโอจาก ผู้จัดการ EVS และส่งเฟรมที่เสร็จแล้วสำหรับจอแสดงผลกลับไปยังผู้จัดการ EVS คาดว่าจะเริ่มดำเนินการภายในทันทีที่ EVS และบริการรถยนต์พร้อมให้บริการ กำหนดเป้าหมายภายในสอง (2) วินาทีหลังจากเปิดเครื่อง OEM จะแก้ไขหรือเปลี่ยน EVS ได้ แอปได้ตามต้องการ

ผู้จัดการ EVS

EVS Manager (/packages/services/Car/evs/manager) ให้ องค์ประกอบพื้นฐานที่แอป EVS ต้องการเพื่อใช้งานทุกอย่างตั้งแต่ การแสดงผลจากกล้องหลังในแบบ 6DOF ที่ใช้งานง่าย อินเทอร์เฟซของ นำเสนอผ่าน HIDL และสร้างมาเพื่อรับไคลเอ็นต์ที่ทำงานพร้อมกันหลายราย แอปและบริการอื่นๆ (โดยเฉพาะบริการรถยนต์) สามารถค้นหา EVS ได้ สถานะผู้จัดการเพื่อดูว่าระบบ EVS ทำงานอยู่เมื่อใด

อินเทอร์เฟซ EVS HIDL

ระบบ EVS ทั้งองค์ประกอบกล้องและจอแสดงผลจะระบุไว้ใน แพ็กเกจ android.hardware.automotive.evs ตัวอย่างการใช้งาน ที่ทำงานกับอินเทอร์เฟซ (สร้างภาพทดสอบสังเคราะห์และตรวจสอบ รูปภาพที่ทำให้เกิด Conversion ไป-กลับ) จะระบุไว้ใน /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 ไคลเอนต์เพียงเครื่องเดียวสามารถเก็บอินสแตนซ์ที่ทำงานของ 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 สตริงที่ระบุกล้องโดยไม่ซ้ำกัน อาจเป็นชื่ออุปกรณ์เคอร์เนลของอุปกรณ์หรือชื่อของอุปกรณ์ เช่น กระจกหลัง ค่าสำหรับสตริงนี้เลือกโดยการใช้งาน HAL และใช้แบบทึบโดยกลุ่มด้านบน
  • vendor_flags วิธีการส่งผ่านกล้องเฉพาะทาง ข้อมูลไม่ชัดเจนจากคนขับไปยังแอป EVS ที่กำหนดเอง ผ่านแล้ว ไม่ตีความจากคนขับไปจนถึงแอป EVS ซึ่งไม่ต้องสนใจ ได้

กล้อง IEv

วัตถุนี้แสดงกล้องตัวเดียวและเป็นอินเทอร์เฟซหลักสำหรับ ที่กำลังจับภาพ

getCameraInfo() generates (CameraDesc info);

แสดง CameraDesc ของกล้องนี้

setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);

ระบุความลึกของห่วงโซ่บัฟเฟอร์ที่กล้องจะขอรองรับ ไม่เกิน เฟรมจำนวนมากนี้อาจใช้พร้อมกันโดยไคลเอ็นต์ของ IEvsกล้องถ่ายรูป หากสิ่งนี้ เฟรมจำนวนมากถูกส่งไปยังเครื่องรับโดยไม่มีการส่งคืนโดย doneWithFrame สตรีมจะข้ามเฟรมจนกว่าจะแสดงบัฟเฟอร์ เพื่อนำมาใช้ใหม่ การโทรนี้เปิดให้ทำได้ในเวลาใดก็ได้ แม้ในขณะที่สตรีม ทำงานอยู่แล้ว ซึ่งในกรณีนี้ควรเพิ่มหรือนำบัฟเฟอร์ออกจากเชน ตามความเหมาะสม ถ้าไม่มีการเรียกไปยังจุดแรกเข้านี้ IEvscamera จะสนับสนุน อย่างน้อย 1 เฟรมโดยค่าเริ่มต้น ด้วยรูปแบบที่ยอมรับได้มากกว่า

หากไม่สามารถรองรับบัฟเฟอร์จำนวนที่ขอ ฟังก์ชันจะแสดงผล BUFFER_NOT_AVAILABLE หรือรหัสข้อผิดพลาดอื่นๆ ที่เกี่ยวข้อง ในกรณีนี้ ระบบจะยังคงทำงานต่อไปด้วยค่าที่กำหนดไว้ก่อนหน้านี้

startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);

ส่งคำขอการนำส่งเฟรมกล้อง EVS จากกล้องนี้ สตรีมกล้อง IEv เริ่มได้รับการเรียกเป็นระยะๆ พร้อมกรอบรูปใหม่จนถึง โทรหา stopVideoStream() ต้องเริ่มนำส่งเฟรม ภายใน 500 มิลลิวินาทีของการโทร startVideoStream และหลังจากเริ่มต้น ต้อง สร้างอย่างน้อย 10 FPS เวลาที่ต้องใช้ในการเริ่มสตรีมวิดีโอ นับรวมกับข้อกำหนดเวลาเริ่มต้นของกล้องมองหลังได้อย่างมีประสิทธิภาพ หาก สตรีมไม่เริ่มต้น ต้องส่งคืนรหัสข้อผิดพลาด มิฉะนั้น ระบบจะแสดงผล OK

oneway doneWithFrame(BufferDesc buffer);

แสดงเฟรมที่ส่งโดย IEvscameraStream เมื่อทำเสร็จ เมื่อใช้เฟรมที่ส่งไปยังอินเทอร์เฟซ IEvscameraStream เฟรมดังกล่าวจะต้อง กลับไปที่ IEvsกล้องถ่ายรูป เพื่อใช้ซ้ำ มีบัฟเฟอร์ไม่มาก ว่าง (อาจเหลือน้อยที่สุด) และหากอุปทานหมด ก็ไม่มี จะแสดงเฟรมต่างๆ จนกว่าจะมีการส่งกลับบัฟเฟอร์ ซึ่งอาจส่งผลให้ เฟรมที่ข้าม (บัฟเฟอร์ที่มีแฮนเดิลเป็น Null หมายถึงจุดสิ้นสุดของสตรีมและ ไม่จำเป็นต้องแสดงผลผ่านฟังก์ชันนี้) ส่งคืนสถานะตกลงเมื่อสำเร็จ หรือ รหัสข้อผิดพลาดที่เหมาะสมซึ่งอาจรวม 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 แฮนเดิลตรงนี้

สตรีมจากกล้อง IEv

ไคลเอ็นต์ใช้อินเทอร์เฟซนี้เพื่อรับเฟรมวิดีโอแบบไม่พร้อมกัน ในการจัดส่ง

deliverFrame(BufferDesc buffer);

รับสายจาก HAL ทุกครั้งที่เฟรมวิดีโอพร้อมสำหรับการตรวจสอบ แฮนเดิลบัฟเฟอร์ที่ได้รับจากวิธีนี้จะต้องส่งคืนผ่านการเรียกไปยัง IEvsCamera::doneWithFrame() เมื่อสตรีมวิดีโอหยุดด้วย โทรหา IEvsCamera::stopVideoStream() การติดต่อกลับนี้อาจดำเนินการต่อ ขณะที่ท่อระบายน้ำ แต่ละเฟรมยังคงต้องส่งคืน เฟรมสุดท้าย ในสตรีมมีการนำส่งแล้ว มีการส่ง bufferHandle เป็นค่าว่าง แสดงถึงจุดสิ้นสุดของสตรีม และไม่มีการส่งเฟรมใดๆ เกิดขึ้นอีก ค่าว่าง ไม่จำเป็นต้องส่ง bufferHandle กลับมาพร้อมกับ doneWithFrame() แต่ต้องส่งคืนแฮนเดิลอื่นๆ ทั้งหมดด้วย

แม้ว่ารูปแบบบัฟเฟอร์ที่เป็นกรรมสิทธิ์จะสร้างในทางเทคนิคได้ แต่ความเข้ากันได้ การทดสอบกำหนดให้บัฟเฟอร์อยู่ในรูปแบบที่รองรับ 1 ใน 4 รูปแบบ ได้แก่ NV21 (YCrCb) 4:2:0 กึ่งระนาบ) YV12 (YCrCb 4:2:0 ระนาบ) YUYV (YCrCb 4:2:2 แทรกสลับ) RGBA (32 บิต R:G:B:x), BGRA (32 บิต B:G:R:x) รูปแบบที่เลือกต้องเป็นรูปแบบที่ถูกต้อง แหล่งที่มาของพื้นผิว GL บนการติดตั้งใช้งาน GLES ของแพลตฟอร์ม

แอปควรไม่ต้องพึ่งพาการโต้ตอบใดๆ ระหว่างฟิลด์ bufferId และ memHandle ในฟิลด์ BufferDesc ค่า bufferId คือ มีความเฉพาะตัวในการใช้งานไดรเวอร์ HAL และอาจใช้ (และนำมาใช้ใหม่) ตามที่เห็นสมควร

การแสดงผล IEv

ออบเจ็กต์นี้แสดงจอแสดงผล 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 แสดงผล "ตกลง" เสมอ เว้นแต่สถานะที่ร้องขอ เป็นค่า enum ที่ไม่รู้จัก ซึ่งในกรณีนี้ INVALID_ARG คือ ส่งคืนแล้ว

getDisplayState() generates (DisplayState state);

รับสถานะการแสดงผล การติดตั้งใช้งาน HAL ควรรายงานเมตริก สถานะปัจจุบัน ซึ่งอาจแตกต่างจากสถานะที่ขอล่าสุด ควรมีตรรกะที่รับผิดชอบในการเปลี่ยนสถานะการแสดงผลอยู่เหนืออุปกรณ์ ซึ่งทำให้การใช้งาน HAL เปลี่ยนแปลงไปเองโดยไม่มีเหตุอันควร แสดงสถานะ

getTargetBuffer() generates (handle bufferHandle);

แสดงผลแฮนเดิลไปยังเฟรมบัฟเฟอร์ที่เชื่อมโยงกับจอแสดงผล บัฟเฟอร์นี้ อาจมีการล็อกและเขียนข้อมูลโดยซอฟต์แวร์และ/หรือ GL ต้องส่งคืนบัฟเฟอร์นี้ ด้วยการเรียกไปยัง returnTargetBufferForDisplay() แม้ว่าจอแสดงผลจะ จะไม่ปรากฏอีกต่อไป

แม้ว่ารูปแบบบัฟเฟอร์ที่เป็นกรรมสิทธิ์จะสร้างในทางเทคนิคได้ แต่การทดสอบความเข้ากันได้ บัฟเฟอร์ต้องอยู่ในรูปแบบที่รองรับทั้ง 4 รูปแบบ ได้แก่ NV21 (YCrCb 4:2:0 กึ่งระนาบ) YV12 (YCrCb 4:2:0 ระนาบ) YUYV (YCrCb 4:2:2 แบบแทรกสลับ) RGBA (32 บิต R:G:B:x), BGRA (32 บิต B:G:R:x) รูปแบบที่เลือกต้องเป็น GL ที่ถูกต้อง เป้าหมายการแสดงผลในการใช้งาน GLES ของแพลตฟอร์ม

หากเกิดข้อผิดพลาด บัฟเฟอร์ที่มีแฮนเดิลเป็น Null จะแสดงผล แต่บัฟเฟอร์ดังกล่าวไม่ จำเป็นต้องส่งคืนให้กับ returnTargetBufferForDisplay

returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);

บอกจอแสดงผลว่าบัฟเฟอร์พร้อมแสดงผลแล้ว เฉพาะบัฟเฟอร์ที่ดึงมา ผ่านการโทรไปยัง getTargetBuffer() ใช้ได้กับ และเนื้อหาของ BufferDesc อาจไม่ถูกแก้ไขโดย แอปไคลเอ็นต์ หลังจากการเรียกใช้ บัฟเฟอร์นี้ไม่สามารถใช้ได้อีกต่อไปโดย ไคลเอ็นต์ ส่งคืนสถานะตกลงเมื่อสำเร็จ หรือรหัสข้อผิดพลาดที่เหมาะสมซึ่งอาจ รวมถึง 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 ซึ่งไม่ต้องสนใจ ได้
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 Manager ให้บริการอินเทอร์เฟซสาธารณะกับระบบ EVS สำหรับ เก็บรวบรวมและนำเสนอมุมมองกล้องภายนอก ส่วนที่ไดรเวอร์ฮาร์ดแวร์อนุญาต อินเทอร์เฟซที่ใช้งานอยู่เพียง 1 อินเทอร์เฟซต่อทรัพยากร (กล้องหรือจอแสดงผล) ตัวจัดการ EVS ช่วยให้เข้าถึงกล้องร่วมกันได้ง่ายขึ้น แอป EVS หลักแอปเดียวคือ ลูกค้ารายแรกของผู้จัดการ EVS และเป็นลูกค้ารายเดียวที่ได้รับอนุญาตให้เขียนข้อมูล ข้อมูลจอแสดงผล (ไคลเอ็นต์เพิ่มเติมจะได้รับสิทธิ์การเข้าถึงกล้องในระดับอ่านอย่างเดียว) รูปภาพ)

EVS Manager ใช้ API เดียวกับไดรเวอร์ HAL ที่สำคัญ และ ให้บริการเพิ่มเติมโดยการสนับสนุนลูกค้าที่ใช้งานพร้อมกันหลายราย (มากกว่า ลูกค้ารายหนึ่งสามารถเปิดกล้องผ่านตัวจัดการ EVS และรับวิดีโอ สตรีม)

วันที่ ผู้จัดการ EVS และ
แผนภาพ API ฮาร์ดแวร์ EVS
รูปที่ 2 EVS Manager แสดงกระจก EVS ที่ใช้งานอยู่ API ฮาร์ดแวร์

แอปไม่เห็นความแตกต่างเมื่อทำงานผ่าน HAL ของฮาร์ดแวร์ EVS หรือ EVS Manager API ยกเว้นที่ EVS Manager API อนุญาตให้ เข้าถึงสตรีมจากกล้องพร้อมกัน ผู้จัดการ EVS เองก็เป็นผู้ได้รับอนุญาต เลเยอร์ฮาร์ดแวร์ EVS ฮาร์ดแวร์ HAL และทำหน้าที่เป็นพร็อกซีสำหรับฮาร์ดแวร์ EVS HAL

ส่วนต่อไปนี้จะอธิบายเฉพาะการเรียกที่มี พฤติกรรม (เพิ่มเติม) ในการใช้งานตัวจัดการ EVS การโทรที่เหลืออยู่คือ เหมือนกับคำอธิบาย EVS HAL

IEvsEnumerator

openCamera(string camera_id) generates (IEvsCamera camera);

รับออบเจ็กต์อินเทอร์เฟซที่ใช้โต้ตอบกับกล้องบางตัว ที่ระบุโดยสตริง camera_id ที่ไม่ซ้ำกัน แสดงผล NULL เมื่อล้มเหลว ในเลเยอร์ตัวจัดการ EVS หากทรัพยากรระบบมีเพียงพอ กล้องที่เปิดอยู่แล้วอาจเปิดอีกครั้งด้วยกระบวนการอื่น ซึ่งทำให้ กระจายสตรีมวิดีโอไปยังแอปผู้บริโภคหลายแอป สตริง camera_id ที่เลเยอร์ EVS Manager เหมือนกันกับสตริง รายงานไปยังเลเยอร์ฮาร์ดแวร์ EVS แล้ว

กล้อง IEv

ตัวจัดการ EVS จัดให้การใช้งาน IEvsกล้องถ่ายรูป ทำในระบบเสมือนจริงภายใน ดังนั้นการดำเนินการกับกล้องของลูกค้า 1 ราย ไม่ส่งผลกระทบต่อไคลเอ็นต์อื่นๆ สามารถเข้าถึงกล้องได้อย่างอิสระ

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 ไม่เข้าใจผลของ คำควบคุมที่ผู้ให้บริการกำหนด ไม่ได้ใช้ระบบเสมือนจริง และผลข้างเคียงใดๆ จะมีผลกับไคลเอ็นต์ทั้งหมดของกล้องตัวนั้นๆ ตัวอย่างเช่น หากผู้ให้บริการใช้การเรียกนี้ ในการเปลี่ยนอัตราเฟรม ไคลเอ็นต์ทั้งหมดของกล้องที่มีเลเยอร์ฮาร์ดแวร์ที่ได้รับผลกระทบ จะได้รับเฟรมในอัตราใหม่

การแสดงผล IEv

อนุญาตเจ้าของจอแสดงผลเพียง 1 คน แม้ว่าจะอยู่ในระดับผู้จัดการ EVS ก็ตาม Manager ไม่ได้เพิ่มฟังก์ชันใดๆ และเพียงแค่ส่งอินเทอร์เฟซ IEvsDisplay เท่านั้น ไปจนถึงการติดตั้งใช้งาน HAL ที่สำคัญ

แอป EVS

Android มีการใช้การอ้างอิง C++ ที่มาพร้อมเครื่อง EVS แอปที่สื่อสารกับผู้จัดการ EVS และ HAL ของยานพาหนะเพื่อ จะมีฟังก์ชันพื้นฐานของกล้องหลัง แอปคาดว่าจะเริ่มทำงาน ในช่วงต้นของขั้นตอนการบูตระบบ โดยมีวิดีโอที่เหมาะสมแสดง กล้องที่พร้อมใช้งานและสถานะของรถ (สถานะเกียร์และไฟเลี้ยว) OEM สามารถแก้ไขหรือแทนที่แอป EVS ด้วยยานพาหนะเฉพาะของตน และการนำเสนอ

รูปที่ 3 ตรรกะตัวอย่างของแอป EVS, ซื้อกล้อง


วันที่
รูปที่ 4 ตรรกะตัวอย่างแอป EVS รับ จัดเฟรม Callback

เนื่องจากข้อมูลรูปภาพแสดงอยู่ในแอปในรูปแบบกราฟิกมาตรฐาน บัฟเฟอร์ แอปมีหน้าที่ย้ายรูปภาพจากแหล่งที่มา ลงในบัฟเฟอร์เอาต์พุต แม้ว่าวิธีนี้จะทำให้ การคัดลอกข้อมูลมีค่าใช้จ่าย แต่ยังทำให้แอปมีโอกาสแสดงภาพลงใน แสดงผลบัฟเฟอร์ในรูปแบบใดก็ได้ตามต้องการ

ตัวอย่างเช่น แอปอาจเลือกที่จะย้ายข้อมูลพิกเซลเอง อาจมีการดำเนินการปรับขนาดหรือการหมุนแบบอินไลน์ แอปสามารถ และยังเลือกใช้ภาพต้นฉบับเป็นพื้นผิว OpenGL และแสดงผลที่ซับซ้อน ไปยังบัฟเฟอร์เอาต์พุต รวมถึงองค์ประกอบเสมือน เช่น ไอคอน หลักเกณฑ์ และภาพเคลื่อนไหว แอปที่ซับซ้อนขึ้นอาจเลือก กล้องอินพุตที่ทำงานพร้อมกันหลายตัวและรวมเข้าเป็นเฟรมเอาต์พุตเดียว (เช่น สำหรับใช้ในมุมมองด้านบนลง มุมมองเสมือนจริงของสภาพแวดล้อมยานพาหนะ)

ใช้ EGL/SurfaceFlinger ใน HAL จอแสดงผล EVS

ส่วนนี้จะอธิบายวิธีใช้ EGL เพื่อแสดงผลการใช้งาน HAL จอแสดงผล EVS ใน Android 10

รถยนต์ EVS การใช้การอ้างอิง HAL ใช้ EGL เพื่อแสดงการแสดงตัวอย่างจากกล้อง หน้าจอและใช้ libgui เพื่อสร้างพื้นที่แสดงผล EGL เป้าหมาย ใน Android 8 (ขึ้นไป) libgui ได้รับการจัดประเภทเป็น VNDK-private หมายถึงกลุ่มไลบรารีที่มีให้กับไลบรารี VNDK ซึ่งกระบวนการของผู้ให้บริการไม่สามารถใช้งานได้ เนื่องจากการติดตั้งใช้งาน HAL ต้องอยู่ในพาร์ติชันผู้ให้บริการ ผู้ให้บริการจึงไม่สามารถใช้ แสดงให้เห็นการนำไปใช้งาน HAL

การสร้าง Libgui สำหรับกระบวนการของผู้ให้บริการ

การใช้ libgui เป็นตัวเลือกเดียวในการใช้ EGL/SurfaceFlinger ในการใช้งาน Display HAL ของ EVS วิธีใช้งาน libgui ที่ง่ายที่สุดคือ ผ่าน เฟรมเวิร์ก/เนทีฟ/ไลบรารี/กุย โดยตรงโดยใช้เป้าหมายบิลด์เพิ่มเติมในสคริปต์บิลด์ เป้าหมายนี้เหมือนกับ เป้าหมาย 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 จะมีเฉพาะใน Android 8 กระบวนการของเฟรมเวิร์ก และทำให้กระบวนการของผู้ให้บริการไม่สามารถเข้าถึงได้ แต่ กระบวนการของผู้ให้บริการควรใช้ /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 มีวิธีการเลือกแฟ้ม ไดรเวอร์ของ libbinder ซึ่งลิงก์กับกระบวนการของไลบรารี userspace

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

ถ้าอุปกรณ์ติดตั้งใช้งานเสียงแหลมเต็ม 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

อย่างไรก็ตาม การเพิ่มสิทธิ์เหล่านี้ทำให้บิลด์ล้มเหลวเนื่องจากเป็นการละเมิดสิ่งต่อไปนี้ กฎห้ามอนุญาตที่กำหนดไว้ใน system/sepolicy/domain.te สำหรับอุปกรณ์ที่มีเสียงแหลมเต็ม

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;