• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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