1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <sys/types.h> 20 21 #include <functional> 22 #include <shared_mutex> 23 #include <string> 24 #include <unordered_map> 25 #include <unordered_set> 26 #include <vector> 27 28 #include <linux/ion_4.12.h> 29 30 #include <android-base/unique_fd.h> 31 32 #include <BufferAllocator/dmabufheap-defs.h> 33 34 35 class BufferAllocator { 36 public: 37 BufferAllocator(); ~BufferAllocator()38 ~BufferAllocator() {} 39 40 /* Not copyable or movable */ 41 BufferAllocator(const BufferAllocator&) = delete; 42 BufferAllocator& operator=(const BufferAllocator&) = delete; 43 44 /** 45 * Maps a dmabuf heap to an equivalent ion heap configuration. This method is required since 46 * dmabuf heaps do not support heap flags. This means that a single ion heap may encompass the 47 * functionality of multiple dmabuf heaps by using heap flags. If the interface being used is 48 * non-legacy ion, the mapping from dmabuf heap name to non-legacy ion heap name will be created 49 * and the legacy parameters will be ignored. 50 * The method can be deprecated once all devices have 51 * migrated to dmabuf heaps from ion. Returns an error code when the 52 * interface used is non-legacy ion and the @ion_heap_name parameter is non-empty and 53 * invalid or if the interface used is legacy ion and @legacy_ion_heap_mask 54 * is invalid(0); 55 * @heap_name: dmabuf heap name. 56 * @ion_heap_name: name of the equivalent ion heap - if empty ("") legacy heap mask will be used 57 * @ion_heap_flags: flags to be passed to the ion heap @ion_heap_name for it to function 58 * equivalently to the dmabuf heap @heap_name. Ignored if ion_heap_name is empty(""). 59 * @legacy_ion_heap_mask: heap mask for the equivalent legacy ion heap. 60 * @legacy_ion_heap_flags: flags to be passed to the legacy ion heap for it 61 * to function equivalently to dmabuf heap @heap_name. 62 */ 63 int MapNameToIonHeap(const std::string& heap_name, const std::string& ion_heap_name, 64 unsigned int ion_heap_flags = 0, unsigned int legacy_ion_heap_mask = 0, 65 unsigned int legacy_ion_heap_flags = 0); 66 67 /* * 68 * Returns a dmabuf fd if the allocation in one of the specified heaps is successful and 69 * an error code otherwise. If dmabuf heaps are supported, tries to allocate in the 70 * specified dmabuf heap. If allocation fails in the specified dmabuf heap and ion_fd is a 71 * valid fd, goes through saved heap data to find a heap ID/mask to match the specified heap 72 * names and allocates memory as per the specified parameters. For vendor defined heaps with a 73 * legacy ION interface(no heap query support), MapNameToIonMask() must be called prior to 74 * invocation of Alloc() to map a heap name to an equivalent heap mask and heap flag 75 * configuration. 76 * @heap_name: name of the heap to allocate in. 77 * @len: size of the allocation. 78 * @heap_flags: flags passed to heap. 79 * @legacy_align: alignment value used only by legacy ION 80 */ 81 int Alloc(const std::string& heap_name, size_t len, unsigned int heap_flags = 0, size_t legacy_align = 0); 82 83 /* * 84 * Returns a dmabuf fd if the allocation in system heap(cached/uncached) is successful and 85 * an error code otherwise. Allocates in the 'system' heap if CPU access of 86 * the buffer is expected and 'system-uncached' otherwise. If the 'system-uncached' 87 * heap is not supported, falls back to the 'system' heap. 88 * For vendor defined heaps with a legacy ION interface(no heap query support), 89 * MapNameToIonMask() must be called prior to invocation of AllocSystem() to 90 * map names 'system'(and optionally 'system-uncached' if applicable) to an 91 * equivalent heap mask and heap flag configuration; 92 * configuration. 93 * @cpu_access: indicates if CPU access of the buffer is expected. 94 * @len: size of the allocation. 95 * @heap_flags: flags passed to heap. 96 * @legacy_align: alignment value used only by legacy ION 97 */ 98 int AllocSystem(bool cpu_access, size_t len, unsigned int heap_flags = 0, 99 size_t legacy_align = 0); 100 101 /** 102 * Optional custom callback for legacy ion implementation that can be specified as a 103 * parameter to CpuSyncStart() and CpuSyncEnd(). Its first argument is an fd to /dev/ion. 104 * The callback MUST NOT assume ownership of the fd. The fd will be closed once the 105 * callback returns. The second argument is a dma_buf fd, upon which the custom sync IOCTL 106 * should be called. The third argument is a void pointer that can be used to pass data 107 * to be used in the IOCTL. 108 * If provided as an argument to CpuSyncStart() and CpuSyncEnd(), the callback will be used 109 * for syncing a shared dmabuf fd with memory(instead of ion_sync_fd()). It will be invoked 110 * with a dup of ion_fd_ as its first argument. Return 0 on success and error code otherwise 111 * which will become the return value for CpuSyncStart() and CpuSyncEnd(). 112 */ 113 typedef std::function<int(int, int, void *)> CustomCpuSyncLegacyIon; 114 115 /** 116 * Must be invoked before CPU access of the allocated memory. 117 * For a legacy ion interface, syncs a shared dmabuf fd with memory either using 118 * ION_IOC_SYNC ioctl or using callback @legacy_ion_cpu_sync if specified. For 119 * non-legacy ION and dmabuf heap interfaces, DMA_BUF_IOCTL_SYNC is used. 120 * @dmabuf_fd: dmabuf fd. When the legacy version of ion is in use and a callback 121 * function is supplied, this is passed as the second argument to legacy_ion_cpu_sync. 122 * @sync_type: specifies if the sync is for read, write or read/write. 123 * @legacy_ion_cpu_sync: optional callback for legacy ion interfaces. If 124 * specified, will be invoked instead of ion_sync_fd() 125 * to sync dmabuf_fd with memory. The paremeter will be ignored if the interface being 126 * used is not legacy ion. 127 * @legacy_ion_custom_data: When the legacy version of ion is in use and a callback 128 * function is supplied, this pointer is passed as the third argument to 129 * legacy_ion_cpu_sync. It is intended to point to data for performing the callback. 130 * 131 * Returns 0 on success and an error code otherwise. 132 */ 133 int CpuSyncStart(unsigned int dmabuf_fd, SyncType sync_type = kSyncRead, 134 const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync = nullptr, 135 void *legacy_ion_custom_data = nullptr); 136 137 /** 138 * Must be invoked once CPU is done accessing the allocated memory. 139 * For a legacy ion interface, syncs a shared dmabuf fd with memory using 140 * either ION_IOC_SYNC ioctl or using callback @legacy_ion_cpu_sync if 141 * specified. For non-legacy ION and dmabuf heap interfaces, 142 * DMA_BUF_IOCTL_SYNC is used. 143 * @dmabuf_fd: dmabuf fd. When the legacy version of ion is in use and a callback 144 * function is supplied, this is passed as the second argument to legacy_ion_cpu_sync. 145 * @sync_type: specifies if sync_type is for read, write or read/write. 146 * @legacy_ion_cpu_sync: optional callback for legacy ion interfaces. If 147 * specified, will be invoked instead of ion_sync_fd with a dup of ion_fd_ as its 148 * argument. The parameter will be ignored if the interface being used is 149 * not legacy ion. 150 * @legacy_ion_custom_data: When the legacy version of ion is in use and a callback 151 * function is supplied, this pointer is passed as the third argument to 152 * legacy_ion_cpu_sync. It is intended to point to data for performing the callback. 153 * 154 * Returns 0 on success and an error code otherwise. 155 */ 156 int CpuSyncEnd(unsigned int dmabuf_fd, SyncType sync_type = kSyncRead, 157 const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync = nullptr, 158 void* legacy_ion_custom_data = nullptr); 159 160 /** 161 * Query supported DMA-BUF heaps. 162 * 163 * @return the list of supported DMA-BUF heap names. 164 */ 165 static std::unordered_set<std::string> GetDmabufHeapList(); 166 167 /** 168 * 169 * Check if ION is supported on the device. 170 * 171 * @return true if /dev/ion is present on the device, otherwise false. 172 */ 173 static bool CheckIonSupport(); 174 175 /** 176 * Set the name of a dma buffer. 177 * 178 * @dmabuf_fd: dmabuf file descriptor. 179 * @name: The name for the dmabuf. Length should not exceed DMA_BUF_NAME_LEN. 180 * 181 * @return Returns 0 on success, otherwise -1 and sets errno. 182 */ 183 static int DmabufSetName(unsigned int dmabuf_fd, const std::string& name); 184 185 private: 186 int OpenDmabufHeap(const std::string& name); 187 void QueryIonHeaps(); 188 int GetDmabufHeapFd(const std::string& name); DmabufHeapsSupported()189 bool DmabufHeapsSupported() { return !dmabuf_heap_fds_.empty(); } 190 int GetIonHeapIdByName(const std::string& heap_name, unsigned int* heap_id); 191 int MapNameToIonMask(const std::string& heap_name, unsigned int ion_heap_mask, 192 unsigned int ion_heap_flags = 0); 193 int MapNameToIonName(const std::string& heap_name, const std::string& ion_heap_name, 194 unsigned int ion_heap_flags = 0); 195 void LogInterface(const std::string& interface); 196 int IonAlloc(const std::string& heap_name, size_t len, unsigned int heap_flags = 0, size_t legacy_align = 0); 197 int DmabufAlloc(const std::string& heap_name, size_t len, int fd); 198 199 struct IonHeapConfig { 200 unsigned int mask; 201 unsigned int flags; 202 }; 203 int GetIonConfig(const std::string& heap_name, IonHeapConfig& heap_config); 204 int LegacyIonCpuSync(unsigned int fd, const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync_custom, 205 void *custom_data); 206 int DoSync(unsigned int dmabuf_fd, bool start, SyncType sync_type, 207 const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync_custom, 208 void *custom_data); 209 210 /* Stores all open dmabuf_heap handles. */ 211 std::unordered_map<std::string, android::base::unique_fd> dmabuf_heap_fds_; 212 /* Protects dma_buf_heap_fd_ from concurrent access */ 213 std::shared_mutex dmabuf_heap_fd_mutex_; 214 215 /* saved handle to /dev/ion. */ 216 android::base::unique_fd ion_fd_; 217 /** 218 * Stores the queried ion heap data. Struct ion_heap_date is defined 219 * as part of the ION UAPI as follows. 220 * struct ion_heap_data { 221 * char name[MAX_HEAP_NAME]; 222 * __u32 type; 223 * __u32 heap_id; 224 * __u32 reserved0; 225 * __u32 reserved1; 226 * __u32 reserved2; 227 * }; 228 */ 229 bool uses_legacy_ion_iface_ = false; 230 std::vector<struct ion_heap_data> ion_heap_info_; 231 inline static bool logged_interface_ = false; 232 /* stores a map of dmabuf heap names to equivalent ion heap configurations. */ 233 std::unordered_map<std::string, struct IonHeapConfig> heap_name_to_config_; 234 /* protects heap_name_to_config_ from concurrent access */ 235 std::shared_mutex heap_name_to_config_mutex_; 236 }; 237