1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "memory_manager.h"
17
18 #include <cerrno>
19 #include <unistd.h>
20 #include "hilog/log.h"
21 #include "image_utils.h"
22 #include "log_tags.h"
23 #include "media_errors.h"
24 #include "securec.h"
25
26 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(IOS_PLATFORM) &&!defined(A_PLATFORM)
27 #include <sys/mman.h>
28 #include "ashmem.h"
29 #include "surface_buffer.h"
30 #define SUPPORT_SHARED_MEMORY
31 #endif
32
33 namespace OHOS {
34 namespace Media {
35 using namespace OHOS::HiviewDFX;
36 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "MemoryManager" };
37 static const size_t SIZE_ZERO = 0;
38 static const int LINUX_SUCCESS = 0;
39 // Define pixel map malloc max size 600MB
40 constexpr int32_t PIXEL_MAP_MAX_RAM_SIZE = 600 * 1024 * 1024;
41
Create()42 uint32_t HeapMemory::Create()
43 {
44 HiLog::Debug(LABEL, "HeapMemory::Create IN");
45 if (data.data != nullptr) {
46 HiLog::Debug(LABEL, "HeapMemory::Create has created");
47 return SUCCESS;
48 }
49 if (data.size == 0 || data.size > PIXEL_MAP_MAX_RAM_SIZE) {
50 HiLog::Error(LABEL, "HeapMemory::Create Invalid value of bufferSize");
51 return ERR_IMAGE_DATA_ABNORMAL;
52 }
53 data.data = static_cast<uint8_t *>(malloc(data.size));
54 if (data.data == nullptr) {
55 HiLog::Error(LABEL, "HeapMemory::Create malloc buffer failed");
56 return ERR_IMAGE_MALLOC_ABNORMAL;
57 }
58 #if defined(IOS_PLATFORM) || defined(A_PLATFORM)
59 memset_s(data.data, data.size, 0, data.size);
60 #endif
61 return SUCCESS;
62 }
63
Release()64 uint32_t HeapMemory::Release()
65 {
66 #if !defined(IOS_PLATFORM) &&!defined(A_PLATFORM)
67 HiLog::Debug(LABEL, "HeapMemory::Release IN");
68 if (data.data == nullptr) {
69 HiLog::Error(LABEL, "HeapMemory::Release nullptr data");
70 return ERR_IMAGE_DATA_ABNORMAL;
71 }
72 free(data.data);
73 data.data = nullptr;
74 #endif
75 return SUCCESS;
76 }
77
ReleaseSharedMemory(int * fdPtr,uint8_t * ptr=nullptr,size_t size=SIZE_ZERO)78 static inline void ReleaseSharedMemory(int* fdPtr, uint8_t* ptr = nullptr, size_t size = SIZE_ZERO)
79 {
80 #if !defined(IOS_PLATFORM) &&!defined(A_PLATFORM)
81 if (ptr != nullptr && ptr != MAP_FAILED) {
82 ::munmap(ptr, size);
83 }
84 if (fdPtr != nullptr) {
85 ::close(*fdPtr);
86 }
87 #endif
88 }
89
Create()90 uint32_t SharedMemory::Create()
91 {
92 #ifdef SUPPORT_SHARED_MEMORY
93 HiLog::Debug(LABEL, "SharedMemory::Create IN tag %{public}s, data size %{public}zu",
94 (data.tag == nullptr)?"nullptr":data.tag, data.size);
95
96 if (data.tag == nullptr || data.size == SIZE_ZERO) {
97 HiLog::Error(LABEL, "SharedMemory::Create tag is nullptr or data size %{public}zu", data.size);
98 return ERR_IMAGE_DATA_ABNORMAL;
99 }
100 auto fdPtr = std::make_unique<int>();
101 *fdPtr = AshmemCreate(data.tag, data.size);
102 if (*fdPtr < 0) {
103 HiLog::Error(LABEL, "SharedMemory::Create AshmemCreate fd:[%{public}d].", *fdPtr);
104 return ERR_IMAGE_DATA_ABNORMAL;
105 }
106 if (AshmemSetProt(*fdPtr, PROT_READ | PROT_WRITE) < LINUX_SUCCESS) {
107 HiLog::Error(LABEL, "SharedMemory::Create AshmemSetProt errno %{public}d.", errno);
108 ReleaseSharedMemory(fdPtr.get());
109 return ERR_IMAGE_DATA_ABNORMAL;
110 }
111 data.data = ::mmap(nullptr, data.size, PROT_READ | PROT_WRITE, MAP_SHARED, *fdPtr, 0);
112 if (data.data == MAP_FAILED) {
113 HiLog::Error(LABEL, "SharedMemory::Create mmap failed, errno:%{public}d", errno);
114 ReleaseSharedMemory(fdPtr.get(), static_cast<uint8_t*>(data.data), data.size);
115 return ERR_IMAGE_DATA_ABNORMAL;
116 }
117 extend.size = sizeof(int);
118 extend.data = fdPtr.release();
119 return SUCCESS;
120 #else
121 HiLog::Error(LABEL, "SharedMemory::Create unsupported");
122 return ERR_IMAGE_DATA_UNSUPPORT;
123 #endif
124 }
125
Release()126 uint32_t SharedMemory::Release()
127 {
128 #ifdef SUPPORT_SHARED_MEMORY
129 HiLog::Debug(LABEL, "SharedMemory::Release IN");
130 ReleaseSharedMemory(static_cast<int*>(extend.data), static_cast<uint8_t*>(data.data), data.size);
131 data.data = nullptr;
132 data.size = SIZE_ZERO;
133 if (extend.data != nullptr) {
134 free(extend.data);
135 extend.data = nullptr;
136 extend.size = SIZE_ZERO;
137 }
138 return SUCCESS;
139 #else
140 HiLog::Error(LABEL, "SharedMemory::Release unsupported");
141 return ERR_IMAGE_DATA_UNSUPPORT;
142 #endif
143 }
144
Create()145 uint32_t DmaMemory::Create()
146 {
147 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
148 HiLog::Error(LABEL, "Unsupport dma mem alloc");
149 return ERR_IMAGE_DATA_UNSUPPORT;
150 #else
151 sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
152 BufferRequestConfig requestConfig = {
153 .width = data.desiredSize.width,
154 .height = data.desiredSize.height,
155 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
156 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
157 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
158 .timeout = 0,
159 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
160 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
161 };
162 GSError ret = sb->Alloc(requestConfig);
163 if (ret != GSERROR_OK) {
164 HiLog::Error(LABEL, "SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
165 return ERR_DMA_NOT_EXIST;
166 }
167 void* nativeBuffer = sb.GetRefPtr();
168 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
169 if (err != OHOS::GSERROR_OK) {
170 HiLog::Error(LABEL, "NativeBufferReference failed");
171 return ERR_DMA_DATA_ABNORMAL;
172 }
173 data.data = static_cast<uint8_t*>(sb->GetVirAddr());
174 extend.size = data.size;
175 extend.data = nativeBuffer;
176 return SUCCESS;
177 #endif
178 }
179
Release()180 uint32_t DmaMemory::Release()
181 {
182 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
183 HiLog::Error(LABEL, "Unsupport dma mem release");
184 return ERR_IMAGE_DATA_UNSUPPORT;
185 #else
186 data.data = nullptr;
187 data.size = SIZE_ZERO;
188 if (extend.data != nullptr) {
189 int32_t err = ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(extend.data));
190 if (err != OHOS::GSERROR_OK) {
191 HiLog::Error(LABEL, "NativeBufferReference failed");
192 return ERR_DMA_DATA_ABNORMAL;
193 }
194 extend.data = nullptr;
195 extend.size = SIZE_ZERO;
196 }
197 return SUCCESS;
198 #endif
199 }
200
CreateMemory(AllocatorType type,MemoryData & data)201 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data)
202 {
203 MemoryData extend;
204 return CreateMemory(type, data, extend);
205 }
206
CreateMemory(AllocatorType type,MemoryData & data,MemoryData & extend)207 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data, MemoryData &extend)
208 {
209 std::unique_ptr<AbsMemory> res = nullptr;
210 switch (type) {
211 case AllocatorType::SHARE_MEM_ALLOC:
212 res = std::make_unique<SharedMemory>();
213 break;
214 case AllocatorType::DMA_ALLOC:
215 res = std::make_unique<DmaMemory>();
216 break;
217 case AllocatorType::CUSTOM_ALLOC:
218 HiLog::Error(LABEL, "MemoryManager::CreateMemory unsupported CUSTOM_ALLOC now");
219 return nullptr;
220 case AllocatorType::DEFAULT:
221 case AllocatorType::HEAP_ALLOC:
222 default:
223 res = std::make_unique<HeapMemory>();
224 break;
225 }
226 if (res == nullptr) {
227 HiLog::Error(LABEL, "MemoryManager::CreateMemory unsupported %{public}d", type);
228 return nullptr;
229 }
230 res->data.data = data.data;
231 res->data.size = data.size;
232 res->data.tag = data.tag;
233 res->data.desiredSize = data.desiredSize;
234 res->extend.data = extend.data;
235 res->extend.size = extend.size;
236 res->extend.tag = extend.tag;
237 res->extend.desiredSize = extend.desiredSize;
238 if (res->data.data == nullptr) {
239 if (res->Create() != SUCCESS) {
240 return nullptr;
241 }
242 }
243 return res;
244 }
245
TransMemoryType(const AbsMemory & source,AllocatorType target,std::string tag)246 std::unique_ptr<AbsMemory> MemoryManager::TransMemoryType(const AbsMemory &source, AllocatorType target,
247 std::string tag)
248 {
249 MemoryData data = { nullptr, source.data.size, tag.c_str()};
250 auto res = CreateMemory(target, data);
251 if (res == nullptr) {
252 return res;
253 }
254 memcpy_s(res->data.data, res->data.size, source.data.data, source.data.size);
255 return res;
256 }
257 } // namespace Media
258 } // namespace OHOS