228 lines
11 KiB
C++
228 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <BufferAllocator/dmabufheap-defs.h>
|
|
|
|
#include <android-base/unique_fd.h>
|
|
#include <linux/ion_4.12.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <cstdint>
|
|
#include <shared_mutex>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
|
|
class BufferAllocator {
|
|
public:
|
|
BufferAllocator();
|
|
~BufferAllocator() {}
|
|
|
|
/* Not copyable or movable */
|
|
BufferAllocator(const BufferAllocator&) = delete;
|
|
BufferAllocator& operator=(const BufferAllocator&) = delete;
|
|
|
|
/**
|
|
* Maps a dmabuf heap to an equivalent ion heap configuration. This method is required since
|
|
* dmabuf heaps do not support heap flags. This means that a single ion heap may encompass the
|
|
* functionality of multiple dmabuf heaps by using heap flags. If the interface being used is
|
|
* non-legacy ion, the mapping from dmabuf heap name to non-legacy ion heap name will be created
|
|
* and the legacy parameters will be ignored.
|
|
* The method can be deprecated once all devices have
|
|
* migrated to dmabuf heaps from ion. Returns an error code when the
|
|
* interface used is non-legacy ion and the @ion_heap_name parameter is non-empty and
|
|
* invalid or if the interface used is legacy ion and @legacy_ion_heap_mask
|
|
* is invalid(0);
|
|
* @heap_name: dmabuf heap name.
|
|
* @ion_heap_name: name of the equivalent ion heap - if empty ("") legacy heap mask will be used
|
|
* @ion_heap_flags: flags to be passed to the ion heap @ion_heap_name for it to function
|
|
* equivalently to the dmabuf heap @heap_name. Ignored if ion_heap_name is empty("").
|
|
* @legacy_ion_heap_mask: heap mask for the equivalent legacy ion heap.
|
|
* @legacy_ion_heap_flags: flags to be passed to the legacy ion heap for it
|
|
* to function equivalently to dmabuf heap @heap_name.
|
|
*/
|
|
int MapNameToIonHeap(const std::string& heap_name, const std::string& ion_heap_name,
|
|
unsigned int ion_heap_flags = 0, unsigned int legacy_ion_heap_mask = 0,
|
|
unsigned int legacy_ion_heap_flags = 0);
|
|
|
|
/* *
|
|
* Returns a dmabuf fd if the allocation in one of the specified heaps is successful and
|
|
* an error code otherwise. If dmabuf heaps are supported, tries to allocate in the
|
|
* specified dmabuf heap. If allocation fails in the specified dmabuf heap and ion_fd is a
|
|
* valid fd, goes through saved heap data to find a heap ID/mask to match the specified heap
|
|
* names and allocates memory as per the specified parameters. For vendor defined heaps with a
|
|
* legacy ION interface(no heap query support), MapNameToIonMask() must be called prior to
|
|
* invocation of Alloc() to map a heap name to an equivalent heap mask and heap flag
|
|
* configuration.
|
|
* @heap_name: name of the heap to allocate in.
|
|
* @len: size of the allocation.
|
|
* @heap_flags: flags passed to heap.
|
|
* @legacy_align: alignment value used only by legacy ION
|
|
*/
|
|
int Alloc(const std::string& heap_name, size_t len, unsigned int heap_flags = 0, size_t legacy_align = 0);
|
|
|
|
/* *
|
|
* Returns a dmabuf fd if the allocation in system heap(cached/uncached) is successful and
|
|
* an error code otherwise. Allocates in the 'system' heap if CPU access of
|
|
* the buffer is expected and 'system-uncached' otherwise. If the 'system-uncached'
|
|
* heap is not supported, falls back to the 'system' heap.
|
|
* For vendor defined heaps with a legacy ION interface(no heap query support),
|
|
* MapNameToIonMask() must be called prior to invocation of AllocSystem() to
|
|
* map names 'system'(and optionally 'system-uncached' if applicable) to an
|
|
* equivalent heap mask and heap flag configuration;
|
|
* configuration.
|
|
* @cpu_access: indicates if CPU access of the buffer is expected.
|
|
* @len: size of the allocation.
|
|
* @heap_flags: flags passed to heap.
|
|
* @legacy_align: alignment value used only by legacy ION
|
|
*/
|
|
int AllocSystem(bool cpu_access, size_t len, unsigned int heap_flags = 0,
|
|
size_t legacy_align = 0);
|
|
|
|
/**
|
|
* Optional custom callback for legacy ion implementation that can be specified as a
|
|
* parameter to CpuSyncStart() and CpuSyncEnd(). Its first argument is an fd to /dev/ion.
|
|
* The callback MUST NOT assume ownership of the fd. The fd will be closed once the
|
|
* callback returns. The second argument is a dma_buf fd, upon which the custom sync IOCTL
|
|
* should be called. The third argument is a void pointer that can be used to pass data
|
|
* to be used in the IOCTL.
|
|
* If provided as an argument to CpuSyncStart() and CpuSyncEnd(), the callback will be used
|
|
* for syncing a shared dmabuf fd with memory(instead of ion_sync_fd()). It will be invoked
|
|
* with a dup of ion_fd_ as its first argument. Return 0 on success and error code otherwise
|
|
* which will become the return value for CpuSyncStart() and CpuSyncEnd().
|
|
*/
|
|
typedef std::function<int(int, int, void *)> CustomCpuSyncLegacyIon;
|
|
|
|
/**
|
|
* Must be invoked before CPU access of the allocated memory.
|
|
* For a legacy ion interface, syncs a shared dmabuf fd with memory either using
|
|
* ION_IOC_SYNC ioctl or using callback @legacy_ion_cpu_sync if specified. For
|
|
* non-legacy ION and dmabuf heap interfaces, DMA_BUF_IOCTL_SYNC is used.
|
|
* @fd: dmabuf fd. When the legacy version of ion is in use and a callback
|
|
* function is supplied, this is passed as the second argument to legacy_ion_cpu_sync.
|
|
* @sync_type: specifies if the sync is for read, write or read/write.
|
|
* @legacy_ion_cpu_sync: optional callback for legacy ion interfaces. If
|
|
* specified, will be invoked instead of ion_sync_fd()
|
|
* to sync dmabuf_fd with memory. The paremeter will be ignored if the interface being
|
|
* used is not legacy ion.
|
|
* @legacy_ion_custom_data: When the legacy version of ion is in use and a callback
|
|
* function is supplied, this pointer is passed as the third argument to
|
|
* legacy_ion_cpu_sync. It is intended to point to data for performing the callback.
|
|
*
|
|
* Returns 0 on success and an error code otherwise.
|
|
*/
|
|
int CpuSyncStart(unsigned int dmabuf_fd, SyncType sync_type = kSyncRead,
|
|
const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync = nullptr,
|
|
void *legacy_ion_custom_data = nullptr);
|
|
|
|
/**
|
|
* Must be invoked once CPU is done accessing the allocated memory.
|
|
* For a legacy ion interface, syncs a shared dmabuf fd with memory using
|
|
* either ION_IOC_SYNC ioctl or using callback @legacy_ion_cpu_sync if
|
|
* specified. For non-legacy ION and dmabuf heap interfaces,
|
|
* DMA_BUF_IOCTL_SYNC is used.
|
|
* @dmabuf_fd: dmabuf fd. When the legacy version of ion is in use and a callback
|
|
* function is supplied, this is passed as the second argument to legacy_ion_cpu_sync.
|
|
* @sync_type: specifies if sync_type is for read, write or read/write.
|
|
* @legacy_ion_cpu_sync: optional callback for legacy ion interfaces. If
|
|
* specified, will be invoked instead of ion_sync_fd with a dup of ion_fd_ as its
|
|
* argument. The parameter will be ignored if the interface being used is
|
|
* not legacy ion.
|
|
* @legacy_ion_custom_data: When the legacy version of ion is in use and a callback
|
|
* function is supplied, this pointer is passed as the third argument to
|
|
* legacy_ion_cpu_sync. It is intended to point to data for performing the callback.
|
|
*
|
|
* Returns 0 on success and an error code otherwise.
|
|
*/
|
|
int CpuSyncEnd(unsigned int dmabuf_fd, SyncType sync_type = kSyncRead,
|
|
const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync = nullptr,
|
|
void* legacy_ion_custom_data = nullptr);
|
|
|
|
/**
|
|
* Query supported DMA-BUF heaps.
|
|
*
|
|
* @return the list of supported DMA-BUF heap names.
|
|
*/
|
|
static std::unordered_set<std::string> GetDmabufHeapList();
|
|
|
|
/**
|
|
*
|
|
* Check if ION is supported on the device.
|
|
*
|
|
* @return true if /dev/ion is present on the device, otherwise false.
|
|
*/
|
|
static bool CheckIonSupport();
|
|
|
|
private:
|
|
int OpenDmabufHeap(const std::string& name);
|
|
void QueryIonHeaps();
|
|
int GetDmabufHeapFd(const std::string& name);
|
|
bool DmabufHeapsSupported() { return !dmabuf_heap_fds_.empty(); }
|
|
int GetIonHeapIdByName(const std::string& heap_name, unsigned int* heap_id);
|
|
int MapNameToIonMask(const std::string& heap_name, unsigned int ion_heap_mask,
|
|
unsigned int ion_heap_flags = 0);
|
|
int MapNameToIonName(const std::string& heap_name, const std::string& ion_heap_name,
|
|
unsigned int ion_heap_flags = 0);
|
|
void LogInterface(const std::string& interface);
|
|
int IonAlloc(const std::string& heap_name, size_t len, unsigned int heap_flags = 0, size_t legacy_align = 0);
|
|
int DmabufAlloc(const std::string& heap_name, size_t len);
|
|
|
|
struct IonHeapConfig {
|
|
unsigned int mask;
|
|
unsigned int flags;
|
|
};
|
|
int GetIonConfig(const std::string& heap_name, IonHeapConfig& heap_config);
|
|
int LegacyIonCpuSync(unsigned int fd, const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync_custom,
|
|
void *custom_data);
|
|
int DoSync(unsigned int dmabuf_fd, bool start, SyncType sync_type,
|
|
const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync_custom,
|
|
void *custom_data);
|
|
|
|
/* Stores all open dmabuf_heap handles. */
|
|
std::unordered_map<std::string, android::base::unique_fd> dmabuf_heap_fds_;
|
|
/* Protects dma_buf_heap_fd_ from concurrent access */
|
|
std::shared_mutex dmabuf_heap_fd_mutex_;
|
|
|
|
/* saved handle to /dev/ion. */
|
|
android::base::unique_fd ion_fd_;
|
|
/**
|
|
* Stores the queried ion heap data. Struct ion_heap_date is defined
|
|
* as part of the ION UAPI as follows.
|
|
* struct ion_heap_data {
|
|
* char name[MAX_HEAP_NAME];
|
|
* __u32 type;
|
|
* __u32 heap_id;
|
|
* __u32 reserved0;
|
|
* __u32 reserved1;
|
|
* __u32 reserved2;
|
|
* };
|
|
*/
|
|
bool uses_legacy_ion_iface_ = false;
|
|
std::vector<struct ion_heap_data> ion_heap_info_;
|
|
inline static bool logged_interface_ = false;
|
|
/* stores a map of dmabuf heap names to equivalent ion heap configurations. */
|
|
std::unordered_map<std::string, struct IonHeapConfig> heap_name_to_config_;
|
|
/* protects heap_name_to_config_ from concurrent access */
|
|
std::shared_mutex heap_name_to_config_mutex_;
|
|
};
|