• 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 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