ใน Android 12 นั้น GKI 2.0 จะแทนที่การจัดสรร ION ด้วย ฮีป DMA-BUF เกิดจากสาเหตุต่อไปนี้
- ความปลอดภัย: เนื่องจากฮีป DMA-BUF แต่ละฮีปเป็นอุปกรณ์อักขระที่แยกจากกัน การเข้าถึง
แต่ละฮีปสามารถควบคุมแยกกันได้ด้วย sepolicy นี่ไม่ใช่
ที่เป็นไปได้ด้วย ION เนื่องจากการจัดสรรจากฮีปทั้งหมดต้องใช้การเข้าถึง
อุปกรณ์
/dev/ion
- ความเสถียรของ ABI: อินเทอร์เฟซ IOCTL ของเฟรมเวิร์กฮีป DMA-BUF ต่างจาก ION ABI เสถียรเนื่องจากมีการบำรุงรักษาในเคอร์เนลของ Linux ต้นทาง
- การกำหนดมาตรฐาน: เฟรมเวิร์กฮีป DMA-BUF มี UAPI ที่กำหนดไว้มาเป็นอย่างดี ไอออน อนุญาตให้ใช้ Flag ที่กำหนดเองและรหัสฮีปที่ขัดขวางการพัฒนาการทดสอบทั่วไป เนื่องจากการใช้งาน ION ของอุปกรณ์แต่ละเครื่องอาจทำงานต่างกัน
สาขา android12-5.10
ของ Kernel ร่วมของ Android ปิดใช้อยู่
CONFIG_ION
ในวันที่ 1 มีนาคม 2021
ฉากหลัง
ต่อไปนี้เป็นการเปรียบเทียบคร่าวๆ ระหว่างฮีป ION และ DMA-BUF
ความคล้ายคลึงระหว่างเฟรมเวิร์กฮีป ION และ DMA-BUF
- ���ฟรมเวิร์กฮีป ION และ DMA-BUF เป็นผู้ส่งออก DMA-BUF ที่ใช้ฮีปทั้งคู่
- ทั้งคู่ให้แต่ละฮีปกำหนดตัวจัดสรรและการดำเนินการ DMA-BUF ของตัวเอง
- ประสิทธิภาพการจัดสรรคล้ายกันเนื่องจากทั้ง 2 รูปแบบต้องการ IOCTL เดียว สำหรับการจัดสรร
ความแตกต่างระหว่างเฟรมเวิร์กฮีป ION และ DMA-BUF
ฮีป ION | ฮีป DMA-BUF |
---|---|
การจัดสรร ION ทั้งหมดจะดำเนินการด้วย /dev/ion
|
ฮีป DMA-BUF แต่ละรายการคืออุปกรณ์อักขระซึ่งอยู่ที่ /dev/dma_heap/<heap_name>
|
ION รองรับฮีป Flag | ฮีป DMA-BUF ไม่รองรับแฟล็กส่วนตัวฮีป โดยแต่ละประเภทก็
การจัดสรรจะดำเนินการจากฮีปอื่นแทน ตัวอย่างเช่น แคชและ
ตัวแปรฮีปของระบบที่ไม่ได้แคชคือฮีปแยกต่างหากที่
/dev/dma_heap/system และ
/dev/dma_heap/system_uncached
|
ต้องระบุรหัสฮีป/มาสก์และแฟล็กสำหรับการจัดสรร | ชื่อฮีปจะใช้สำ���รับการจัดสรร |
ส่วนต่อไปนี้แสดงรายการองค์ประกอบที่ใช้จัดการ ION และอธิบายวิธี ให้เปลี่ยนไปใช้เฟรมเวิร์กฮีป DMA-BUF
การเปลี่ยนไดรเวอร์เคอร์เนลจาก ION เป็นฮีป DMA-BUF
ไดรเวอร์เคอร์เนลที่ใช้ฮีป ION
ทั้งฮีป ION และ DMA-BUF จะช่วยให้แต่ละฮีปสามารถใช้ตัวจัดสรรของตนเองและ การดำเนินการ DMA-BUF คุณจึงสามารถเปลี่ยนจากการใช้ฮีป ION เป็นฮีป DMA-BUF โดยใช้ API ชุดอื่นในการลงทะเบียนฮีป ตารางนี้ แสดง API การลงทะเบียนฮีป ION และฮีป API ของ DMA-BUF ที่เทียบเท่า
ฮีป ION | ฮีป DMA-BUF |
---|---|
void ion_device_add_heap(struct ion_heap *heap)
|
struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
|
void ion_device_remove_heap(struct ion_heap *heap)
|
void dma_heap_put(struct dma_heap *heap);
|
ฮีป DMA-BUF ไม่รองรับแฟล็กส่วนตัวฮีป ดังนั้นแต่ละตัวแปรของฮีป
ต้องลงทะเบียนเป็นรายบุคคลโดยใช้ dma_heap_add()
API เพื่อช่วยอำนวยความสะดวกในการแชร์โค้ด ขอแนะนำให้ลงทะเบียนตัวแปรทั้งหมดของ
ฮีปเดียวกันในไดรเวอร์เดียวกัน
ตัวอ��่าง dma-buf: system_heap นี้
แสดงการใช้งานรูปแบบที่แคชไว้และไม่แคชของระบบ
ฮีป
ใช้ dma-buf: ฮีปส์: เทมเพลตตัวอย่าง เพื่อสร้างฮีป DMA-BUF ตั้งแต่ต้น
ไดรเวอร์เคอร์เนลที่จัดสรรจากฮีป ION โดยตรง
เฟรมเวิร์กฮีป DMA-BUF ยังนำเสนอ อินเทอร์เฟซการจัดสรร สำหรับไคลเอ็นต์ในเคอร์เนล แทนที่จะระบุฮีปมาสก์และแฟล็กเพื่อเลือก ประเภทของการจัดสรร อินเทอร์เฟซที่นำเสนอโดยฮีป DMA-BUF จะใช้ชื่อฮีป เป็นอินพุต
รายการต่อไปนี้แสดง API การจัดสรร ION ในเคอร์เนลและ DMA-BUF ที่เทียบเท่า
API การจัดสรรฮีป ไดรเวอร์เคอร์เนลใช้ dma_heap_find()
API เพื่อค้นหาได้
การมีอยู่ของฮีป API ส่งคืนตัวชี้ไปยังอินสแตนซ์ของ
struct dma_heap ซึ่งสามารถส่งเป็นอาร์กิวเมนต์ไปยัง
API dma_heap_buffer_alloc()
ฮีป ION | ฮีป DMA-BUF |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
ไดรเวอร์ Kernel ที่ใช้ DMA-BUF
ไม่จำเป็นต้องมีการเปลี่ยนแปลงใดๆ สำหรับไดรเวอร์ที่นำเข้าเฉพาะ DMA-BUF เนื่องจากบัฟเฟอร์ ที่จัดสรรจากฮีป ION จะทำงานเหมือนกับบัฟเฟอร์ที่จัดสรรจาก ฮีป DMA-BUF ที่เทียบเท่า
เปลี่ยนไคลเอ็นต์พื้นที่ผู้ใช้ของ ION เป็นฮีป DMA-BUF
เพื่อให้การเปลี่ยนเป็นไปอย่างง่ายดายสำหรับลูกค้าพื้นที่ของผู้ใช้ของ ION เราแนะนำให้รู้จักองค์ประกอบนี้
ไลบรารีที่ชื่อว่า
libdmabufheap
พร้อมใช้งาน libdmabufheap
รองรับการจัดสรรในฮีป DMA-BUF
และฮีป ION ระบบตรวจสอบก่อน��่ามีฮีป DMA-BUF ของชื่อที่ระบุหรือไม่
และหากไม่ใช่ จะกลับไปเป็นฮีป ION ที่เทียบเท่ากัน (หากมี)
ลูกค้าควรเริ่มต้น
BufferAllocator
ระหว่างการเริ่มต้นแทนที่จะเปิด /dev/ion using
ion_open()
ซึ่งเป็นเพราะข้อบ่งชี้ไฟล์ที่สร้างโดยการเปิด
/dev/ion
และ /dev/dma_heap/<heap_name>
มีการจัดการ
ภายในโดยออบเจ็กต์ BufferAllocator
หากต้องการเปลี่ยนจาก libion
เป็น libdmabufheap
ให้แก้ไขพฤติกรรมของลูกค้าเป็น
ดังต่อไปนี้:
- ติดตามชื่อฮีปที่จะใช้เพื่อการจัดสรร แทนที่จะเป็นส่วนหัว ID/มาสก์และฮีปแฟล็ก
- แทนที่
ion_alloc_fd()
API ซึ่งรับฮีปมาสก์และอาร์กิวเมนต์แฟล็ก ด้วยBufferAllocator::Alloc()
API ซึ่งจะใช้ชื่อฮีปแทน
ตารางนี้แสดงการเปลี่ยนแปลงดังกล่าวโดยแสดงวิธีที่ libion
และ libdmabufheap
จัดสรรฮีปของระบบที่ไม่ได้แคช
ประเภทการจัดสรร | Libion | Libdmabufheap |
---|---|---|
การจัดสรรแคชจากฮีปของระบบ | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)
|
allocator->Alloc("system", size)
|
การจัดสรรที่ไม่ได้แคชจากฮีปของระบบ | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd)
|
allocator->Alloc("system-uncached", size)
|
ตัวแปรฮีปของระบบที่ไม่ได้แคช
กำลังรอการอนุมัติอัปสตรีม แต่เป็นส่วนหนึ่งของ android12-5.10
แล้ว
Branch
MapNameToIonHeap()
API จะอนุญาตให้แมปฮีปเพื่อรองรับการอัปเกรดอุปกรณ์
ลงในพารามิเตอร์ฮีปของ ION (ชื่อฮีปหรือมาสก์และแฟล็ก) เพื่อให้แท็กดังกล่าว
จะใช้การจัดสรรตามชื่อ ต่อไปนี้คือการจัดสรรตามชื่อ
ตัวอย่าง
เอกสารประกอบสำหรับ API ทั้งหมดที่แสดงโดย
libdmabufheap
พร้อมใช้งาน
คลัง
จะแสดงไฟล์ส่วนหัวเพื่อให้ไคลเอ็นต์ C ใช้งานด้วย
การใช้ Gralloc อ้างอิง
การใช้งาน Hikey960 Gralloc ใช้ libdmabufheap
เพื่อให้���ุณสามารถใช้เป็น
การอ้างอิง
การใช้งาน
การเพิ่มเติมที่จำเป็น
สำหรับฮีป DMA-BUF เฉพาะอุปกรณ์ใหม่ที่สร้าง ให้เพิ่มรายการใหม่ลงใน
ไฟล์ ueventd.rc
ของอุปกรณ์
การตั้งค่านี้ได้รับการตั้งค่าให้รองรับฮีป DMA-BUF
ตัวอย่าง
จะแสดงให้เห็นวิธีใช้สำหรับฮีประบบ DMA-BUF
การเพิ่ม Sepolicy ที่จำเป็น
เพิ่มสิทธิ์ sepolicy เพื่อช่วยให้ไคลเอ็นต์พื้นที่ผู้ใช้เข้าถึง DMA-BUF ใหม่ ฮีป ต้องเพิ่มค่านี้ สิทธิ์ ตัวอย่างแสดงสิทธิ์ sepolicy ที่สร้างขึ้นสำหรับไคลเอ็นต์ต่างๆ เพื่อ เข้าถึงฮีประบบ DMA-BUF
เข้าถึงฮีปของผู้ให้บริการจากโค้ดเฟรมเวิร์ก
โค้ดเฟรมเวิร์กสามารถจัดสรรได้เฉพาะจากที่ได้รับการอนุมัติล่วงหน้าเท่านั้นเพื่อให้เป็นไปตามข้อกำหนดของ Treble ของผู้ให้บริการจำนวนมาก
จากความคิดเห็นที่ได้รับจากพาร์ทเนอร์ Google ได้ระบุ 2 หมวดหมู่ ฮีปของผู้ให้บริการที่ต้องเข้าถึงจากโค้ดเฟรมเวิร์ก:
- ฮีปที่อิงตามฮีปของระบบพร้อมด้วยอุปกรณ์หรือประสิทธิภาพเฉพาะ SoC การเพิ่มประสิทธิภาพ
- ฮีปที่จะจัดสรรจากหน่วยความจำที่มีการป้องกัน
ฮีปที่อิงจากฮีปของระบบที่มีการเพิ่มประสิทธิภาพอุปกรณ์หรือ SoC โดย��ฉพาะ
เพื่อรองรับกรณีการใช้งานนี้ การใช้ฮีปของฮีป DMA-BUF เริ่มต้น สามารถลบล้างระบบได้
CONFIG_DMABUF_HEAPS_SYSTEM
ปิดในgki_defconfig
เพื่ออนุญาตให้ เป็นโมดูลของผู้ให้บริการ- การทดสอบการปฏิบัติตามข้อกำหนดของ VTS ช่วยให้มั่นใจว่ามีฮีปอยู่ที่
/dev/dma_heap/system
การทดสอบยังยืนยันด้วยว่ามีการจัดสรรฮีปจาก ข้อบ่งชี้ไฟล์ที่ส่งก��ับ (fd
) สามารถแมปด้วยหน่วยความจำ (mmapped) จากผู้ใช้ได้ พื้นที่ทำงาน
ประเด็นก่อนหน้านี้ก็เป็นจริงสำหรับตัวแปรที่ไม่ได้แคชของฮีประบบ แม้ว่าเครื่องมือจะไม่ได้จำเป็นสำหรับอุปกรณ์ที่รองรับ IO อย่างเต็มรูปแบบ
ฮีปที่จะจัดสรรจากหน่วยความจำที่มีการป้องกัน
การใช้ฮีปที่ปลอดภัยต้องใช้เฉพาะผู้ให้บริการตั้งแต่ Android Common เคอร์เนลไม่รองรับการใช้งานฮีปที่ปลอดภัยทั่วไป
- ลงทะเบียนการใช้งานเฉพาะผู้ให้บริการเป็น
/dev/dma_heap/system-secure<vendor-suffix>
- การติดตั้งใช้งานฮีปเหล่านี้เป็นตัวเลือกที่ไม่บังคับ
- หากมีฮีปอยู่ การทดสอบ VTS ช่วยให้มั่นใจว่ามีการจัดสรรจากฮีปได้
- คอมโพเนนต์เฟรมเวิร์กจะมีสิทธิ์เข้าถึงฮีปเหล่านี้เพื่อให้ เปิดใช้งานการใช้ฮีปผ่าน HAL ของตัวแปลงรหัส/HAL ที่ไม่มีการเชื่อมโยง กระบวนการเดียวกัน อย่างไรก็ตาม ฟีเจอร์เฟรมเวิร์กของ Android ทั่วไปจะใช้งานไม่ได้เนื่องจาก ความแปรปรวนในรายละเอียดการใช้งาน หากฮีปแบบปลอดภัยทั่วไป โดยจะเพิ่มเข้ามาใน Kernel ร่วมของ Android ในอนาคต อุปกรณ์จะต้องใช้ ABI อื่นเพื่อหลีกเลี่ยงความขัดแย้งกับการอัปเกรดอุปกรณ์
ตัวจัดสรรตัวแปลงรหัส 2 สำหรับฮีป DMA-BUF
ตัวแปลงรหัส 2 ตัวแปลงรหัสสำหรับฮีป DMA-BUF อินเทอร์เฟซ พร้อมให้บริการใน AOSP
อินเทอร์เฟซร้านค้าคอมโพเนนต์ที่อนุญาตให้ระบุพารามิเตอร์ฮีปจาก C2 HAL ใช้ได้กับที่จัดสรรฮีป C2 DMA-BUF
ตัวอย่างโฟลว์การเปลี่ยนสำหรับฮีป ION
เพื่อให้การเปลี่ยนจาก ION เป็นฮีป DMA-BUF เป็นไปอย่างราบรื่น libdmabufheap
จะอนุญาตให้
โดยเปลี่ยนครั้งละ 1 ฮีป ขั้นตอนต่อไปนี้จะแสดงเวิร์กโฟลว์ที่แนะนำ
สำหรับการเปลี่ยนฮีป ION ที่ไม่ใช่แบบเดิมชื่อ my_heap
ซึ่งรองรับฮีป ION
ION_FLAG_MY_FLAG
ขั้นตอนที่ 1: สร้างฮีปที่เทียบเท่ากับ ION ในเฟรมเวิร์ก DMA-BUF ด้วยวิธีนี้
ตัวอย่างเช่น เนื่องจากฮีป ION my_heap
รองรับแฟล็ก ION_FLAG_MY_FLAG
เราจึง
ลงทะเบียนฮีป DMA-BUF 2 ฮีป:
- ลักษณะการทำงานของ
my_heap
ตรงกันทุกประการกับลักษณะการทำงานของฮีป ION กับ ปิดใช้ FlagION_FLAG_MY_FLAG
อยู่ - ลักษณะการทำงานของ
my_heap_special
ตรงกันทุกประการกับลักษณะการทำงานของฮีป ION ที่เปิดใช้งานการแฟล็กION_FLAG_MY_FLAG
ขั้นตอนที่ 2: สร้างการเปลี่ยนแปลงที่เพิ่งเกิดขึ้นสำหรับ my_heap
ใหม่และ
my_heap_special
ฮีป DMA-BUF ในตอนนี้ ฮีปจะแสดงเป็น
/dev/dma_heap/my_heap
และ /dev/dma_heap/my_heap_special
โดยมี
สิทธิ์ที่ต้องการ
ขั้นตอนที่ 3: แก้ไขไคลเอ็นต์ที่จัดสรรจาก my_heap
เพื่อลิงก์กับ libdmabufheap
ในระหว่างการเริ่มต้นไคลเอ็นต์ ให้สร้างอินสแตนซ์
BufferAllocator
และใช้ MapNameToIonHeap()
API เพื่อแมป
<ION heap name/mask, flag>
ร่วมกับชื่อฮีป DMA-BUF ที่เทียบเท่า
เช่น
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
แทนที่จะใช้ MapNameToIonHeap()
API กับพารามิเตอร์ชื่อและแฟล็ก
คุณสามารถสร้างการแมป
<ION heap mask, flag>
ไปยังฮีป DMA-BUF ที่เทียบเท่า
ชื่อ
โดยการตั้งค่าพารามิเตอร์ชื่อฮีปของ ION ให้ว่างไว้
ขั้นตอนที่ 4: แทนที่คำขอ ion_alloc_fd()
ด้วย
BufferAllocator::Alloc()
โดยใช้ชื่อฮีปที่เหมาะสม
ประเภทการจัดสรร | Libion | Libdmabufheap |
---|---|---|
การจัดสรรจาก my_heap พร้อมธง
ยกเลิกการตั้งค่า ION_FLAG_MY_FLAG แล้ว
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
การจัดสรรจาก my_heap พร้อมธง
ION_FLAG_MY_FLAG ชุด
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
ที่จุดนี้ไคลเอ็นต์ใช้งานได้แล้วแต่ยังคงจัดสรรจากฮีป ION เนื่อ��จากไม่มีสิทธิ์ sepolicy ที่จำเป็นในการเปิด DMA-BUF ฮีป
ขั้นตอนที่ 5: สร้างสิทธิ์ sepolicy ที่จำเป็นสำหรับลูกค้าในการเข้าถึง ฮีป DMA-BUF ใหม่ ตอนนี้ลูกค้าพร้อมที่จะจัดสรรจาก ฮีป DMA-BUF
ขั้นตอนที่ 6: ตรวจสอบว่าการจัดสรรมาจากฮีป DMA-BUF ใหม่ โดยการตรวจสอบ logcat
ขั้นตอนที่ 7: ปิดใช้ฮีป ION my_heap
ในเคอร์เนล หากรหัสไคลเอ็นต์
ไม่จำเป็นต้องสนับสนุนการอัปเกรดอุปกรณ์ (ซึ่งเคอร์เนลอาจสนับสนุนเฉพาะ ION เท่านั้น
ฮีป) คุณยังสามารถนำการเรียกใช้ MapNameToIonHeap()
ออกได้ด้วย