176fd607bSopenharmony_ci/* 276fd607bSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 376fd607bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 476fd607bSopenharmony_ci * you may not use this file except in compliance with the License. 576fd607bSopenharmony_ci * You may obtain a copy of the License at 676fd607bSopenharmony_ci * 776fd607bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 876fd607bSopenharmony_ci * 976fd607bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1076fd607bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1176fd607bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1276fd607bSopenharmony_ci * See the License for the specific language governing permissions and 1376fd607bSopenharmony_ci * limitations under the License. 1476fd607bSopenharmony_ci */ 1576fd607bSopenharmony_ci 1676fd607bSopenharmony_ci#include "thumbnail_manager.h" 1776fd607bSopenharmony_ci 1876fd607bSopenharmony_ci#include <memory> 1976fd607bSopenharmony_ci#include <mutex> 2076fd607bSopenharmony_ci#include <sys/mman.h> 2176fd607bSopenharmony_ci#include <sys/stat.h> 2276fd607bSopenharmony_ci#include <uuid/uuid.h> 2376fd607bSopenharmony_ci 2476fd607bSopenharmony_ci#include "ashmem.h" 2576fd607bSopenharmony_ci#include "image_source.h" 2676fd607bSopenharmony_ci#include "image_type.h" 2776fd607bSopenharmony_ci#include "js_native_api.h" 2876fd607bSopenharmony_ci#include "media_file_uri.h" 2976fd607bSopenharmony_ci#include "medialibrary_errno.h" 3076fd607bSopenharmony_ci#include "medialibrary_napi_log.h" 3176fd607bSopenharmony_ci#include "medialibrary_napi_utils.h" 3276fd607bSopenharmony_ci#include "medialibrary_tracer.h" 3376fd607bSopenharmony_ci#include "pixel_map.h" 3476fd607bSopenharmony_ci#include "pixel_map_napi.h" 3576fd607bSopenharmony_ci#include "post_proc.h" 3676fd607bSopenharmony_ci#include "securec.h" 3776fd607bSopenharmony_ci#include "string_ex.h" 3876fd607bSopenharmony_ci#include "thumbnail_const.h" 3976fd607bSopenharmony_ci#include "unique_fd.h" 4076fd607bSopenharmony_ci#include "userfile_manager_types.h" 4176fd607bSopenharmony_ci#include "uv.h" 4276fd607bSopenharmony_ci#include "userfile_client.h" 4376fd607bSopenharmony_ci 4476fd607bSopenharmony_ci#ifdef IMAGE_PURGEABLE_PIXELMAP 4576fd607bSopenharmony_ci#include "purgeable_pixelmap_builder.h" 4676fd607bSopenharmony_ci#endif 4776fd607bSopenharmony_ci 4876fd607bSopenharmony_ciusing namespace std; 4976fd607bSopenharmony_ciconst int UUID_STR_LENGTH = 37; 5076fd607bSopenharmony_ci 5176fd607bSopenharmony_cinamespace OHOS { 5276fd607bSopenharmony_cinamespace Media { 5376fd607bSopenharmony_cishared_ptr<ThumbnailManager> ThumbnailManager::instance_ = nullptr; 5476fd607bSopenharmony_cimutex ThumbnailManager::mutex_; 5576fd607bSopenharmony_cibool ThumbnailManager::init_ = false; 5676fd607bSopenharmony_cistatic constexpr int32_t DEFAULT_FD = -1; 5776fd607bSopenharmony_ci 5876fd607bSopenharmony_ciThumbnailRequest::ThumbnailRequest(const RequestPhotoParams ¶ms, napi_env env, 5976fd607bSopenharmony_ci napi_ref callback) : callback_(env, callback), requestPhotoType(params.type), uri_(params.uri), 6076fd607bSopenharmony_ci path_(params.path), requestSize_(params.size) 6176fd607bSopenharmony_ci{ 6276fd607bSopenharmony_ci} 6376fd607bSopenharmony_ci 6476fd607bSopenharmony_ciThumbnailRequest::~ThumbnailRequest() 6576fd607bSopenharmony_ci{ 6676fd607bSopenharmony_ci} 6776fd607bSopenharmony_ci 6876fd607bSopenharmony_civoid ThumbnailRequest::ReleaseCallbackRef() 6976fd607bSopenharmony_ci{ 7076fd607bSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 7176fd607bSopenharmony_ci if (callback_.callBackRef_) { 7276fd607bSopenharmony_ci napi_delete_reference(callback_.env_, callback_.callBackRef_); 7376fd607bSopenharmony_ci callback_.callBackRef_ = nullptr; 7476fd607bSopenharmony_ci } 7576fd607bSopenharmony_ci} 7676fd607bSopenharmony_ci 7776fd607bSopenharmony_cibool ThumbnailRequest::UpdateStatus(ThumbnailStatus status) 7876fd607bSopenharmony_ci{ 7976fd607bSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 8076fd607bSopenharmony_ci if (status <= status_) { 8176fd607bSopenharmony_ci return false; 8276fd607bSopenharmony_ci } 8376fd607bSopenharmony_ci status_ = status; 8476fd607bSopenharmony_ci return true; 8576fd607bSopenharmony_ci} 8676fd607bSopenharmony_ci 8776fd607bSopenharmony_ciThumbnailStatus ThumbnailRequest::GetStatus() 8876fd607bSopenharmony_ci{ 8976fd607bSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 9076fd607bSopenharmony_ci return status_; 9176fd607bSopenharmony_ci} 9276fd607bSopenharmony_ci 9376fd607bSopenharmony_cibool ThumbnailRequest::NeedContinue() 9476fd607bSopenharmony_ci{ 9576fd607bSopenharmony_ci return GetStatus() < ThumbnailStatus::THUMB_REMOVE; 9676fd607bSopenharmony_ci} 9776fd607bSopenharmony_ci 9876fd607bSopenharmony_cistatic bool IsPhotoSizeThumb(const Size &size) 9976fd607bSopenharmony_ci{ 10076fd607bSopenharmony_ci return ((size.width >= DEFAULT_THUMB_SIZE || size.height >= DEFAULT_THUMB_SIZE) || 10176fd607bSopenharmony_ci (size.width == DEFAULT_MTH_SIZE || size.height == DEFAULT_MTH_SIZE)); 10276fd607bSopenharmony_ci} 10376fd607bSopenharmony_ci 10476fd607bSopenharmony_cistatic bool NeedFastThumb(const Size &size, RequestPhotoType type) 10576fd607bSopenharmony_ci{ 10676fd607bSopenharmony_ci return IsPhotoSizeThumb(size) && (type != RequestPhotoType::REQUEST_QUALITY_THUMBNAIL); 10776fd607bSopenharmony_ci} 10876fd607bSopenharmony_ci 10976fd607bSopenharmony_cistatic bool NeedQualityThumb(const Size &size, RequestPhotoType type) 11076fd607bSopenharmony_ci{ 11176fd607bSopenharmony_ci return IsPhotoSizeThumb(size) && (type != RequestPhotoType::REQUEST_FAST_THUMBNAIL); 11276fd607bSopenharmony_ci} 11376fd607bSopenharmony_ci 11476fd607bSopenharmony_ciMMapFdPtr::MMapFdPtr(int32_t fd, bool isNeedRelease) 11576fd607bSopenharmony_ci{ 11676fd607bSopenharmony_ci if (fd < 0) { 11776fd607bSopenharmony_ci NAPI_ERR_LOG("Fd is invalid: %{public}d", fd); 11876fd607bSopenharmony_ci return; 11976fd607bSopenharmony_ci } 12076fd607bSopenharmony_ci 12176fd607bSopenharmony_ci struct stat st; 12276fd607bSopenharmony_ci if (fstat(fd, &st) == -1) { 12376fd607bSopenharmony_ci NAPI_ERR_LOG("fstat error, errno:%{public}d", errno); 12476fd607bSopenharmony_ci return; 12576fd607bSopenharmony_ci } 12676fd607bSopenharmony_ci size_ = st.st_size; 12776fd607bSopenharmony_ci 12876fd607bSopenharmony_ci // mmap ptr from fd 12976fd607bSopenharmony_ci fdPtr_ = mmap(nullptr, size_, PROT_READ, MAP_SHARED, fd, 0); 13076fd607bSopenharmony_ci if (fdPtr_ == MAP_FAILED || fdPtr_ == nullptr) { 13176fd607bSopenharmony_ci NAPI_ERR_LOG("mmap uniqueFd failed, errno = %{public}d", errno); 13276fd607bSopenharmony_ci return; 13376fd607bSopenharmony_ci } 13476fd607bSopenharmony_ci 13576fd607bSopenharmony_ci isValid_ = true; 13676fd607bSopenharmony_ci isNeedRelease_ = isNeedRelease; 13776fd607bSopenharmony_ci} 13876fd607bSopenharmony_ci 13976fd607bSopenharmony_ciMMapFdPtr::~MMapFdPtr() 14076fd607bSopenharmony_ci{ 14176fd607bSopenharmony_ci // munmap ptr from fd 14276fd607bSopenharmony_ci if (isNeedRelease_) { 14376fd607bSopenharmony_ci munmap(fdPtr_, size_); 14476fd607bSopenharmony_ci } 14576fd607bSopenharmony_ci} 14676fd607bSopenharmony_ci 14776fd607bSopenharmony_civoid* MMapFdPtr::GetFdPtr() 14876fd607bSopenharmony_ci{ 14976fd607bSopenharmony_ci return fdPtr_; 15076fd607bSopenharmony_ci} 15176fd607bSopenharmony_ci 15276fd607bSopenharmony_cioff_t MMapFdPtr::GetFdSize() 15376fd607bSopenharmony_ci{ 15476fd607bSopenharmony_ci return size_; 15576fd607bSopenharmony_ci} 15676fd607bSopenharmony_ci 15776fd607bSopenharmony_cibool MMapFdPtr::IsValid() 15876fd607bSopenharmony_ci{ 15976fd607bSopenharmony_ci return isValid_; 16076fd607bSopenharmony_ci} 16176fd607bSopenharmony_ci 16276fd607bSopenharmony_cistatic string GenerateRequestId() 16376fd607bSopenharmony_ci{ 16476fd607bSopenharmony_ci uuid_t uuid; 16576fd607bSopenharmony_ci uuid_generate(uuid); 16676fd607bSopenharmony_ci char str[UUID_STR_LENGTH] = {}; 16776fd607bSopenharmony_ci uuid_unparse(uuid, str); 16876fd607bSopenharmony_ci return str; 16976fd607bSopenharmony_ci} 17076fd607bSopenharmony_ci 17176fd607bSopenharmony_cishared_ptr<ThumbnailManager> ThumbnailManager::GetInstance() 17276fd607bSopenharmony_ci{ 17376fd607bSopenharmony_ci if (instance_ == nullptr) { 17476fd607bSopenharmony_ci lock_guard<mutex> lock(mutex_); 17576fd607bSopenharmony_ci if (instance_ == nullptr) { 17676fd607bSopenharmony_ci instance_ = shared_ptr<ThumbnailManager>(new ThumbnailManager()); 17776fd607bSopenharmony_ci } 17876fd607bSopenharmony_ci } 17976fd607bSopenharmony_ci 18076fd607bSopenharmony_ci return instance_; 18176fd607bSopenharmony_ci} 18276fd607bSopenharmony_ci 18376fd607bSopenharmony_civoid ThumbnailManager::Init() 18476fd607bSopenharmony_ci{ 18576fd607bSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 18676fd607bSopenharmony_ci if (init_) { 18776fd607bSopenharmony_ci return; 18876fd607bSopenharmony_ci } 18976fd607bSopenharmony_ci init_ = true; 19076fd607bSopenharmony_ci isThreadRunning_ = true; 19176fd607bSopenharmony_ci for (auto i = 0; i < THREAD_NUM; i++) { 19276fd607bSopenharmony_ci threads_.emplace_back( 19376fd607bSopenharmony_ci std::thread([this, num = i]() { this->ImageWorker(num); }) 19476fd607bSopenharmony_ci ); 19576fd607bSopenharmony_ci threads_[i].detach(); 19676fd607bSopenharmony_ci } 19776fd607bSopenharmony_ci return; 19876fd607bSopenharmony_ci} 19976fd607bSopenharmony_ci 20076fd607bSopenharmony_cistring ThumbnailManager::AddPhotoRequest(const RequestPhotoParams ¶ms, napi_env env, napi_ref callback) 20176fd607bSopenharmony_ci{ 20276fd607bSopenharmony_ci shared_ptr<ThumbnailRequest> request = make_shared<ThumbnailRequest>(params, env, callback); 20376fd607bSopenharmony_ci string requestId = GenerateRequestId(); 20476fd607bSopenharmony_ci request->SetUUID(requestId); 20576fd607bSopenharmony_ci if (!thumbRequest_.Insert(requestId, request)) { 20676fd607bSopenharmony_ci return ""; 20776fd607bSopenharmony_ci } 20876fd607bSopenharmony_ci // judge from request option 20976fd607bSopenharmony_ci if (NeedFastThumb(params.size, params.type)) { 21076fd607bSopenharmony_ci AddFastPhotoRequest(request); 21176fd607bSopenharmony_ci } else { 21276fd607bSopenharmony_ci AddQualityPhotoRequest(request); 21376fd607bSopenharmony_ci } 21476fd607bSopenharmony_ci return requestId; 21576fd607bSopenharmony_ci} 21676fd607bSopenharmony_ci 21776fd607bSopenharmony_civoid ThumbnailManager::RemovePhotoRequest(const string &requestId) 21876fd607bSopenharmony_ci{ 21976fd607bSopenharmony_ci RequestSharedPtr ptr; 22076fd607bSopenharmony_ci if (thumbRequest_.Find(requestId, ptr)) { 22176fd607bSopenharmony_ci if (ptr == nullptr) { 22276fd607bSopenharmony_ci return; 22376fd607bSopenharmony_ci } 22476fd607bSopenharmony_ci // do not need delete from queue, just update remove status. 22576fd607bSopenharmony_ci ptr->UpdateStatus(ThumbnailStatus::THUMB_REMOVE); 22676fd607bSopenharmony_ci ptr->ReleaseCallbackRef(); 22776fd607bSopenharmony_ci } 22876fd607bSopenharmony_ci thumbRequest_.Erase(requestId); 22976fd607bSopenharmony_ci} 23076fd607bSopenharmony_ci 23176fd607bSopenharmony_ciThumbnailManager::~ThumbnailManager() 23276fd607bSopenharmony_ci{ 23376fd607bSopenharmony_ci isThreadRunning_ = false; 23476fd607bSopenharmony_ci queueCv_.notify_all(); 23576fd607bSopenharmony_ci for (auto &thread : threads_) { 23676fd607bSopenharmony_ci if (thread.joinable()) { 23776fd607bSopenharmony_ci thread.join(); 23876fd607bSopenharmony_ci } 23976fd607bSopenharmony_ci } 24076fd607bSopenharmony_ci} 24176fd607bSopenharmony_ci 24276fd607bSopenharmony_civoid SetThreadName(const string &threadName, int num) 24376fd607bSopenharmony_ci{ 24476fd607bSopenharmony_ci string name = threadName; 24576fd607bSopenharmony_ci name.append(to_string(num)); 24676fd607bSopenharmony_ci pthread_setname_np(pthread_self(), name.c_str()); 24776fd607bSopenharmony_ci} 24876fd607bSopenharmony_ci 24976fd607bSopenharmony_civoid ThumbnailManager::AddFastPhotoRequest(const RequestSharedPtr &request) 25076fd607bSopenharmony_ci{ 25176fd607bSopenharmony_ci request->UpdateStatus(ThumbnailStatus::THUMB_FAST); 25276fd607bSopenharmony_ci fastQueue_.Push(request); 25376fd607bSopenharmony_ci queueCv_.notify_one(); 25476fd607bSopenharmony_ci} 25576fd607bSopenharmony_ci 25676fd607bSopenharmony_civoid ThumbnailManager::AddQualityPhotoRequest(const RequestSharedPtr &request) 25776fd607bSopenharmony_ci{ 25876fd607bSopenharmony_ci request->UpdateStatus(ThumbnailStatus::THUMB_QUALITY); 25976fd607bSopenharmony_ci qualityQueue_.Push(request); 26076fd607bSopenharmony_ci queueCv_.notify_one(); 26176fd607bSopenharmony_ci} 26276fd607bSopenharmony_ci 26376fd607bSopenharmony_cistatic bool GetFastThumbNewSize(const Size &size, Size &newSize) 26476fd607bSopenharmony_ci{ 26576fd607bSopenharmony_ci // if thumbnail size is YEAR SIZE, do not need to request fast thumb 26676fd607bSopenharmony_ci // if thumbnail size is MTH SIZE, return YEAR SIZE 26776fd607bSopenharmony_ci // if thumbnail size is THUMB SIZE, return MTH SIZE 26876fd607bSopenharmony_ci // else return THUMB SIZE 26976fd607bSopenharmony_ci if (size.width == DEFAULT_YEAR_SIZE && size.height == DEFAULT_YEAR_SIZE) { 27076fd607bSopenharmony_ci newSize.height = DEFAULT_YEAR_SIZE; 27176fd607bSopenharmony_ci newSize.width = DEFAULT_YEAR_SIZE; 27276fd607bSopenharmony_ci return false; 27376fd607bSopenharmony_ci } else if (size.width == DEFAULT_MTH_SIZE && size.height == DEFAULT_MTH_SIZE) { 27476fd607bSopenharmony_ci newSize.height = DEFAULT_YEAR_SIZE; 27576fd607bSopenharmony_ci newSize.width = DEFAULT_YEAR_SIZE; 27676fd607bSopenharmony_ci return true; 27776fd607bSopenharmony_ci } else if (size.width <= DEFAULT_THUMB_SIZE && size.height <= DEFAULT_THUMB_SIZE) { 27876fd607bSopenharmony_ci newSize.height = DEFAULT_MTH_SIZE; 27976fd607bSopenharmony_ci newSize.width = DEFAULT_MTH_SIZE; 28076fd607bSopenharmony_ci return true; 28176fd607bSopenharmony_ci } else { 28276fd607bSopenharmony_ci newSize.height = DEFAULT_THUMB_SIZE; 28376fd607bSopenharmony_ci newSize.width = DEFAULT_THUMB_SIZE; 28476fd607bSopenharmony_ci return true; 28576fd607bSopenharmony_ci } 28676fd607bSopenharmony_ci} 28776fd607bSopenharmony_ci 28876fd607bSopenharmony_cistatic int OpenThumbnail(const string &path, ThumbnailType type) 28976fd607bSopenharmony_ci{ 29076fd607bSopenharmony_ci if (!path.empty()) { 29176fd607bSopenharmony_ci string sandboxPath = GetSandboxPath(path, type); 29276fd607bSopenharmony_ci int fd = -1; 29376fd607bSopenharmony_ci if (!sandboxPath.empty()) { 29476fd607bSopenharmony_ci fd = open(sandboxPath.c_str(), O_RDONLY); 29576fd607bSopenharmony_ci } 29676fd607bSopenharmony_ci if (fd > 0) { 29776fd607bSopenharmony_ci return fd; 29876fd607bSopenharmony_ci } 29976fd607bSopenharmony_ci } 30076fd607bSopenharmony_ci return E_ERR; 30176fd607bSopenharmony_ci} 30276fd607bSopenharmony_ci 30376fd607bSopenharmony_cistatic int OpenKeyFrameThumbnail(const string &path, const int32_t &beginStamp, const int32_t &type) 30476fd607bSopenharmony_ci{ 30576fd607bSopenharmony_ci if (!path.empty()) { 30676fd607bSopenharmony_ci string sandboxPath = GetKeyFrameSandboxPath(path, beginStamp, type); 30776fd607bSopenharmony_ci int fd = -1; 30876fd607bSopenharmony_ci if (!sandboxPath.empty()) { 30976fd607bSopenharmony_ci fd = open(sandboxPath.c_str(), O_RDONLY); 31076fd607bSopenharmony_ci } 31176fd607bSopenharmony_ci if (fd > 0) { 31276fd607bSopenharmony_ci return fd; 31376fd607bSopenharmony_ci } 31476fd607bSopenharmony_ci NAPI_ERR_LOG("OpenKeyFrameThumbnail failed, fd: %{public}d", fd); 31576fd607bSopenharmony_ci } 31676fd607bSopenharmony_ci return E_ERR; 31776fd607bSopenharmony_ci} 31876fd607bSopenharmony_ci 31976fd607bSopenharmony_cistatic bool IfSizeEqualsRatio(const Size &imageSize, const Size &targetSize) 32076fd607bSopenharmony_ci{ 32176fd607bSopenharmony_ci if (imageSize.height <= 0 || targetSize.height <= 0) { 32276fd607bSopenharmony_ci return false; 32376fd607bSopenharmony_ci } 32476fd607bSopenharmony_ci 32576fd607bSopenharmony_ci float imageSizeScale = static_cast<float>(imageSize.width) / static_cast<float>(imageSize.height); 32676fd607bSopenharmony_ci float targetSizeScale = static_cast<float>(targetSize.width) / static_cast<float>(targetSize.height); 32776fd607bSopenharmony_ci if (imageSizeScale - targetSizeScale > FLOAT_EPSILON || targetSizeScale - imageSizeScale > FLOAT_EPSILON) { 32876fd607bSopenharmony_ci return false; 32976fd607bSopenharmony_ci } else { 33076fd607bSopenharmony_ci return true; 33176fd607bSopenharmony_ci } 33276fd607bSopenharmony_ci} 33376fd607bSopenharmony_ci 33476fd607bSopenharmony_cistatic PixelMapPtr CreateThumbnailByAshmem(UniqueFd &uniqueFd, const Size &size) 33576fd607bSopenharmony_ci{ 33676fd607bSopenharmony_ci MediaLibraryTracer tracer; 33776fd607bSopenharmony_ci tracer.Start("CreateThumbnailByAshmem"); 33876fd607bSopenharmony_ci 33976fd607bSopenharmony_ci Media::InitializationOptions option = { 34076fd607bSopenharmony_ci .size = size, 34176fd607bSopenharmony_ci }; 34276fd607bSopenharmony_ci PixelMapPtr pixel = Media::PixelMap::Create(option); 34376fd607bSopenharmony_ci if (pixel == nullptr) { 34476fd607bSopenharmony_ci NAPI_ERR_LOG("Can not create pixel"); 34576fd607bSopenharmony_ci return nullptr; 34676fd607bSopenharmony_ci } 34776fd607bSopenharmony_ci 34876fd607bSopenharmony_ci UniqueFd dupFd = UniqueFd(dup(uniqueFd.Get())); 34976fd607bSopenharmony_ci MMapFdPtr mmapFd(dupFd.Get(), false); 35076fd607bSopenharmony_ci if (!mmapFd.IsValid()) { 35176fd607bSopenharmony_ci NAPI_ERR_LOG("Can not mmap by fd"); 35276fd607bSopenharmony_ci return nullptr; 35376fd607bSopenharmony_ci } 35476fd607bSopenharmony_ci auto memSize = static_cast<int32_t>(mmapFd.GetFdSize()); 35576fd607bSopenharmony_ci 35676fd607bSopenharmony_ci void* fdPtr = new int32_t(); 35776fd607bSopenharmony_ci *static_cast<int32_t*>(fdPtr) = dupFd.Release(); 35876fd607bSopenharmony_ci pixel->SetPixelsAddr(mmapFd.GetFdPtr(), fdPtr, memSize, Media::AllocatorType::SHARE_MEM_ALLOC, nullptr); 35976fd607bSopenharmony_ci return pixel; 36076fd607bSopenharmony_ci} 36176fd607bSopenharmony_ci 36276fd607bSopenharmony_cistatic PixelMapPtr DecodeThumbnail(const UniqueFd &uniqueFd, const Size &size) 36376fd607bSopenharmony_ci{ 36476fd607bSopenharmony_ci MediaLibraryTracer tracer; 36576fd607bSopenharmony_ci tracer.Start("ImageSource::CreateImageSource"); 36676fd607bSopenharmony_ci SourceOptions opts; 36776fd607bSopenharmony_ci uint32_t err = 0; 36876fd607bSopenharmony_ci unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err); 36976fd607bSopenharmony_ci if (imageSource == nullptr) { 37076fd607bSopenharmony_ci NAPI_ERR_LOG("CreateImageSource err %{public}d", err); 37176fd607bSopenharmony_ci return nullptr; 37276fd607bSopenharmony_ci } 37376fd607bSopenharmony_ci 37476fd607bSopenharmony_ci ImageInfo imageInfo; 37576fd607bSopenharmony_ci err = imageSource->GetImageInfo(0, imageInfo); 37676fd607bSopenharmony_ci if (err != E_OK) { 37776fd607bSopenharmony_ci NAPI_ERR_LOG("GetImageInfo err %{public}d", err); 37876fd607bSopenharmony_ci return nullptr; 37976fd607bSopenharmony_ci } 38076fd607bSopenharmony_ci 38176fd607bSopenharmony_ci bool isEqualsRatio = IfSizeEqualsRatio(imageInfo.size, size); 38276fd607bSopenharmony_ci DecodeOptions decodeOpts; 38376fd607bSopenharmony_ci decodeOpts.desiredSize = isEqualsRatio ? size : imageInfo.size; 38476fd607bSopenharmony_ci unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err); 38576fd607bSopenharmony_ci if (pixelMap == nullptr) { 38676fd607bSopenharmony_ci NAPI_ERR_LOG("CreatePixelMap err %{public}d", err); 38776fd607bSopenharmony_ci return nullptr; 38876fd607bSopenharmony_ci } 38976fd607bSopenharmony_ci 39076fd607bSopenharmony_ci PostProc postProc; 39176fd607bSopenharmony_ci if (size.width != DEFAULT_ORIGINAL && !isEqualsRatio && !postProc.CenterScale(size, *pixelMap)) { 39276fd607bSopenharmony_ci NAPI_ERR_LOG("CenterScale failed, size: %{public}d * %{public}d, imageInfo size: %{public}d * %{public}d", 39376fd607bSopenharmony_ci size.width, size.height, imageInfo.size.width, imageInfo.size.height); 39476fd607bSopenharmony_ci return nullptr; 39576fd607bSopenharmony_ci } 39676fd607bSopenharmony_ci 39776fd607bSopenharmony_ci // Make the ashmem of pixelmap to be purgeable after the operation on ashmem. 39876fd607bSopenharmony_ci // And then make the pixelmap subject to PurgeableManager's control. 39976fd607bSopenharmony_ci#ifdef IMAGE_PURGEABLE_PIXELMAP 40076fd607bSopenharmony_ci PurgeableBuilder::MakePixelMapToBePurgeable(pixelMap, imageSource, decodeOpts, size); 40176fd607bSopenharmony_ci#endif 40276fd607bSopenharmony_ci return pixelMap; 40376fd607bSopenharmony_ci} 40476fd607bSopenharmony_ci 40576fd607bSopenharmony_cistatic int32_t GetPixelMapFromServer(const string &uriStr, const Size &size, const string &path) 40676fd607bSopenharmony_ci{ 40776fd607bSopenharmony_ci string openUriStr = uriStr + "?" + MEDIA_OPERN_KEYWORD + "=" + MEDIA_DATA_DB_THUMBNAIL + "&" + 40876fd607bSopenharmony_ci MEDIA_DATA_DB_WIDTH + "=" + to_string(size.width) + "&" + MEDIA_DATA_DB_HEIGHT + "=" + 40976fd607bSopenharmony_ci to_string(size.height); 41076fd607bSopenharmony_ci if (IsAsciiString(path)) { 41176fd607bSopenharmony_ci openUriStr += "&" + THUMBNAIL_PATH + "=" + path; 41276fd607bSopenharmony_ci } 41376fd607bSopenharmony_ci Uri openUri(openUriStr); 41476fd607bSopenharmony_ci return UserFileClient::OpenFile(openUri, "R"); 41576fd607bSopenharmony_ci} 41676fd607bSopenharmony_ci 41776fd607bSopenharmony_cistatic int32_t GetKeyFramePixelMapFromServer(const string &uriStr, const string &path, 41876fd607bSopenharmony_ci const int32_t &beginStamp, const int32_t &type) 41976fd607bSopenharmony_ci{ 42076fd607bSopenharmony_ci string openUriStr = uriStr + "?" + MEDIA_OPERN_KEYWORD + "=" + MEDIA_DATA_DB_KEY_FRAME + "&" + 42176fd607bSopenharmony_ci MEDIA_DATA_DB_BEGIN_STAMP + "=" + to_string(beginStamp) + "&" + MEDIA_DATA_DB_TYPE + "=" + to_string(type); 42276fd607bSopenharmony_ci if (IsAsciiString(path)) { 42376fd607bSopenharmony_ci openUriStr += "&" + THUMBNAIL_PATH + "=" + path; 42476fd607bSopenharmony_ci } 42576fd607bSopenharmony_ci Uri openUri(openUriStr); 42676fd607bSopenharmony_ci return UserFileClient::OpenFile(openUri, "R"); 42776fd607bSopenharmony_ci} 42876fd607bSopenharmony_ci 42976fd607bSopenharmony_ciunique_ptr<PixelMap> ThumbnailManager::QueryThumbnail(const string &uriStr, const Size &size, const string &path) 43076fd607bSopenharmony_ci{ 43176fd607bSopenharmony_ci MediaLibraryTracer tracer; 43276fd607bSopenharmony_ci tracer.Start("QueryThumbnail uri:" + uriStr); 43376fd607bSopenharmony_ci tracer.Start("DataShare::OpenFile"); 43476fd607bSopenharmony_ci ThumbnailType thumbType = GetThumbType(size.width, size.height); 43576fd607bSopenharmony_ci if (MediaFileUri::GetMediaTypeFromUri(uriStr) == MediaType::MEDIA_TYPE_AUDIO && 43676fd607bSopenharmony_ci (thumbType == ThumbnailType::MTH || thumbType == ThumbnailType::YEAR)) { 43776fd607bSopenharmony_ci thumbType = ThumbnailType::THUMB; 43876fd607bSopenharmony_ci } 43976fd607bSopenharmony_ci UniqueFd uniqueFd(OpenThumbnail(path, thumbType)); 44076fd607bSopenharmony_ci if (uniqueFd.Get() == E_ERR) { 44176fd607bSopenharmony_ci uniqueFd = UniqueFd(GetPixelMapFromServer(uriStr, size, path)); 44276fd607bSopenharmony_ci if (uniqueFd.Get() < 0) { 44376fd607bSopenharmony_ci NAPI_ERR_LOG("queryThumb is null, errCode is %{public}d", uniqueFd.Get()); 44476fd607bSopenharmony_ci return nullptr; 44576fd607bSopenharmony_ci } 44676fd607bSopenharmony_ci return DecodeThumbnail(uniqueFd, size); 44776fd607bSopenharmony_ci } 44876fd607bSopenharmony_ci tracer.Finish(); 44976fd607bSopenharmony_ci if (thumbType == ThumbnailType::MTH || thumbType == ThumbnailType::YEAR) { 45076fd607bSopenharmony_ci return CreateThumbnailByAshmem(uniqueFd, size); 45176fd607bSopenharmony_ci } else { 45276fd607bSopenharmony_ci return DecodeThumbnail(uniqueFd, size); 45376fd607bSopenharmony_ci } 45476fd607bSopenharmony_ci} 45576fd607bSopenharmony_ci 45676fd607bSopenharmony_ciunique_ptr<PixelMap> ThumbnailManager::QueryKeyFrameThumbnail(const string &uriStr, const int &beginStamp, 45776fd607bSopenharmony_ci const int &type, const string &path) 45876fd607bSopenharmony_ci{ 45976fd607bSopenharmony_ci MediaLibraryTracer tracer; 46076fd607bSopenharmony_ci tracer.Start("QueryKeyFrameThumbnail uri:" + uriStr); 46176fd607bSopenharmony_ci 46276fd607bSopenharmony_ci UniqueFd uniqueFd(OpenKeyFrameThumbnail(path, beginStamp, type)); 46376fd607bSopenharmony_ci Size size; 46476fd607bSopenharmony_ci size.width = DEFAULT_THUMB_SIZE; 46576fd607bSopenharmony_ci size.height = DEFAULT_THUMB_SIZE; 46676fd607bSopenharmony_ci if (uniqueFd.Get() == E_ERR) { 46776fd607bSopenharmony_ci uniqueFd = UniqueFd(GetKeyFramePixelMapFromServer(uriStr, path, beginStamp, type)); 46876fd607bSopenharmony_ci if (uniqueFd.Get() < 0) { 46976fd607bSopenharmony_ci NAPI_ERR_LOG("queryKeyFrameThumb is null, errCode is %{public}d", uniqueFd.Get()); 47076fd607bSopenharmony_ci return nullptr; 47176fd607bSopenharmony_ci } 47276fd607bSopenharmony_ci } 47376fd607bSopenharmony_ci tracer.Finish(); 47476fd607bSopenharmony_ci return DecodeThumbnail(uniqueFd, size); 47576fd607bSopenharmony_ci} 47676fd607bSopenharmony_ci 47776fd607bSopenharmony_civoid ThumbnailManager::DeleteRequestIdFromMap(const string &requestId) 47876fd607bSopenharmony_ci{ 47976fd607bSopenharmony_ci thumbRequest_.Erase(requestId); 48076fd607bSopenharmony_ci} 48176fd607bSopenharmony_ci 48276fd607bSopenharmony_cibool ThumbnailManager::RequestFastImage(const RequestSharedPtr &request) 48376fd607bSopenharmony_ci{ 48476fd607bSopenharmony_ci MediaLibraryTracer tracer; 48576fd607bSopenharmony_ci tracer.Start("ThumbnailManager::RequestFastImage"); 48676fd607bSopenharmony_ci request->SetFd(DEFAULT_FD); 48776fd607bSopenharmony_ci Size fastSize; 48876fd607bSopenharmony_ci if (!GetFastThumbNewSize(request->GetRequestSize(), fastSize)) { 48976fd607bSopenharmony_ci return false; 49076fd607bSopenharmony_ci } 49176fd607bSopenharmony_ci UniqueFd uniqueFd(OpenThumbnail(request->GetPath(), GetThumbType(fastSize.width, fastSize.height))); 49276fd607bSopenharmony_ci if (uniqueFd.Get() < 0) { 49376fd607bSopenharmony_ci // Can not get fast image in sandbox 49476fd607bSopenharmony_ci int32_t outFd = GetPixelMapFromServer(request->GetUri(), request->GetRequestSize(), request->GetPath()); 49576fd607bSopenharmony_ci if (outFd <= 0) { 49676fd607bSopenharmony_ci NAPI_ERR_LOG("Can not get thumbnail from server, uri=%{private}s", request->GetUri().c_str()); 49776fd607bSopenharmony_ci request->error = E_FAIL; 49876fd607bSopenharmony_ci return false; 49976fd607bSopenharmony_ci } 50076fd607bSopenharmony_ci request->SetFd(outFd); 50176fd607bSopenharmony_ci } 50276fd607bSopenharmony_ci 50376fd607bSopenharmony_ci ThumbnailType thumbType = GetThumbType(fastSize.width, fastSize.height); 50476fd607bSopenharmony_ci PixelMapPtr pixelMap = nullptr; 50576fd607bSopenharmony_ci if (request->GetFd().Get() == DEFAULT_FD && 50676fd607bSopenharmony_ci (thumbType == ThumbnailType::MTH || thumbType == ThumbnailType::YEAR)) { 50776fd607bSopenharmony_ci pixelMap = CreateThumbnailByAshmem(uniqueFd, fastSize); 50876fd607bSopenharmony_ci } else { 50976fd607bSopenharmony_ci pixelMap = DecodeThumbnail(request->GetFd(), fastSize); 51076fd607bSopenharmony_ci } 51176fd607bSopenharmony_ci if (pixelMap == nullptr) { 51276fd607bSopenharmony_ci request->error = E_FAIL; 51376fd607bSopenharmony_ci return false; 51476fd607bSopenharmony_ci } 51576fd607bSopenharmony_ci request->SetFastPixelMap(move(pixelMap)); 51676fd607bSopenharmony_ci return true; 51776fd607bSopenharmony_ci} 51876fd607bSopenharmony_ci 51976fd607bSopenharmony_civoid ThumbnailManager::DealWithFastRequest(const RequestSharedPtr &request) 52076fd607bSopenharmony_ci{ 52176fd607bSopenharmony_ci MediaLibraryTracer tracer; 52276fd607bSopenharmony_ci tracer.Start("ThumbnailManager::DealWithFastRequest"); 52376fd607bSopenharmony_ci 52476fd607bSopenharmony_ci if (request == nullptr) { 52576fd607bSopenharmony_ci return; 52676fd607bSopenharmony_ci } 52776fd607bSopenharmony_ci 52876fd607bSopenharmony_ci if (!RequestFastImage(request) && request->error != E_FAIL) { 52976fd607bSopenharmony_ci // when local pixelmap not exit, must add QualityThread 53076fd607bSopenharmony_ci AddQualityPhotoRequest(request); 53176fd607bSopenharmony_ci return; 53276fd607bSopenharmony_ci } 53376fd607bSopenharmony_ci 53476fd607bSopenharmony_ci // callback 53576fd607bSopenharmony_ci NotifyImage(request); 53676fd607bSopenharmony_ci} 53776fd607bSopenharmony_ci 53876fd607bSopenharmony_civoid ThumbnailManager::DealWithQualityRequest(const RequestSharedPtr &request) 53976fd607bSopenharmony_ci{ 54076fd607bSopenharmony_ci MediaLibraryTracer tracer; 54176fd607bSopenharmony_ci tracer.Start("ThumbnailManager::DealWithQualityRequest"); 54276fd607bSopenharmony_ci 54376fd607bSopenharmony_ci unique_ptr<PixelMap> pixelMapPtr = nullptr; 54476fd607bSopenharmony_ci if (request->GetFd().Get() > 0) { 54576fd607bSopenharmony_ci pixelMapPtr = DecodeThumbnail(request->GetFd(), request->GetRequestSize()); 54676fd607bSopenharmony_ci } else { 54776fd607bSopenharmony_ci pixelMapPtr = QueryThumbnail(request->GetUri(), request->GetRequestSize(), request->GetPath()); 54876fd607bSopenharmony_ci } 54976fd607bSopenharmony_ci 55076fd607bSopenharmony_ci if (pixelMapPtr == nullptr) { 55176fd607bSopenharmony_ci NAPI_ERR_LOG("Can not get pixelMap"); 55276fd607bSopenharmony_ci request->error = E_FAIL; 55376fd607bSopenharmony_ci } 55476fd607bSopenharmony_ci request->SetPixelMap(move(pixelMapPtr)); 55576fd607bSopenharmony_ci 55676fd607bSopenharmony_ci // callback 55776fd607bSopenharmony_ci NotifyImage(request); 55876fd607bSopenharmony_ci} 55976fd607bSopenharmony_ci 56076fd607bSopenharmony_civoid ThumbnailManager::ImageWorker(int num) 56176fd607bSopenharmony_ci{ 56276fd607bSopenharmony_ci SetThreadName("ImageWorker", num); 56376fd607bSopenharmony_ci while (true) { 56476fd607bSopenharmony_ci if (!isThreadRunning_) { 56576fd607bSopenharmony_ci return; 56676fd607bSopenharmony_ci } 56776fd607bSopenharmony_ci if (!fastQueue_.Empty()) { 56876fd607bSopenharmony_ci RequestSharedPtr request; 56976fd607bSopenharmony_ci if (fastQueue_.Pop(request) && request->NeedContinue()) { 57076fd607bSopenharmony_ci DealWithFastRequest(request); 57176fd607bSopenharmony_ci } 57276fd607bSopenharmony_ci } else if (!qualityQueue_.Empty()) { 57376fd607bSopenharmony_ci RequestSharedPtr request; 57476fd607bSopenharmony_ci if (qualityQueue_.Pop(request) && request->NeedContinue()) { 57576fd607bSopenharmony_ci DealWithQualityRequest(request); 57676fd607bSopenharmony_ci } 57776fd607bSopenharmony_ci } else { 57876fd607bSopenharmony_ci std::unique_lock<std::mutex> lock(queueLock_); 57976fd607bSopenharmony_ci queueCv_.wait(lock, [this]() { 58076fd607bSopenharmony_ci return !isThreadRunning_ || !(qualityQueue_.Empty() && fastQueue_.Empty()); 58176fd607bSopenharmony_ci }); 58276fd607bSopenharmony_ci } 58376fd607bSopenharmony_ci } 58476fd607bSopenharmony_ci} 58576fd607bSopenharmony_ci 58676fd607bSopenharmony_cistatic void HandlePixelCallback(const RequestSharedPtr &request) 58776fd607bSopenharmony_ci{ 58876fd607bSopenharmony_ci napi_env env = request->callback_.env_; 58976fd607bSopenharmony_ci napi_value jsCallback = nullptr; 59076fd607bSopenharmony_ci napi_status status = napi_get_reference_value(env, request->callback_.callBackRef_, &jsCallback); 59176fd607bSopenharmony_ci if (status != napi_ok) { 59276fd607bSopenharmony_ci NAPI_ERR_LOG("Create reference fail, status: %{public}d", status); 59376fd607bSopenharmony_ci return; 59476fd607bSopenharmony_ci } 59576fd607bSopenharmony_ci 59676fd607bSopenharmony_ci napi_value retVal = nullptr; 59776fd607bSopenharmony_ci napi_value result[ARGS_TWO]; 59876fd607bSopenharmony_ci if (request->GetStatus() == ThumbnailStatus::THUMB_REMOVE) { 59976fd607bSopenharmony_ci return; 60076fd607bSopenharmony_ci } 60176fd607bSopenharmony_ci 60276fd607bSopenharmony_ci if (request->error == E_FAIL) { 60376fd607bSopenharmony_ci int32_t errorNum = MediaLibraryNapiUtils::TransErrorCode("requestPhoto", request->error); 60476fd607bSopenharmony_ci MediaLibraryNapiUtils::CreateNapiErrorObject(env, result[PARAM0], errorNum, 60576fd607bSopenharmony_ci "Failed to request Photo"); 60676fd607bSopenharmony_ci } else { 60776fd607bSopenharmony_ci result[PARAM0] = nullptr; 60876fd607bSopenharmony_ci } 60976fd607bSopenharmony_ci if (request->GetStatus() == ThumbnailStatus::THUMB_FAST) { 61076fd607bSopenharmony_ci result[PARAM1] = Media::PixelMapNapi::CreatePixelMap(env, 61176fd607bSopenharmony_ci shared_ptr<PixelMap>(request->GetFastPixelMap())); 61276fd607bSopenharmony_ci } else { 61376fd607bSopenharmony_ci result[PARAM1] = Media::PixelMapNapi::CreatePixelMap(env, 61476fd607bSopenharmony_ci shared_ptr<PixelMap>(request->GetPixelMap())); 61576fd607bSopenharmony_ci } 61676fd607bSopenharmony_ci 61776fd607bSopenharmony_ci status = napi_call_function(env, nullptr, jsCallback, ARGS_TWO, result, &retVal); 61876fd607bSopenharmony_ci if (status != napi_ok) { 61976fd607bSopenharmony_ci NAPI_ERR_LOG("CallJs napi_call_function fail, status: %{public}d", status); 62076fd607bSopenharmony_ci return; 62176fd607bSopenharmony_ci } 62276fd607bSopenharmony_ci} 62376fd607bSopenharmony_ci 62476fd607bSopenharmony_cistatic void UvJsExecute(uv_work_t *work) 62576fd607bSopenharmony_ci{ 62676fd607bSopenharmony_ci // js thread 62776fd607bSopenharmony_ci if (work == nullptr) { 62876fd607bSopenharmony_ci return; 62976fd607bSopenharmony_ci } 63076fd607bSopenharmony_ci 63176fd607bSopenharmony_ci ThumnailUv *uvMsg = reinterpret_cast<ThumnailUv *>(work->data); 63276fd607bSopenharmony_ci if (uvMsg == nullptr) { 63376fd607bSopenharmony_ci delete work; 63476fd607bSopenharmony_ci return; 63576fd607bSopenharmony_ci } 63676fd607bSopenharmony_ci if (uvMsg->request_ == nullptr) { 63776fd607bSopenharmony_ci delete uvMsg; 63876fd607bSopenharmony_ci delete work; 63976fd607bSopenharmony_ci return; 64076fd607bSopenharmony_ci } 64176fd607bSopenharmony_ci do { 64276fd607bSopenharmony_ci napi_env env = uvMsg->request_->callback_.env_; 64376fd607bSopenharmony_ci if (!uvMsg->request_->NeedContinue()) { 64476fd607bSopenharmony_ci break; 64576fd607bSopenharmony_ci } 64676fd607bSopenharmony_ci NapiScopeHandler scopeHandler(env); 64776fd607bSopenharmony_ci if (!scopeHandler.IsValid()) { 64876fd607bSopenharmony_ci break; 64976fd607bSopenharmony_ci } 65076fd607bSopenharmony_ci HandlePixelCallback(uvMsg->request_); 65176fd607bSopenharmony_ci } while (0); 65276fd607bSopenharmony_ci if (uvMsg->manager_ == nullptr) { 65376fd607bSopenharmony_ci delete uvMsg; 65476fd607bSopenharmony_ci delete work; 65576fd607bSopenharmony_ci return; 65676fd607bSopenharmony_ci } 65776fd607bSopenharmony_ci if (uvMsg->request_->GetStatus() == ThumbnailStatus::THUMB_FAST && 65876fd607bSopenharmony_ci NeedQualityThumb(uvMsg->request_->GetRequestSize(), uvMsg->request_->requestPhotoType)) { 65976fd607bSopenharmony_ci uvMsg->manager_->AddQualityPhotoRequest(uvMsg->request_); 66076fd607bSopenharmony_ci } else { 66176fd607bSopenharmony_ci uvMsg->manager_->DeleteRequestIdFromMap(uvMsg->request_->GetUUID()); 66276fd607bSopenharmony_ci uvMsg->request_->ReleaseCallbackRef(); 66376fd607bSopenharmony_ci } 66476fd607bSopenharmony_ci 66576fd607bSopenharmony_ci delete uvMsg; 66676fd607bSopenharmony_ci delete work; 66776fd607bSopenharmony_ci} 66876fd607bSopenharmony_ci 66976fd607bSopenharmony_civoid ThumbnailManager::NotifyImage(const RequestSharedPtr &request) 67076fd607bSopenharmony_ci{ 67176fd607bSopenharmony_ci MediaLibraryTracer tracer; 67276fd607bSopenharmony_ci tracer.Start("ThumbnailManager::NotifyImage"); 67376fd607bSopenharmony_ci 67476fd607bSopenharmony_ci if (!request->NeedContinue()) { 67576fd607bSopenharmony_ci DeleteRequestIdFromMap(request->GetUUID()); 67676fd607bSopenharmony_ci return; 67776fd607bSopenharmony_ci } 67876fd607bSopenharmony_ci 67976fd607bSopenharmony_ci uv_loop_s *loop = nullptr; 68076fd607bSopenharmony_ci napi_get_uv_event_loop(request->callback_.env_, &loop); 68176fd607bSopenharmony_ci if (loop == nullptr) { 68276fd607bSopenharmony_ci DeleteRequestIdFromMap(request->GetUUID()); 68376fd607bSopenharmony_ci return; 68476fd607bSopenharmony_ci } 68576fd607bSopenharmony_ci 68676fd607bSopenharmony_ci uv_work_t *work = new (nothrow) uv_work_t; 68776fd607bSopenharmony_ci if (work == nullptr) { 68876fd607bSopenharmony_ci DeleteRequestIdFromMap(request->GetUUID()); 68976fd607bSopenharmony_ci return; 69076fd607bSopenharmony_ci } 69176fd607bSopenharmony_ci 69276fd607bSopenharmony_ci ThumnailUv *msg = new (nothrow) ThumnailUv(request, this); 69376fd607bSopenharmony_ci if (msg == nullptr) { 69476fd607bSopenharmony_ci delete work; 69576fd607bSopenharmony_ci DeleteRequestIdFromMap(request->GetUUID()); 69676fd607bSopenharmony_ci return; 69776fd607bSopenharmony_ci } 69876fd607bSopenharmony_ci 69976fd607bSopenharmony_ci work->data = reinterpret_cast<void *>(msg); 70076fd607bSopenharmony_ci int ret = uv_queue_work(loop, work, [](uv_work_t *w) {}, [](uv_work_t *w, int s) { 70176fd607bSopenharmony_ci UvJsExecute(w); 70276fd607bSopenharmony_ci }); 70376fd607bSopenharmony_ci if (ret != 0) { 70476fd607bSopenharmony_ci NAPI_ERR_LOG("Failed to execute libuv work queue, ret: %{public}d", ret); 70576fd607bSopenharmony_ci delete msg; 70676fd607bSopenharmony_ci delete work; 70776fd607bSopenharmony_ci return; 70876fd607bSopenharmony_ci } 70976fd607bSopenharmony_ci return; 71076fd607bSopenharmony_ci} 71176fd607bSopenharmony_ci} 71276fd607bSopenharmony_ci} 713