Many Android OEMs modify the ION kernel driver for various reasons, such as adding vendor heaps and customizing cache management (for details on these modifications, refer to Integrating the ION memory allocator). To enable OEMs to retain such modifications when using the Generic Kernel Image (GKI), Android Common Kernel v5.4 introduces a framework for modularizing vendor-specific ION heaps while keeping the core ION driver built in. The following figure shows the kernel image layout.
Figure 1. Modularized ION kernel driver
Modular ION heaps have the following advantages.
- The ION core driver can be part of the GKI image, enabling all device-independent performance optimizations and bug fixes to reach all devices.
- The ION core driver in the common kernel can handle heap registration and manage the interface to userspace and kernel clients. The vendor heap modules are required only to implement the custom heap operations.
- The ION core driver (as part of the GKI) can include hooks for easier memory usage tracking, which wasn't possible when each OEM had their own version of the ION driver.
- Modular vendor ION heaps should make any future transitions to
dmabuf
heaps easier.
Implementation
ION heap modules can register their own dmabuf
operations to override the ones
registered by the core ION driver. A dmabuf
operation (such as get_flags()
)
that isn't supported by the core ION driver returns -EOPNOTSUPP
if the heap
implementation lacks the necessary overrides.
To improve performance, the dmabuf
driver can perform partial cache
maintenance (see
changelist).
Kernel clients can use the dma_buf_begin_cpu_access_partial
and
dma_buf_end_cpu_access_partial
functions to perform partial cache maintenance.
The Android Common Kernel contains modular implementations of the system and contiguous memory allocator (CMA) heaps for use as a reference for heap modularization.
Changes to the ION UAPI header
The ION user space API (UAPI) header contains an ion_heap_id
enum for use in
defining a range of heap IDs for use by vendor heaps.
/**
* ion_heap_id - list of heap IDs that Android can use
*
* @ION_HEAP_SYSTEM ID for the ION_HEAP_TYPE_SYSTEM
* @ION_HEAP_DMA_START Start of reserved ID range for heaps of type ION_HEAP_TYPE_DMA
* @ION_HEAP_DMA_END End of reserved ID range for heaps of type ION_HEAP_TYPE_DMA
* @ION_HEAP_CUSTOM_START Start of reserved ID range for heaps of custom type
* @ION_HEAP_CUSTOM_END End of reserved ID range for heaps of custom type
*/
enum ion_heap_id {
ION_HEAP_SYSTEM = (1 << ION_HEAP_TYPE_SYSTEM),
ION_HEAP_DMA_START = (ION_HEAP_SYSTEM << 1),
ION_HEAP_DMA_END = (ION_HEAP_DMA_START << 7),
ION_HEAP_CUSTOM_START = (ION_HEAP_DMA_END << 1),
ION_HEAP_CUSTOM_END = (ION_HEAP_CUSTOM_START << 22),
};
In addition, a new IOCTL
(ION_IOC_ABI_VERSION
) can help user space clients
determine if modular heaps are being used.
Overriding the generic system heap
The ION system heap is built in and is part of the GKI image to ensure that any
feature that needs access to a generic/device-independent heap can depend on its
existence. As such, you can't override the heap ID of ION_HEAP_SYSTEM
. To
create a customized system heap, use a heap ID in the custom range
(ION_HEAP_CUSTOM_START
to ION_HEAP_CUSTOM_END
) to perform allocations.