Modularizing ION Heaps for GKI

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.

Modular ION Heaps

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.

Implementing

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.