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 <BufferAllocator/dmabufheap-defs.h> 20 21 #include <android-base/unique_fd.h> 22 #include <linux/ion_4.12.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <sys/types.h> 27 28 #include <cstdint> 29 #include <string> 30 #include <unordered_map> 31 #include <vector> 32 33 34 class BufferAllocator { 35 public: 36 BufferAllocator(); ~BufferAllocator()37 ~BufferAllocator() {} 38 39 /* Not copyable or movable */ 40 BufferAllocator(const BufferAllocator&) = delete; 41 BufferAllocator& operator=(const BufferAllocator&) = delete; 42 43 /** 44 * Maps a dmabuf heap to an equivalent ion heap configuration. This method is required since 45 * dmabuf heaps do not support heap flags. This means that a single ion heap may encompass the 46 * functionality of multiple dmabuf heaps by using heap flags. This method will check the 47 * interface being used and only create the required mappings. For example, 48 * if the interface being used is dmabuf heaps, the method will not do 49 * anything. If the interface being used is non-legacy ion, the mapping from 50 * dmabuf heap name to non-legacy ion heap name will be created and the 51 * legacy parameters will be ignored. 52 * The method can be deprecated once all devices have 53 * migrated to dmabuf heaps from ion. Returns an error code when the 54 * interface used is non-legacy ion and the @ion_heap_name parameter is 55 * invalid or if the interface used is legacy ion and @legacy_ion_heap_mask 56 * is invalid(0); 57 * @heap_name: dmabuf heap name. 58 * @ion_heap_name: name of the equivalent ion heap. 59 * @ion_heap_flags: flags to be passed to the ion heap @ion_heap_name for it to function 60 * equivalently to the dmabuf heap @heap_name. 61 * @legacy_ion_heap_mask: heap mask for the equivalent legacy ion heap. 62 * @legacy_ion_heap_flags: flags to be passed to the legacy ion heap for it 63 * to function equivalently to dmabuf heap @heap_name.. 64 */ 65 int MapNameToIonHeap(const std::string& heap_name, const std::string& ion_heap_name, 66 unsigned int ion_heap_flags = 0, unsigned int legacy_ion_heap_mask = 0, 67 unsigned int legacy_ion_heap_flags = 0); 68 69 /* * 70 * Returns a dmabuf fd if the allocation in one of the specified heaps is successful and 71 * an error code otherwise. If dmabuf heaps are supported, tries to allocate in the 72 * specified dmabuf heap. If dmabuf heaps are not supported and if ion_fd is a valid fd, 73 * go through saved heap data to find a heap ID/mask to match the specified heap names and 74 * allocate memory as per the specified parameters. For vendor defined heaps with a legacy 75 * ION interface(no heap query support), MapNameToIonMask() must be called prior to invocation 76 * of Alloc() to map a heap name to an equivalent heap mask and heap flag configuration. 77 * @heap_name: name of the heap to allocate in. 78 * @len: size of the allocation. 79 * @heap_flags: flags passed to heap. 80 */ 81 int Alloc(const std::string& heap_name, size_t len, unsigned int heap_flags = 0); 82 83 /** 84 * Optional custom callback for legacy ion implementation that can be specified as a 85 * parameter to CpuSyncStart() and CpuSyncEnd(). It takes an fd to /dev/ion 86 * as its argument. The callback MUST NOT assume ownership of the fd. 87 * The fd will be closed once the callback returns. 88 * If specified, the callback will be used for syncing a shared dmabuf fd with 89 * memory(instead of ion_sync_fd()). It will be invoked with a dup of 90 * ion_fd_ as its argument. Return 0 on success and error code otherwise 91 * which will become the return value for CpuSyncStart() and CpuSyncEnd(). 92 */ 93 typedef std::function<int(int)> CustomCpuSyncLegacyIon; 94 95 /** 96 * Must be invoked before CPU access of the allocated memory. 97 * For a legacy ion interface, syncs a shared dmabuf fd with memory either using 98 * ION_IOC_SYNC ioctl or using callback @legacy_ion_cpu_sync if specified. For 99 * non-legacy ION and dmabuf heap interfaces, DMA_BUF_IOCTL_SYNC is used. 100 * @fd: dmabuf fd 101 * @sync_type: specifies if the sync is for read, write or read/write. 102 * @legacy_ion_cpu_sync: optional callback for legacy ion interfaces. If 103 * specified, will be invoked instead of ion_sync_fd() 104 * to sync dmabuf_fd with memory. The paremeter will be ignored if the interface being 105 * used is not legacy ion. 106 * 107 * Returns 0 on success and an error code otherwise. 108 */ 109 int CpuSyncStart(unsigned int dmabuf_fd, SyncType sync_type = kSyncRead, 110 const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync = nullptr); 111 112 /** 113 * Must be invoked once CPU is done accessing the allocated memory. 114 * For a legacy ion interface, syncs a shared dmabuf fd with memory using 115 * either ION_IOC_SYNC ioctl or using callback @legacy_ion_cpu_sync if 116 * specified. For non-legacy ION and dmabuf heap interfaces, 117 * DMA_BUF_IOCTL_SYNC is used. The type of sync(read, write or rw) done will 118 * the same with which CpuSyncStart() was invoked. 119 * @fd: dmabuf fd 120 * @legacy_ion_cpu_sync: optional callback for legacy ion interfaces. If 121 * specified, will be invoked instead of ion_sync_fd with a dup of ion_fd_ as its 122 * argument. The parameter will be ignored if the interface being used is 123 * not legacy ion. 124 * 125 * Returns 0 on success and an error code otherwise. 126 */ 127 int CpuSyncEnd(unsigned int dmabuf_fd, 128 const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync = nullptr); 129 130 private: 131 int OpenDmabufHeap(const std::string& name); 132 void QueryIonHeaps(); 133 int GetDmabufHeapFd(const std::string& name); DmabufHeapsSupported()134 bool DmabufHeapsSupported() { return !dmabuf_heap_fds_.empty(); } 135 int GetIonHeapIdByName(const std::string& heap_name, unsigned int* heap_id); 136 int MapNameToIonMask(const std::string& heap_name, unsigned int ion_heap_mask, 137 unsigned int ion_heap_flags = 0); 138 int MapNameToIonName(const std::string& heap_name, const std::string& ion_heap_name, 139 unsigned int ion_heap_flags = 0); 140 void LogInterface(const std::string& interface); 141 int IonAlloc(const std::string& heap_name, size_t len, unsigned int heap_flags = 0); 142 int DmabufAlloc(const std::string& heap_name, size_t len); 143 144 struct IonHeapConfig { 145 unsigned int mask; 146 unsigned int flags; 147 }; 148 int GetIonConfig(const std::string& heap_name, IonHeapConfig& heap_config); 149 int LegacyIonCpuSync(unsigned int fd, const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync_custom); 150 int DmabufFdSync(unsigned int dmabuf_fd, bool start, SyncType sync_type); 151 int DoSync(unsigned int dmabuf_fd, bool start, SyncType sync_type, 152 const CustomCpuSyncLegacyIon& legacy_ion_cpu_sync_custom); 153 154 /* Stores all open dmabuf_heap handles. */ 155 std::unordered_map<std::string, android::base::unique_fd> dmabuf_heap_fds_; 156 157 /* saved handle to /dev/ion. */ 158 android::base::unique_fd ion_fd_; 159 /** 160 * Stores the queried ion heap data. Struct ion_heap_date is defined 161 * as part of the ION UAPI as follows. 162 * struct ion_heap_data { 163 * char name[MAX_HEAP_NAME]; 164 * __u32 type; 165 * __u32 heap_id; 166 * __u32 reserved0; 167 * __u32 reserved1; 168 * __u32 reserved2; 169 * }; 170 */ 171 bool uses_legacy_ion_iface_ = false; 172 std::vector<struct ion_heap_data> ion_heap_info_; 173 inline static bool logged_interface_ = false; 174 /* stores a map of dmabuf heap names to equivalent ion heap configurations. */ 175 std::unordered_map<std::string, struct IonHeapConfig> heap_name_to_config_; 176 /** 177 * stores a map of dmabuf fds to the type of their last known CpuSyncStart() 178 * call. The entry will be cleared when CpuSyncEnd() is invoked. 179 */ 180 std::unordered_map<int, SyncType> fd_last_sync_type_; 181 }; 182