1 /*
2 * Copyright (C) 2023 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 "av_hardware_memory.h"
17 #include <unistd.h>
18 #include <unordered_map>
19 #include "ashmem.h"
20 #include "av_hardware_allocator.h"
21 #include "common/log.h"
22 #include "common/status.h"
23 #include "message_parcel.h"
24 #include "scope_guard.h"
25
26 #ifdef MEDIA_OHOS
27 #include "sys/mman.h"
28 #endif
29 #define HARDWARE_ALLOCATOR std::static_pointer_cast<AVHardwareAllocator>(allocator_)
30 namespace OHOS {
31 namespace Media {
CreateHardwareAllocator(int32_t fd,int32_t capacity,MemoryFlag memFlag,bool isSecure)32 std::shared_ptr<AVAllocator> AVAllocatorFactory::CreateHardwareAllocator(int32_t fd, int32_t capacity,
33 MemoryFlag memFlag, bool isSecure)
34 {
35 FALSE_RETURN_V_MSG_E(fd > 0, nullptr, "File descriptor is invalid");
36 auto allocator = std::shared_ptr<AVHardwareAllocator>(new AVHardwareAllocator());
37 allocator->fd_ = dup(fd);
38 allocator->capacity_ = capacity;
39 allocator->memFlag_ = memFlag;
40 allocator->isSecure_ = isSecure;
41 return allocator;
42 }
43
AVHardwareAllocator()44 AVHardwareAllocator::AVHardwareAllocator()
45 : fd_(-1),
46 capacity_(-1),
47 allocBase_(nullptr),
48 memFlag_(MemoryFlag::MEMORY_READ_ONLY),
49 isAllocated_(false),
50 isSecure_(false){};
51
~AVHardwareAllocator()52 AVHardwareAllocator::~AVHardwareAllocator()
53 {
54 if (fd_ > 0 && (!isAllocated_ || isSecure_)) {
55 (void)::close(fd_);
56 fd_ = -1;
57 }
58 }
59
Alloc(int32_t capacity)60 void *AVHardwareAllocator::Alloc(int32_t capacity)
61 {
62 (void)capacity;
63 if (isSecure_) {
64 return nullptr;
65 }
66 Status ret = MapMemoryAddr();
67 FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Map dma buffer failed");
68 isAllocated_ = true;
69 return reinterpret_cast<void *>(allocBase_);
70 }
71
Free(void * ptr)72 bool AVHardwareAllocator::Free(void *ptr)
73 {
74 #ifdef MEDIA_OHOS
75 if (isSecure_) {
76 return true;
77 }
78 FALSE_RETURN_V_MSG_E(static_cast<uint8_t *>(ptr) == allocBase_, false, "Mapped buffer not match");
79 FALSE_RETURN_V_MSG_E(isAllocated_, false, "Never allocated memory by Alloc function of this allocator");
80 if (allocBase_ != nullptr) {
81 (void)::munmap(allocBase_, static_cast<size_t>(capacity_));
82 }
83 if (fd_ > 0) {
84 (void)::close(fd_);
85 fd_ = -1;
86 }
87 allocBase_ = nullptr;
88 capacity_ = -1;
89 #endif
90 return true;
91 }
92
GetMemoryType()93 MemoryType AVHardwareAllocator::GetMemoryType()
94 {
95 return MemoryType::HARDWARE_MEMORY;
96 }
97
GetMemFlag()98 MemoryFlag AVHardwareAllocator::GetMemFlag()
99 {
100 return memFlag_;
101 }
102
GetFileDescriptor()103 int32_t AVHardwareAllocator::GetFileDescriptor()
104 {
105 return fd_;
106 }
107
GetIsSecure()108 bool AVHardwareAllocator::GetIsSecure()
109 {
110 return isSecure_;
111 }
112
MapMemoryAddr()113 Status AVHardwareAllocator::MapMemoryAddr()
114 {
115 #ifdef MEDIA_OHOS
116 ON_SCOPE_EXIT(0)
117 {
118 MEDIA_LOG_E("MapMemoryAddr failed. "
119 "capacity:%{public}d, flags:0x%{public}x, fd:%{public}d",
120 capacity_, memFlag_, fd_);
121 if (allocBase_ != nullptr) {
122 (void)::munmap(allocBase_, static_cast<size_t>(capacity_));
123 allocBase_ = nullptr;
124 }
125 return Status::ERROR_NO_MEMORY;
126 };
127 FALSE_RETURN_V_MSG_E(capacity_ > 0, Status::ERROR_INVALID_DATA, "capacity is invalid, capacity:%{public}d",
128 capacity_);
129 unsigned int prot = PROT_READ | PROT_WRITE;
130 FALSE_RETURN_V_MSG_E(fd_ > 0, Status::ERROR_INVALID_OPERATION, "fd is invalid, fd:%{public}d", fd_);
131 if (memFlag_ == MemoryFlag::MEMORY_READ_ONLY) {
132 prot &= ~PROT_WRITE;
133 } else if (memFlag_ == MemoryFlag::MEMORY_WRITE_ONLY) {
134 prot &= ~PROT_READ;
135 }
136 void *addr = ::mmap(nullptr, static_cast<size_t>(capacity_), static_cast<int>(prot), MAP_SHARED, fd_, 0);
137 FALSE_RETURN_V_MSG_E(addr != MAP_FAILED, Status::ERROR_INVALID_OPERATION, "mmap failed, please check params");
138 allocBase_ = reinterpret_cast<uint8_t *>(addr);
139 CANCEL_SCOPE_EXIT_GUARD(0);
140 #endif
141 return Status::OK;
142 }
143
AVHardwareMemory()144 AVHardwareMemory::AVHardwareMemory() : isStartSync_(false), memFlag_(MemoryFlag::MEMORY_READ_ONLY) {}
145
~AVHardwareMemory()146 AVHardwareMemory::~AVHardwareMemory()
147 {
148 #ifdef MEDIA_OHOS
149 if (allocator_ == nullptr) {
150 if (base_ != nullptr) {
151 (void)::munmap(base_, static_cast<size_t>(capacity_));
152 }
153 if (fd_ > 0) {
154 (void)::close(fd_);
155 fd_ = -1;
156 }
157 return;
158 }
159 #endif
160 allocator_->Free(base_);
161 }
162
Init()163 Status AVHardwareMemory::Init()
164 {
165 fd_ = HARDWARE_ALLOCATOR->GetFileDescriptor();
166 memFlag_ = HARDWARE_ALLOCATOR->GetMemFlag();
167 base_ = static_cast<uint8_t *>(allocator_->Alloc(0));
168
169 FALSE_RETURN_V_MSG_E(base_ != nullptr || HARDWARE_ALLOCATOR->GetIsSecure(), Status::ERROR_NO_MEMORY,
170 "dma memory alloc failed");
171 return Status::OK;
172 }
173
Init(MessageParcel & parcel)174 Status AVHardwareMemory::Init(MessageParcel &parcel)
175 {
176 #ifdef MEDIA_OHOS
177 int32_t fd = parcel.ReadFileDescriptor();
178 FALSE_RETURN_V_MSG_E(fd > 0, Status::ERROR_INVALID_DATA, "File descriptor is invalid");
179
180 memFlag_ = static_cast<MemoryFlag>(parcel.ReadUint32());
181
182 allocator_ = AVAllocatorFactory::CreateHardwareAllocator(fd, capacity_, memFlag_);
183 if (allocator_ == nullptr) {
184 MEDIA_LOG_E("allocator is nullptr");
185 (void)::close(fd);
186 return Status::ERROR_NO_MEMORY;
187 }
188 fd_ = HARDWARE_ALLOCATOR->GetFileDescriptor();
189 (void)::close(fd);
190
191 base_ = static_cast<uint8_t *>(allocator_->Alloc(0));
192 allocator_ = nullptr;
193
194 FALSE_RETURN_V_MSG_E(base_ != nullptr, Status::ERROR_NO_MEMORY, "dma memory alloc failed");
195 #endif
196 return Status::OK;
197 }
198
WriteToMessageParcel(MessageParcel & parcel)199 bool AVHardwareMemory::WriteToMessageParcel(MessageParcel &parcel)
200 {
201 FALSE_RETURN_V_MSG_E(!HARDWARE_ALLOCATOR->GetIsSecure(), false, "AVHardwareAllocator is secure");
202 bool ret = true;
203 #ifdef MEDIA_OHOS
204 MessageParcel bufferParcel;
205 ret = bufferParcel.WriteFileDescriptor(fd_) && bufferParcel.WriteUint32(static_cast<uint32_t>(memFlag_));
206 if (ret) {
207 parcel.Append(bufferParcel);
208 }
209 #endif
210 return ret;
211 }
212
ReadFromMessageParcel(MessageParcel & parcel)213 bool AVHardwareMemory::ReadFromMessageParcel(MessageParcel &parcel)
214 {
215 #ifdef MEDIA_OHOS
216 int32_t fd = parcel.ReadFileDescriptor();
217 (void)parcel.ReadUint32();
218 if (fd > 0) {
219 (void)::close(fd);
220 }
221 #endif
222 return true;
223 }
224
GetMemoryType()225 MemoryType AVHardwareMemory::GetMemoryType()
226 {
227 return MemoryType::HARDWARE_MEMORY;
228 }
229
GetMemoryFlag()230 MemoryFlag AVHardwareMemory::GetMemoryFlag()
231 {
232 return memFlag_;
233 }
234
GetFileDescriptor()235 int32_t AVHardwareMemory::GetFileDescriptor()
236 {
237 return fd_;
238 }
239 } // namespace Media
240 } // namespace OHOS
241