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 "buffer/avsharedmemorybase.h" 17#include <sys/mman.h> 18#include <unistd.h> 19#include "ashmem.h" 20#include "common/status.h" 21#include "common/log.h" 22#include "scope_guard.h" 23#include "securec.h" 24 25namespace { 26constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "AVSharedMemoryBase" }; 27} 28 29namespace OHOS { 30namespace Media { 31struct AVSharedMemoryBaseImpl : public AVSharedMemoryBase { 32public: 33 AVSharedMemoryBaseImpl(int32_t fd, int32_t size, uint32_t flags, const std::string &name) 34 : AVSharedMemoryBase(fd, size, flags, name) {} 35}; 36 37std::shared_ptr<AVSharedMemory> AVSharedMemoryBase::CreateFromLocal( 38 int32_t size, uint32_t flags, const std::string &name) 39{ 40 std::shared_ptr<AVSharedMemoryBase> memory = std::make_shared<AVSharedMemoryBase>(size, flags, name); 41 int32_t ret = memory->Init(); 42 if (ret != static_cast<int32_t>(Status::OK)) { 43 MEDIA_LOG_E("Create avsharedmemory failed, ret = %{public}d", ret); 44 return nullptr; 45 } 46 47 return memory; 48} 49 50std::shared_ptr<AVSharedMemory> AVSharedMemoryBase::CreateFromRemote( 51 int32_t fd, int32_t size, uint32_t flags, const std::string &name) 52{ 53 std::shared_ptr<AVSharedMemoryBase> memory = std::make_shared<AVSharedMemoryBaseImpl>(fd, size, flags, name); 54 int32_t ret = memory->Init(); 55 if (ret != static_cast<int32_t>(Status::OK)) { 56 MEDIA_LOG_E("Create avsharedmemory failed, ret = %{public}d", ret); 57 return nullptr; 58 } 59 60 return memory; 61} 62 63AVSharedMemoryBase::AVSharedMemoryBase(int32_t size, uint32_t flags, const std::string &name) 64 : base_(nullptr), capacity_(size), flags_(flags), name_(name), fd_(-1), size_(0) 65{ 66 MEDIA_LOG_DD(LOGD_FREQUENCY, "enter ctor, instance: 0x%{public}06" PRIXPTR ", name = %{public}s", 67 FAKE_POINTER(this), name_.c_str()); 68} 69 70AVSharedMemoryBase::AVSharedMemoryBase(int32_t fd, int32_t size, uint32_t flags, const std::string &name) 71 : base_(nullptr), capacity_(size), flags_(flags), name_(name), fd_(dup(fd)), size_(0) 72{ 73 MEDIA_LOG_DD(LOGD_FREQUENCY, "enter ctor, instance: 0x%{public}06" PRIXPTR ", name = %{public}s", 74 FAKE_POINTER(this), name_.c_str()); 75} 76 77AVSharedMemoryBase::~AVSharedMemoryBase() 78{ 79 MEDIA_LOG_DD(LOGD_FREQUENCY, "enter dtor, instance: 0x%{public}06" PRIXPTR ", name = %{public}s", 80 FAKE_POINTER(this), name_.c_str()); 81 Close(); 82} 83 84int32_t AVSharedMemoryBase::Init(bool isMapVirAddr) 85{ 86 ON_SCOPE_EXIT(0) { 87 MEDIA_LOG_E("create avsharedmemory failed, name = %{public}s, size = %{public}d, " 88 "flags = 0x%{public}x, fd = %{public}d", 89 name_.c_str(), capacity_, flags_, fd_); 90 Close(); 91 }; 92 93 FALSE_RETURN_V_MSG_E(capacity_ > 0, static_cast<int32_t>(Status::ERROR_INVALID_PARAMETER), 94 "size is invalid, size = %{public}d", capacity_); 95 96 bool isRemote = false; 97 if (fd_ > 0) { 98 int size = AshmemGetSize(fd_); 99 FALSE_RETURN_V_MSG_E(size == capacity_, static_cast<int32_t>(Status::ERROR_INVALID_PARAMETER), 100 "size not equal capacity_, size = %{public}d, capacity_ = %{public}d", size, capacity_); 101 isRemote = true; 102 } else { 103 fd_ = AshmemCreate(name_.c_str(), static_cast<size_t>(capacity_)); 104 FALSE_RETURN_V_MSG_E(fd_ > 0, static_cast<int32_t>(Status::ERROR_INVALID_PARAMETER), 105 "fd is invalid, fd = %{public}d", fd_); 106 } 107 if (isMapVirAddr) { 108 int32_t ret = MapMemory(isRemote); 109 FALSE_RETURN_V_MSG_E(ret == static_cast<int32_t>(Status::OK), 110 static_cast<int32_t>(Status::ERROR_INVALID_PARAMETER), 111 "MapMemory failed, ret = %{plublic}d", ret); 112 } 113 CANCEL_SCOPE_EXIT_GUARD(0); 114 return static_cast<int32_t>(Status::OK); 115} 116 117int32_t AVSharedMemoryBase::MapMemory(bool isRemote) 118{ 119#ifdef MEDIA_OHOS 120 unsigned int prot = PROT_READ | PROT_WRITE; 121 if (isRemote && (flags_ & FLAGS_READ_ONLY)) { 122 prot &= ~PROT_WRITE; 123 } 124 125 int result = AshmemSetProt(fd_, static_cast<int>(prot)); 126 FALSE_RETURN_V_MSG_E(result >= 0, static_cast<int32_t>(Status::ERROR_INVALID_OPERATION), 127 "AshmemSetProt failed, result = %{public}d", result); 128 129 void *addr = ::mmap(nullptr, static_cast<size_t>(capacity_), static_cast<int>(prot), MAP_SHARED, fd_, 0); 130 FALSE_RETURN_V_MSG_E(addr != MAP_FAILED, static_cast<int32_t>(Status::ERROR_INVALID_OPERATION), 131 "mmap failed, please check params"); 132 133 base_ = reinterpret_cast<uint8_t*>(addr); 134#endif 135 return static_cast<int32_t>(Status::OK); 136} 137 138void AVSharedMemoryBase::Close() noexcept 139{ 140#ifdef MEDIA_OHOS 141 if (base_ != nullptr) { 142 (void)::munmap(base_, static_cast<size_t>(capacity_)); 143 base_ = nullptr; 144 capacity_ = 0; 145 flags_ = 0; 146 size_ = 0; 147 } 148#endif 149 if (fd_ > 0) { 150 (void)::close(fd_); 151 fd_ = -1; 152 } 153} 154 155int32_t AVSharedMemoryBase::Write(const uint8_t *in, int32_t writeSize, int32_t position) 156{ 157 FALSE_RETURN_V_MSG_E(in != nullptr, 0, "Input buffer is nullptr"); 158 FALSE_RETURN_V_MSG_E(writeSize > 0, 0, "Input writeSize:%{public}d is invalid", writeSize); 159 int32_t start = 0; 160 if (position == INVALID_POSITION) { 161 start = size_; 162 } else { 163 start = std::min(position, capacity_); 164 } 165 int32_t unusedSize = capacity_ - start; 166 int32_t length = std::min(writeSize, unusedSize); 167 MEDIA_LOG_DD("write data,length:%{public}d, start:%{public}d, name:%{public}s", length, start, name_.c_str()); 168 FALSE_RETURN_V_MSG_E((length + start) <= capacity_, 0, "Write out of bounds, length:%{public}d, " 169 "start:%{public}d, capacity_:%{public}d", length, start, capacity_); 170 uint8_t *dstPtr = base_ + start; 171 FALSE_RETURN_V_MSG_E(dstPtr != nullptr, 0, "Inner dstPtr is nullptr"); 172 173 auto error = memcpy_s(dstPtr, length, in, length); 174 FALSE_RETURN_V_MSG_E(error == EOK, 0, "Inner memcpy_s failed,name:%{public}s, %{public}s", 175 name_.c_str(), strerror(error)); 176 size_ = start + length; 177 return length; 178} 179 180int32_t AVSharedMemoryBase::Read(uint8_t *out, int32_t readSize, int32_t position) 181{ 182 FALSE_RETURN_V_MSG_E(out != nullptr, 0, "Input buffer is nullptr"); 183 FALSE_RETURN_V_MSG_E(readSize > 0, 0, "Input readSize:%{public}d is invalid", readSize); 184 int32_t start = 0; 185 int32_t maxLength = size_; 186 if (position != INVALID_POSITION) { 187 start = std::min(position, size_); 188 maxLength = size_ - start; 189 } 190 int32_t length = std::min(readSize, maxLength); 191 FALSE_RETURN_V_MSG_E((length + start) <= capacity_, 0, "Read out of bounds, length:%{public}d, " 192 "start:%{public}d, capacity_:%{public}d", length, start, capacity_); 193 uint8_t *srcPtr = base_ + start; 194 FALSE_RETURN_V_MSG_E(srcPtr != nullptr, 0, "Inner srcPtr is nullptr"); 195 auto error = memcpy_s(out, length, srcPtr, length); 196 FALSE_RETURN_V_MSG_E(error == EOK, 0, "Inner memcpy_s failed,name:%{public}s, %{public}s", 197 name_.c_str(), strerror(error)); 198 return length; 199} 200 201void AVSharedMemoryBase::ClearUsedSize() 202{ 203 size_ = 0; 204} 205 206int32_t AVSharedMemoryBase::GetUsedSize() const 207{ 208 return size_; 209} 210} // namespace Media 211} // namespace OHOS 212