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