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