• 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 #define MLOG_TAG "MediaAssetManagerNapi"
17 
18 #include "media_asset_manager_napi.h"
19 
20 #include <fcntl.h>
21 #include <string>
22 #include <sys/sendfile.h>
23 #include <unordered_map>
24 #include <uuid/uuid.h>
25 
26 #include "access_token.h"
27 #include "accesstoken_kit.h"
28 #include "adapted_vo.h"
29 #include "dataobs_mgr_client.h"
30 #include "directory_ex.h"
31 #include "file_asset_napi.h"
32 #include "file_uri.h"
33 #include "image_source.h"
34 #include "image_source_napi.h"
35 #include "ipc_skeleton.h"
36 #include "media_column.h"
37 #include "media_file_utils.h"
38 #include "media_file_uri.h"
39 #include "medialibrary_business_code.h"
40 #include "medialibrary_client_errno.h"
41 #include "media_library_napi.h"
42 #include "medialibrary_errno.h"
43 #include "medialibrary_napi_log.h"
44 #include "medialibrary_napi_utils.h"
45 #include "medialibrary_napi_utils_ext.h"
46 #include "medialibrary_tracer.h"
47 #include "moving_photo_napi.h"
48 #include "moving_photo_call_transcoder.h"
49 #include "permission_utils.h"
50 #include "picture_handle_client.h"
51 #include "query_photo_vo.h"
52 #include "ui_extension_context.h"
53 #include "user_define_ipc_client.h"
54 #include "userfile_client.h"
55 #include "media_call_transcode.h"
56 #include "medialibrary_operation.h"
57 #include "media_asset_rdbstore.h"
58 
59 using namespace OHOS::Security::AccessToken;
60 
61 namespace OHOS {
62 namespace Media {
63 static const std::string MEDIA_ASSET_MANAGER_CLASS = "MediaAssetManager";
64 static std::mutex multiStagesCaptureLock;
65 static std::mutex registerTaskLock;
66 
67 const int32_t LOW_QUALITY_IMAGE = 1;
68 const int32_t HIGH_QUALITY_IMAGE = 0;
69 
70 const int32_t UUID_STR_LENGTH = 37;
71 const int32_t MAX_URI_SIZE = 384; // 256 for display name and 128 for relative path
72 const int32_t REQUEST_ID_MAX_LEN = 64;
73 const int32_t PROGRESS_MAX = 100;
74 
75 const std::string HIGH_TEMPERATURE = "high_temperature";
76 
77 static const std::string URI_TYPE = "uriType";
78 static const std::string TYPE_PHOTOS = "1";
79 
80 thread_local unique_ptr<ChangeListenerNapi> g_multiStagesRequestListObj = nullptr;
81 thread_local napi_ref constructor_ = nullptr;
82 
83 static std::map<std::string, std::shared_ptr<MultiStagesTaskObserver>> multiStagesObserverMap;
84 static std::map<std::string, std::map<std::string, AssetHandler*>> inProcessUriMap;
85 static SafeMap<std::string, AssetHandler*> inProcessFastRequests;
86 static SafeMap<std::string, AssetHandler*> onPreparedResult_;
87 static SafeMap<std::string, napi_value> onPreparedResultValue_;
88 static SafeMap<std::string, bool> isTranscoderMap_;
89 
Init(napi_env env,napi_value exports)90 napi_value MediaAssetManagerNapi::Init(napi_env env, napi_value exports)
91 {
92     NapiClassInfo info = {.name = MEDIA_ASSET_MANAGER_CLASS,
93         .ref = &constructor_,
94         .constructor = Constructor,
95         .props = {
96             DECLARE_NAPI_STATIC_FUNCTION("requestImage", JSRequestImage),
97             DECLARE_NAPI_STATIC_FUNCTION("requestImageData", JSRequestImageData),
98             DECLARE_NAPI_STATIC_FUNCTION("requestMovingPhoto", JSRequestMovingPhoto),
99             DECLARE_NAPI_STATIC_FUNCTION("requestVideoFile", JSRequestVideoFile),
100             DECLARE_NAPI_STATIC_FUNCTION("cancelRequest", JSCancelRequest),
101             DECLARE_NAPI_STATIC_FUNCTION("loadMovingPhoto", JSLoadMovingPhoto),
102             DECLARE_NAPI_STATIC_FUNCTION("quickRequestImage", JSRequestEfficientIImage)
103         }};
104         MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
105         return exports;
106 }
107 
Constructor(napi_env env,napi_callback_info info)108 napi_value MediaAssetManagerNapi::Constructor(napi_env env, napi_callback_info info)
109 {
110     napi_value newTarget = nullptr;
111     CHECK_ARGS(env, napi_get_new_target(env, info, &newTarget), JS_INNER_FAIL);
112     bool isConstructor = newTarget != nullptr;
113     if (isConstructor) {
114         napi_value thisVar = nullptr;
115         unique_ptr<MediaAssetManagerNapi> obj = make_unique<MediaAssetManagerNapi>();
116         CHECK_COND_WITH_MESSAGE(env, obj != nullptr, "Create MediaAssetManagerNapi failed");
117         CHECK_ARGS(env,
118             napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()), MediaAssetManagerNapi::Destructor,
119                 nullptr, nullptr),
120             JS_INNER_FAIL);
121         obj.release();
122         return thisVar;
123     }
124     napi_value constructor = nullptr;
125     napi_value result = nullptr;
126     NAPI_CALL(env, napi_get_reference_value(env, constructor_, &constructor));
127     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
128     return result;
129 }
130 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)131 void MediaAssetManagerNapi::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
132 {
133     auto* mediaAssetManager = reinterpret_cast<MediaAssetManagerNapi*>(nativeObject);
134     if (mediaAssetManager != nullptr) {
135         delete mediaAssetManager;
136         mediaAssetManager = nullptr;
137     }
138 }
139 
HasReadPermission()140 static bool HasReadPermission()
141 {
142     AccessTokenID tokenCaller = IPCSkeleton::GetSelfTokenID();
143     int result = AccessTokenKit::VerifyAccessToken(tokenCaller, PERM_READ_IMAGEVIDEO);
144     return result == PermissionState::PERMISSION_GRANTED;
145 }
146 
CreateAssetHandler(const std::string & photoId,const std::string & requestId,const std::string & uri,const MediaAssetDataHandlerPtr & handler,napi_threadsafe_function func)147 static AssetHandler* CreateAssetHandler(const std::string &photoId, const std::string &requestId,
148     const std::string &uri, const MediaAssetDataHandlerPtr &handler, napi_threadsafe_function func)
149 {
150     AssetHandler *assetHandler = new AssetHandler(photoId, requestId, uri, handler, func);
151     NAPI_DEBUG_LOG("[AssetHandler create] photoId: %{public}s, requestId: %{public}s, uri: %{public}s",
152         photoId.c_str(), requestId.c_str(), uri.c_str());
153     return assetHandler;
154 }
155 
DeleteAssetHandlerSafe(AssetHandler * handler,napi_env env)156 static void DeleteAssetHandlerSafe(AssetHandler *handler, napi_env env)
157 {
158     if (handler != nullptr) {
159         if (handler->dataHandler != nullptr) {
160             handler->dataHandler->DeleteNapiReference(env);
161         }
162         if (handler->threadSafeFunc != nullptr) {
163             napi_release_threadsafe_function(handler->threadSafeFunc, napi_tsfn_release);
164             handler->threadSafeFunc = nullptr;
165         }
166         delete handler;
167         handler = nullptr;
168     }
169 }
170 
DeleteProcessHandlerSafe(ProgressHandler * handler,napi_env env)171 static void DeleteProcessHandlerSafe(ProgressHandler *handler, napi_env env)
172 {
173     if (handler == nullptr) {
174         return;
175     }
176     if (handler->progressRef != nullptr && env != nullptr) {
177         napi_delete_reference(env, handler->progressRef);
178         handler->progressRef = nullptr;
179     }
180     if (handler->progressFunc != nullptr) {
181         napi_release_threadsafe_function(handler->progressFunc, napi_tsfn_release);
182         handler->progressFunc = nullptr;
183     }
184     delete handler;
185     handler = nullptr;
186 }
187 
InsertInProcessMapRecord(const std::string & requestUri,const std::string & requestId,AssetHandler * handler)188 static void InsertInProcessMapRecord(const std::string &requestUri, const std::string &requestId,
189     AssetHandler *handler)
190 {
191     std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
192     std::map<std::string, AssetHandler*> assetHandler;
193     auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(requestUri);
194     if (inProcessUriMap.find(uriLocal) != inProcessUriMap.end()) {
195         assetHandler = inProcessUriMap[uriLocal];
196         assetHandler[requestId] = handler;
197         inProcessUriMap[uriLocal] = assetHandler;
198     } else {
199         assetHandler[requestId] = handler;
200         inProcessUriMap[uriLocal] = assetHandler;
201     }
202 }
203 
204 // Do not use directly
DeleteRecordNoLock(const std::string & requestUri,const std::string & requestId)205 static void DeleteRecordNoLock(const std::string &requestUri, const std::string &requestId)
206 {
207     auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(requestUri);
208     auto uriHightemp = uriLocal + HIGH_TEMPERATURE;
209     if (inProcessUriMap.find(uriLocal) == inProcessUriMap.end()) {
210         return;
211     }
212 
213     std::map<std::string, AssetHandler*> assetHandlers = inProcessUriMap[uriLocal];
214     if (assetHandlers.find(requestId) == assetHandlers.end()) {
215         return;
216     }
217 
218     assetHandlers.erase(requestId);
219     if (!assetHandlers.empty()) {
220         inProcessUriMap[uriLocal] = assetHandlers;
221         return;
222     }
223 
224     inProcessUriMap.erase(uriLocal);
225 
226     if (multiStagesObserverMap.find(uriLocal) != multiStagesObserverMap.end()) {
227         UserFileClient::UnregisterObserverExt(Uri(uriLocal),
228             static_cast<std::shared_ptr<DataShare::DataShareObserver>>(multiStagesObserverMap[uriLocal]));
229     }
230     if (multiStagesObserverMap.find(uriHightemp) != multiStagesObserverMap.end()) {
231         UserFileClient::UnregisterObserverExt(Uri(uriHightemp),
232             static_cast<std::shared_ptr<DataShare::DataShareObserver>>(multiStagesObserverMap[uriHightemp]));
233     }
234     multiStagesObserverMap.erase(uriLocal);
235     multiStagesObserverMap.erase(uriHightemp);
236 }
237 
DeleteInProcessMapRecord(const std::string & requestUri,const std::string & requestId)238 static void DeleteInProcessMapRecord(const std::string &requestUri, const std::string &requestId)
239 {
240     DeleteRecordNoLock(requestUri, requestId);
241 }
242 
IsInProcessInMapRecord(const std::string & requestId,AssetHandler * & handler)243 static int32_t IsInProcessInMapRecord(const std::string &requestId, AssetHandler* &handler)
244 {
245     for (auto record : inProcessUriMap) {
246         if (record.second.find(requestId) != record.second.end()) {
247             handler = record.second[requestId];
248             return true;
249         }
250     }
251 
252     return false;
253 }
254 
InsertDataHandler(NotifyMode notifyMode,napi_env env,MediaAssetManagerAsyncContext * asyncContext)255 static AssetHandler* InsertDataHandler(NotifyMode notifyMode, napi_env env,
256     MediaAssetManagerAsyncContext *asyncContext)
257 {
258     napi_ref dataHandlerRef;
259     napi_threadsafe_function threadSafeFunc;
260     if (notifyMode == NotifyMode::FAST_NOTIFY) {
261         dataHandlerRef = asyncContext->dataHandlerRef;
262         asyncContext->dataHandlerRef = nullptr;
263         threadSafeFunc = asyncContext->onDataPreparedPtr;
264     } else {
265         dataHandlerRef = asyncContext->dataHandlerRef2;
266         asyncContext->dataHandlerRef2 = nullptr;
267         threadSafeFunc = asyncContext->onDataPreparedPtr2;
268     }
269     std::shared_ptr<NapiMediaAssetDataHandler> mediaAssetDataHandler = make_shared<NapiMediaAssetDataHandler>(
270         env, dataHandlerRef, asyncContext->returnDataType, asyncContext->photoUri, asyncContext->destUri,
271         asyncContext->sourceMode);
272     mediaAssetDataHandler->SetCompatibleMode(asyncContext->compatibleMode);
273     mediaAssetDataHandler->SetNotifyMode(notifyMode);
274     mediaAssetDataHandler->SetRequestId(asyncContext->requestId);
275     mediaAssetDataHandler->SetProgressHandlerRef(asyncContext->progressHandlerRef);
276     mediaAssetDataHandler->SetThreadsafeFunction(asyncContext->onProgressPtr);
277     AssetHandler *assetHandler = CreateAssetHandler(asyncContext->photoId, asyncContext->requestId,
278         asyncContext->photoUri, mediaAssetDataHandler, threadSafeFunc);
279     assetHandler->photoQuality = asyncContext->photoQuality;
280     assetHandler->needsExtraInfo = asyncContext->needsExtraInfo;
281     NAPI_INFO_LOG("Add %{public}d, %{public}s, %{public}s", notifyMode,
282         MediaFileUtils::DesensitizeUri(asyncContext->photoUri).c_str(), asyncContext->requestId.c_str());
283 
284     switch (notifyMode) {
285         case NotifyMode::FAST_NOTIFY: {
286             inProcessFastRequests.EnsureInsert(asyncContext->requestId, assetHandler);
287             break;
288         }
289         case NotifyMode::WAIT_FOR_HIGH_QUALITY: {
290             InsertInProcessMapRecord(asyncContext->photoUri, asyncContext->requestId, assetHandler);
291             break;
292         }
293         default:
294             break;
295     }
296 
297     return assetHandler;
298 }
299 
InsertProgressHandler(napi_env env,MediaAssetManagerAsyncContext * asyncContext)300 static ProgressHandler* InsertProgressHandler(napi_env env, MediaAssetManagerAsyncContext *asyncContext)
301 {
302     napi_ref dataHandlerRef;
303     napi_threadsafe_function threadSafeFunc;
304     dataHandlerRef = asyncContext->progressHandlerRef;
305     threadSafeFunc = asyncContext->onProgressPtr;
306     ProgressHandler *progressHandler = new ProgressHandler(env, threadSafeFunc, asyncContext->requestId,
307         dataHandlerRef);
308     MediaAssetManagerNapi::progressHandlerMap_.EnsureInsert(asyncContext->requestId, progressHandler);
309     NAPI_DEBUG_LOG("InsertProgressHandler");
310     return  progressHandler;
311 }
312 
DeleteDataHandler(NotifyMode notifyMode,const std::string & requestUri,const std::string & requestId)313 static void DeleteDataHandler(NotifyMode notifyMode, const std::string &requestUri, const std::string &requestId)
314 {
315     std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
316     auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(requestUri);
317     NAPI_INFO_LOG("Rmv %{public}d, %{public}s, %{public}s", notifyMode,
318         MediaFileUtils::DesensitizeUri(requestUri).c_str(), requestId.c_str());
319     if (notifyMode == NotifyMode::WAIT_FOR_HIGH_QUALITY) {
320         DeleteInProcessMapRecord(uriLocal, requestId);
321     }
322     inProcessFastRequests.Erase(requestId);
323 }
324 
QueryViaSandBox(int fileId,const string & photoUri,std::string & photoId,bool hasReadPermission,int32_t userId)325 static MultiStagesCapturePhotoStatus QueryViaSandBox(int fileId,
326     const string& photoUri, std::string &photoId, bool hasReadPermission, int32_t userId)
327 {
328     photoId = "";
329     DataShare::DataSharePredicates predicates;
330     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
331     std::vector<std::string> fetchColumn { PhotoColumn::PHOTO_QUALITY, PhotoColumn::PHOTO_ID};
332     string queryUri;
333     if (hasReadPermission) {
334         queryUri = PAH_QUERY_PHOTO;
335     } else {
336         queryUri = photoUri;
337         MediaFileUri::RemoveAllFragment(queryUri);
338     }
339     Uri uri(queryUri);
340     int errCode = 0;
341     OperationObject object = OperationObject::UNKNOWN_OBJECT;
342     if (MediaAssetRdbStore::GetInstance()->IsQueryAccessibleViaSandBox(uri, object, predicates) && userId == -1) {
343         shared_ptr<DataShare::DataShareResultSet> resultSet = MediaAssetRdbStore::GetInstance()->Query(
344             predicates, fetchColumn, object, errCode);
345         if (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK) {
346             NAPI_ERR_LOG("query resultSet is nullptr");
347             return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
348         }
349         int indexOfPhotoId = -1;
350         resultSet->GetColumnIndex(PhotoColumn::PHOTO_ID, indexOfPhotoId);
351         resultSet->GetString(indexOfPhotoId, photoId);
352 
353         int columnIndexQuality = -1;
354         resultSet->GetColumnIndex(PhotoColumn::PHOTO_QUALITY, columnIndexQuality);
355         int currentPhotoQuality = HIGH_QUALITY_IMAGE;
356         resultSet->GetInt(columnIndexQuality, currentPhotoQuality);
357         if (currentPhotoQuality == LOW_QUALITY_IMAGE) {
358             NAPI_INFO_LOG("query photo status : lowQuality");
359             return MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS;
360         }
361         NAPI_INFO_LOG("query photo status quality: %{public}d", currentPhotoQuality);
362         return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
363     } else {
364         return MultiStagesCapturePhotoStatus::QUERY_INNER_FAIL;
365     }
366 }
367 
QueryPhotoStatus(int fileId,const string & photoUri,std::string & photoId,bool hasReadPermission,int32_t userId)368 MultiStagesCapturePhotoStatus MediaAssetManagerNapi::QueryPhotoStatus(int fileId,
369     const string& photoUri, std::string &photoId, bool hasReadPermission, int32_t userId)
370 {
371     MultiStagesCapturePhotoStatus status = QueryViaSandBox(fileId, photoUri, photoId, hasReadPermission, userId);
372     if (status != MultiStagesCapturePhotoStatus::QUERY_INNER_FAIL) {
373         return status;
374     }
375     QueryPhotoReqBody reqBody;
376     reqBody.fileId = std::to_string(fileId);
377     QueryPhotoRespBody respBody;
378     std::unordered_map<std::string, std::string> headerMap {
379         {MediaColumn::MEDIA_ID, reqBody.fileId }, {URI_TYPE, TYPE_PHOTOS}};
380     int ret = IPC::UserDefineIPCClient().SetUserId(userId).SetHeader(headerMap).Call(
381         static_cast<uint32_t>(MediaLibraryBusinessCode::QUERY_PHOTO_STATUS), reqBody, respBody);
382     if (ret < 0) {
383         NAPI_ERR_LOG("ret = %{public}d", ret);
384         return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
385     }
386     photoId = respBody.photoId;
387     if (respBody.photoQuality == LOW_QUALITY_IMAGE) {
388         NAPI_INFO_LOG("query photo status : lowQuality");
389         return MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS;
390     }
391     NAPI_INFO_LOG("query photo status quality: %{public}d", respBody.photoQuality);
392     return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
393 }
394 
ProcessImage(const int fileId,const int deliveryMode)395 void MediaAssetManagerNapi::ProcessImage(const int fileId, const int deliveryMode)
396 {
397     std::string uriStr = PAH_PROCESS_IMAGE;
398     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
399     Uri uri(uriStr);
400     DataShare::DataSharePredicates predicates;
401     int errCode = 0;
402     std::vector<std::string> columns { std::to_string(fileId), std::to_string(deliveryMode) };
403     UserFileClient::Query(uri, predicates, columns, errCode);
404 }
405 
CancelProcessImage(const std::string & photoId)406 void MediaAssetManagerNapi::CancelProcessImage(const std::string &photoId)
407 {
408     std::string uriStr = PAH_CANCEL_PROCESS_IMAGE;
409     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
410     Uri uri(uriStr);
411     DataShare::DataSharePredicates predicates;
412     int errCode = 0;
413     std::vector<std::string> columns { photoId };
414     UserFileClient::Query(uri, predicates, columns, errCode);
415 }
416 
AddImage(const int fileId,DeliveryMode deliveryMode)417 void MediaAssetManagerNapi::AddImage(const int fileId, DeliveryMode deliveryMode)
418 {
419     Uri updateAssetUri(PAH_ADD_IMAGE);
420     DataShare::DataSharePredicates predicates;
421     DataShare::DataShareValuesBucket valuesBucket;
422     valuesBucket.Put(MediaColumn::MEDIA_ID, fileId);
423     valuesBucket.Put("deliveryMode", static_cast<int>(deliveryMode));
424     UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
425 }
426 
GetDeliveryMode(napi_env env,const napi_value arg,const string & propName,DeliveryMode & deliveryMode)427 napi_status GetDeliveryMode(napi_env env, const napi_value arg, const string &propName,
428     DeliveryMode& deliveryMode)
429 {
430     bool present = false;
431     napi_value property = nullptr;
432     int mode = -1;
433     CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present),
434         "Failed to check property name");
435     if (!present) {
436         NAPI_ERR_LOG("No delivery mode specified");
437         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "No delivery mode specified");
438         return napi_invalid_arg;
439     }
440     CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
441     CHECK_STATUS_RET(napi_get_value_int32(env, property, &mode), "Failed to parse deliveryMode argument value");
442 
443     // delivery mode's valid range is 0 - 2
444     if (mode < 0 || mode > 2) {
445         NAPI_ERR_LOG("delivery mode invalid argument ");
446         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "invalid delivery mode value");
447         return napi_invalid_arg;
448     }
449     deliveryMode = static_cast<DeliveryMode>(mode);
450     return napi_ok;
451 }
452 
GetSourceMode(napi_env env,const napi_value arg,const string & propName,SourceMode & sourceMode)453 napi_status GetSourceMode(napi_env env, const napi_value arg, const string &propName,
454     SourceMode& sourceMode)
455 {
456     bool present = false;
457     napi_value property = nullptr;
458     int mode = -1;
459     CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present), "Failed to check property name");
460     if (!present) {
461         // use default source mode
462         sourceMode = SourceMode::EDITED_MODE;
463         return napi_ok;
464     } else if (!MediaLibraryNapiUtils::IsSystemApp()) {
465         NAPI_ERR_LOG("Source mode is only available to system apps");
466         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Source mode is only available to system apps");
467         return napi_invalid_arg;
468     }
469     CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
470     CHECK_STATUS_RET(napi_get_value_int32(env, property, &mode), "Failed to parse sourceMode argument value");
471 
472     // source mode's valid range is 0 - 1
473     if (mode < 0 || mode > 1) {
474         NAPI_ERR_LOG("source mode invalid");
475         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "invalid source mode value");
476         return napi_invalid_arg;
477     }
478     sourceMode = static_cast<SourceMode>(mode);
479     return napi_ok;
480 }
481 
ParseArgGetRequestOption(napi_env env,napi_value arg,DeliveryMode & deliveryMode,SourceMode & sourceMode)482 napi_status ParseArgGetRequestOption(napi_env env, napi_value arg, DeliveryMode &deliveryMode, SourceMode &sourceMode)
483 {
484     CHECK_STATUS_RET(GetDeliveryMode(env, arg, "deliveryMode", deliveryMode), "Failed to parse deliveryMode");
485     CHECK_STATUS_RET(GetSourceMode(env, arg, "sourceMode", sourceMode), "Failed to parse sourceMode");
486     return napi_ok;
487 }
488 
GetCompatibleMode(napi_env env,const napi_value arg,const string & propName,CompatibleMode & compatibleMode)489 napi_status GetCompatibleMode(napi_env env, const napi_value arg, const string &propName,
490     CompatibleMode& compatibleMode)
491 {
492     bool present = false;
493     napi_value property = nullptr;
494     int mode = static_cast<int>(CompatibleMode::ORIGINAL_FORMAT_MODE);
495     CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present), "Failed to check property name");
496     if (!present) {
497         NAPI_INFO_LOG("compatible mode is null");
498         compatibleMode = CompatibleMode::ORIGINAL_FORMAT_MODE;
499         return napi_ok;
500     }
501     CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
502     CHECK_STATUS_RET(napi_get_value_int32(env, property, &mode), "Failed to parse compatiblemode argument value");
503 
504     if (static_cast<CompatibleMode>(mode) < CompatibleMode::ORIGINAL_FORMAT_MODE ||
505         static_cast<CompatibleMode>(mode) > CompatibleMode::COMPATIBLE_FORMAT_MODE) {
506         NAPI_ERR_LOG("delivery mode invalid argument ");
507         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "invalid compatible mode value");
508         return napi_invalid_arg;
509     }
510 #if !defined(USE_VIDEO_PROCESSING_ENGINE) || !defined(USE_VIDEO_PROCESSING_ENGINE_EXT)
511     if (static_cast<CompatibleMode>(mode) == CompatibleMode::COMPATIBLE_FORMAT_MODE) {
512         NAPI_ERR_LOG("current environment not support transcoder");
513         NapiError::ThrowError(env, OHOS_NOT_SUPPORT_TRANSCODER_CODE, "not support transcoder");
514         return napi_invalid_arg;
515     }
516 #endif
517     compatibleMode = static_cast<CompatibleMode>(mode);
518     return napi_ok;
519 }
520 
GetMediaAssetProgressHandler(napi_env env,const napi_value arg,napi_value & mediaAssetProgressHandler,const string & propName)521 napi_status GetMediaAssetProgressHandler(napi_env env, const napi_value arg, napi_value& mediaAssetProgressHandler,
522     const string &propName)
523 {
524     CHECK_COND_LOG_THROW_RETURN_RET(env, arg != nullptr, OHOS_INVALID_PARAM_CODE,
525         "MediaAssetProgressHandler invalid argument", napi_invalid_arg, "MediaAssetProgressHandler  is nullptr");
526     bool present = false;
527     CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present), "Failed to check property name");
528     if (!present) {
529         NAPI_INFO_LOG("MediaAssetProgressHandler is null");
530         mediaAssetProgressHandler = nullptr;
531         return napi_ok;
532     }
533     napi_value progressHandler;
534     napi_status status = napi_get_named_property(env, arg, "mediaAssetProgressHandler", &progressHandler);
535     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE,
536         "failed to get mediaAssetProgressHandler ", napi_invalid_arg,
537         "failed to get mediaAssetProgressHandler, napi status: %{public}d", static_cast<int>(status));
538     napi_valuetype valueType;
539     status = napi_typeof(env, progressHandler, &valueType);
540     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid progress handler",
541         napi_invalid_arg, "failed to get type of progress handler, napi status: %{public}d", static_cast<int>(status));
542     CHECK_COND_LOG_THROW_RETURN_RET(env, valueType == napi_object, OHOS_INVALID_PARAM_CODE,
543         "progress handler not an object", napi_invalid_arg, "progress handler not an object");
544 
545     napi_value onProgress;
546     status = napi_get_named_property(env, progressHandler, ON_PROGRESS_FUNC, &onProgress);
547     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE,
548         "unable to get onProgress function", napi_invalid_arg,
549         "failed to get onProgress function, napi status: %{public}d", static_cast<int>(status));
550 
551     status = napi_typeof(env, onProgress, &valueType);
552     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onProgress",
553         napi_invalid_arg, "failed to get type of onProgress, napi status: %{public}d", static_cast<int>(status));
554     CHECK_COND_LOG_THROW_RETURN_RET(env, valueType == napi_function, OHOS_INVALID_PARAM_CODE,
555         "onProgress not a function", napi_invalid_arg, "onProgress not a function");
556     mediaAssetProgressHandler = progressHandler;
557     return napi_ok;
558 }
559 
ParseArgGetRequestOptionMore(napi_env env,napi_value arg,CompatibleMode & compatibleMode,napi_value & mediaAssetProgressHandler)560 napi_status ParseArgGetRequestOptionMore(napi_env env, napi_value arg, CompatibleMode &compatibleMode,
561     napi_value &mediaAssetProgressHandler)
562 {
563     NAPI_INFO_LOG("ParseArgGetRequestOptionMore start");
564     CHECK_STATUS_RET(GetCompatibleMode(env, arg, "compatibleMode", compatibleMode), "Failed to parse compatibleMode");
565     if (GetMediaAssetProgressHandler(env, arg, mediaAssetProgressHandler, "mediaAssetProgressHandler") != napi_ok) {
566         NAPI_ERR_LOG("requestMedia GetMediaAssetProgressHandler error");
567         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia GetMediaAssetProgressHandler error");
568         return napi_invalid_arg;
569     }
570     return napi_ok;
571 }
572 
ParseArgGetPhotoAsset(napi_env env,napi_value arg,int & fileId,std::string & uri,std::string & displayName)573 napi_status ParseArgGetPhotoAsset(napi_env env, napi_value arg, int &fileId, std::string &uri,
574     std::string &displayName)
575 {
576     if (arg == nullptr) {
577         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "ParseArgGetPhotoAsset failed to get photoAsset");
578         return napi_invalid_arg;
579     }
580     FileAssetNapi *obj = nullptr;
581     napi_unwrap(env, arg, reinterpret_cast<void**>(&obj));
582     if (obj == nullptr) {
583         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to get asset napi object");
584         return napi_invalid_arg;
585     }
586     fileId = obj->GetFileId();
587     uri = obj->GetFileUri();
588     displayName = obj->GetFileDisplayName();
589     return napi_ok;
590 }
591 
ParseArgGetPhotoAsset(napi_env env,napi_value arg,unique_ptr<MediaAssetManagerAsyncContext> & asyncContext)592 napi_status ParseArgGetPhotoAsset(napi_env env, napi_value arg, unique_ptr<MediaAssetManagerAsyncContext> &asyncContext)
593 {
594     if (arg == nullptr) {
595         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "ParseArgGetPhotoAsset failed to get photoAsset");
596         return napi_invalid_arg;
597     }
598     FileAssetNapi *obj = nullptr;
599     napi_unwrap(env, arg, reinterpret_cast<void**>(&obj));
600     if (obj == nullptr) {
601         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to get asset napi object");
602         return napi_invalid_arg;
603     }
604     asyncContext->fileId = obj->GetFileId();
605     asyncContext->photoUri = obj->GetFileUri();
606     asyncContext->displayName = obj->GetFileDisplayName();
607     asyncContext->userId = obj->GetFileAssetInstance()->GetUserId();
608     return napi_ok;
609 }
610 
ParseArgGetDestPath(napi_env env,napi_value arg,std::string & destPath)611 napi_status ParseArgGetDestPath(napi_env env, napi_value arg, std::string &destPath)
612 {
613     if (arg == nullptr) {
614         NAPI_ERR_LOG("destPath arg is invalid");
615         return napi_invalid_arg;
616     }
617     napi_get_print_string(env, arg, destPath);
618     if (destPath.empty()) {
619         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to get destPath napi object");
620         return napi_invalid_arg;
621     }
622     return napi_ok;
623 }
624 
ParseArgGetEfficientImageDataHandler(napi_env env,napi_value arg,napi_value & dataHandler,bool & needsExtraInfo)625 napi_status ParseArgGetEfficientImageDataHandler(napi_env env, napi_value arg, napi_value& dataHandler,
626     bool& needsExtraInfo)
627 {
628     CHECK_COND_LOG_THROW_RETURN_RET(env, arg != nullptr, OHOS_INVALID_PARAM_CODE, "efficient handler invalid argument",
629         napi_invalid_arg, "efficient data handler is nullptr");
630 
631     napi_valuetype valueType;
632     napi_status status = napi_typeof(env, arg, &valueType);
633     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid efficient data handler",
634         napi_invalid_arg, "failed to get type of efficient data handler, napi status: %{public}d",
635         static_cast<int>(status));
636     CHECK_COND_LOG_THROW_RETURN_RET(env, valueType == napi_object, OHOS_INVALID_PARAM_CODE,
637         "efficient data handler not a object", napi_invalid_arg, "efficient data handler not a object");
638 
639     dataHandler = arg;
640 
641     napi_value onDataPrepared;
642     status = napi_get_named_property(env, arg, ON_DATA_PREPARED_FUNC, &onDataPrepared);
643     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE,
644         "unable to get onDataPrepared function", napi_invalid_arg,
645         "failed to get type of efficient data handler, napi status: %{public}d", static_cast<int>(status));
646     status = napi_typeof(env, onDataPrepared, &valueType);
647     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onDataPrepared",
648         napi_invalid_arg, "failed to get type of onDataPrepared, napi status: %{public}d", static_cast<int>(status));
649     CHECK_COND_LOG_THROW_RETURN_RET(env, valueType == napi_function, OHOS_INVALID_PARAM_CODE,
650         "onDataPrepared not a function", napi_invalid_arg, "onDataPrepared not a function");
651 
652     napi_value paramCountNapi;
653     status = napi_get_named_property(env, onDataPrepared, "length", &paramCountNapi);
654     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onDataPrepared",
655         napi_invalid_arg, "get onDataPrepared arg count fail, napi status: %{public}d", static_cast<int>(status));
656     int32_t paramCount = -1;
657     constexpr int paramCountMin = 2;
658     constexpr int paramCountMax = 3;
659     status = napi_get_value_int32(env, paramCountNapi, &paramCount);
660     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onDataPrepared",
661         napi_invalid_arg, "get onDataPrepared arg count value fail, napi status: %{public}d", static_cast<int>(status));
662     CHECK_COND_LOG_THROW_RETURN_RET(env, (paramCount >= paramCountMin && paramCount <= paramCountMax),
663         OHOS_INVALID_PARAM_CODE, "onDataPrepared has wrong number of parameters",
664         napi_invalid_arg, "onDataPrepared has wrong number of parameters");
665 
666     if (paramCount == ARGS_THREE) {
667         needsExtraInfo = true;
668     }
669     return napi_ok;
670 }
671 
ParseArgGetDataHandler(napi_env env,napi_value arg,napi_value & dataHandler,bool & needsExtraInfo)672 napi_status ParseArgGetDataHandler(napi_env env, napi_value arg, napi_value& dataHandler, bool& needsExtraInfo)
673 {
674     CHECK_COND_LOG_THROW_RETURN_RET(env, arg != nullptr, OHOS_INVALID_PARAM_CODE, "data handler invalid argument",
675         napi_invalid_arg, "data handler is nullptr");
676 
677     napi_valuetype valueType;
678     napi_status status = napi_typeof(env, arg, &valueType);
679     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid data handler",
680         napi_invalid_arg, "failed to get type of data handler, napi status: %{public}d", static_cast<int>(status));
681     CHECK_COND_LOG_THROW_RETURN_RET(env, valueType == napi_object, OHOS_INVALID_PARAM_CODE,
682         "data handler not a object", napi_invalid_arg, "data handler not a object");
683 
684     dataHandler = arg;
685 
686     napi_value onDataPrepared;
687     status = napi_get_named_property(env, arg, ON_DATA_PREPARED_FUNC, &onDataPrepared);
688     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE,
689         "unable to get onDataPrepared function", napi_invalid_arg,
690         "failed to get type of data handler, napi status: %{public}d", static_cast<int>(status));
691     status = napi_typeof(env, onDataPrepared, &valueType);
692     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onDataPrepared",
693         napi_invalid_arg, "failed to get type of onDataPrepared, napi status: %{public}d", static_cast<int>(status));
694     CHECK_COND_LOG_THROW_RETURN_RET(env, valueType == napi_function, OHOS_INVALID_PARAM_CODE,
695         "onDataPrepared not a function", napi_invalid_arg, "onDataPrepared not a function");
696 
697     napi_value paramCountNapi;
698     status = napi_get_named_property(env, onDataPrepared, "length", &paramCountNapi);
699     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onDataPrepared",
700         napi_invalid_arg, "get onDataPrepared arg count fail, napi status: %{public}d", static_cast<int>(status));
701     int32_t paramCount = -1;
702     constexpr int paramCountMin = 1;
703     constexpr int paramCountMax = 2;
704     status = napi_get_value_int32(env, paramCountNapi, &paramCount);
705     CHECK_COND_LOG_THROW_RETURN_RET(env, status == napi_ok, OHOS_INVALID_PARAM_CODE, "invalid onDataPrepared",
706         napi_invalid_arg, "get onDataPrepared arg count value fail, napi status: %{public}d", static_cast<int>(status));
707     CHECK_COND_LOG_THROW_RETURN_RET(env, (paramCount >= paramCountMin && paramCount <= paramCountMax),
708         OHOS_INVALID_PARAM_CODE, "onDataPrepared has wrong number of parameters",
709         napi_invalid_arg, "onDataPrepared has wrong number of parameters");
710 
711     if (paramCount == ARGS_TWO) {
712         needsExtraInfo = true;
713     }
714     return napi_ok;
715 }
716 
GenerateRequestId()717 static std::string GenerateRequestId()
718 {
719     uuid_t uuid;
720     uuid_generate(uuid);
721     char str[UUID_STR_LENGTH] = {};
722     uuid_unparse(uuid, str);
723     return str;
724 }
725 
RegisterTaskObserver(napi_env env,MediaAssetManagerAsyncContext * asyncContext)726 void MediaAssetManagerNapi::RegisterTaskObserver(napi_env env, MediaAssetManagerAsyncContext *asyncContext)
727 {
728     auto dataObserver = std::make_shared<MultiStagesTaskObserver>(asyncContext->fileId);
729     auto uriLocal = MediaFileUtils::GetUriWithoutDisplayname(asyncContext->photoUri);
730     auto uriHightemp = uriLocal + HIGH_TEMPERATURE;
731     NAPI_INFO_LOG("MultistagesCapture, uri: %{public}s, %{public}s, uriHighTemp: %{public}s.",
732         asyncContext->photoUri.c_str(), uriLocal.c_str(), uriHightemp.c_str());
733     Uri uri(asyncContext->photoUri);
734     std::unique_lock<std::mutex> registerLock(registerTaskLock);
735     if (multiStagesObserverMap.find(uriLocal) == multiStagesObserverMap.end()) {
736         UserFileClient::RegisterObserverExt(Uri(uriLocal),
737             static_cast<std::shared_ptr<DataShare::DataShareObserver>>(dataObserver), false);
738         multiStagesObserverMap.insert(std::make_pair(uriLocal, dataObserver));
739     }
740     if (multiStagesObserverMap.find(uriHightemp) == multiStagesObserverMap.end()) {
741         UserFileClient::RegisterObserverExt(Uri(uriHightemp),
742             static_cast<std::shared_ptr<DataShare::DataShareObserver>>(dataObserver), false);
743         multiStagesObserverMap.insert(std::make_pair(uriHightemp, dataObserver));
744     }
745     registerLock.unlock();
746 
747     InsertDataHandler(NotifyMode::WAIT_FOR_HIGH_QUALITY, env, asyncContext);
748 
749     MediaAssetManagerNapi::ProcessImage(asyncContext->fileId, static_cast<int32_t>(asyncContext->deliveryMode));
750 }
751 
ParseRequestMediaArgs(napi_env env,napi_callback_info info,unique_ptr<MediaAssetManagerAsyncContext> & asyncContext)752 napi_status MediaAssetManagerNapi::ParseRequestMediaArgs(napi_env env, napi_callback_info info,
753     unique_ptr<MediaAssetManagerAsyncContext> &asyncContext)
754 {
755     napi_value thisVar = nullptr;
756     GET_JS_ARGS(env, info, asyncContext->argc, asyncContext->argv, thisVar);
757     if (asyncContext->argc != ARGS_FOUR && asyncContext->argc != ARGS_FIVE) {
758         NAPI_ERR_LOG("requestMedia argc error");
759         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia argc invalid");
760         return napi_invalid_arg;
761     }
762     if (ParseArgGetPhotoAsset(env, asyncContext->argv[PARAM1], asyncContext) != napi_ok) {
763         NAPI_ERR_LOG("requestMedia ParseArgGetPhotoAsset error");
764         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetPhotoAsset error");
765         return napi_invalid_arg;
766     }
767     if (ParseArgGetRequestOption(env, asyncContext->argv[PARAM2], asyncContext->deliveryMode,
768         asyncContext->sourceMode) != napi_ok) {
769         NAPI_ERR_LOG("requestMedia ParseArgGetRequestOption error");
770         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetRequestOption error");
771         return napi_invalid_arg;
772     }
773     if (ParseArgGetRequestOptionMore(env, asyncContext->argv[PARAM2], asyncContext->compatibleMode,
774         asyncContext->mediaAssetProgressHandler) != napi_ok) {
775         NAPI_ERR_LOG("requestMedia ParseArgGetRequestOptionMore error");
776         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetRequestOptionMore error");
777         return napi_invalid_arg;
778     }
779     if (asyncContext->argc == ARGS_FOUR) {
780         if (ParseArgGetDataHandler(env, asyncContext->argv[PARAM3], asyncContext->dataHandler,
781             asyncContext->needsExtraInfo) != napi_ok) {
782             NAPI_ERR_LOG("requestMedia ParseArgGetDataHandler error");
783             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetDataHandler error");
784             return napi_invalid_arg;
785         }
786     } else if (asyncContext->argc == ARGS_FIVE) {
787         if (ParseArgGetDestPath(env, asyncContext->argv[PARAM3], asyncContext->destUri) != napi_ok) {
788             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetDestPath error");
789             return napi_invalid_arg;
790         }
791         if (ParseArgGetDataHandler(env, asyncContext->argv[PARAM4], asyncContext->dataHandler,
792             asyncContext->needsExtraInfo) != napi_ok) {
793             NAPI_ERR_LOG("requestMedia ParseArgGetDataHandler error");
794             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetDataHandler error");
795             return napi_invalid_arg;
796         }
797     }
798     asyncContext->hasReadPermission = HasReadPermission();
799     return napi_ok;
800 }
801 
ParseEfficentRequestMediaArgs(napi_env env,napi_callback_info info,unique_ptr<MediaAssetManagerAsyncContext> & asyncContext)802 napi_status MediaAssetManagerNapi::ParseEfficentRequestMediaArgs(napi_env env, napi_callback_info info,
803     unique_ptr<MediaAssetManagerAsyncContext> &asyncContext)
804 {
805     napi_value thisVar = nullptr;
806     GET_JS_ARGS(env, info, asyncContext->argc, asyncContext->argv, thisVar);
807     if (asyncContext->argc != ARGS_FOUR && asyncContext->argc != ARGS_FIVE) {
808         NAPI_ERR_LOG("requestMedia argc error");
809         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia argc invalid");
810         return napi_invalid_arg;
811     }
812 
813     if (ParseArgGetPhotoAsset(env, asyncContext->argv[PARAM1], asyncContext) != napi_ok) {
814         NAPI_ERR_LOG("requestMedia ParseArgGetPhotoAsset error");
815         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetPhotoAsset error");
816         return napi_invalid_arg;
817     }
818     if (ParseArgGetRequestOption(env, asyncContext->argv[PARAM2], asyncContext->deliveryMode,
819         asyncContext->sourceMode) != napi_ok) {
820         NAPI_ERR_LOG("requestMedia ParseArgGetRequestOption error");
821         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetRequestOption error");
822         return napi_invalid_arg;
823     }
824     if (asyncContext->argc == ARGS_FOUR) {
825         if (ParseArgGetEfficientImageDataHandler(env, asyncContext->argv[PARAM3], asyncContext->dataHandler,
826             asyncContext->needsExtraInfo) != napi_ok) {
827             NAPI_ERR_LOG("requestMedia ParseArgGetEfficientImageDataHandler error");
828             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE,
829                 "requestMedia ParseArgGetEfficientImageDataHandler error");
830             return napi_invalid_arg;
831         }
832     } else if (asyncContext->argc == ARGS_FIVE) {
833         if (ParseArgGetDestPath(env, asyncContext->argv[PARAM3], asyncContext->destUri) != napi_ok) {
834             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetDestPath error");
835             return napi_invalid_arg;
836         }
837         if (ParseArgGetEfficientImageDataHandler(env, asyncContext->argv[PARAM4], asyncContext->dataHandler,
838             asyncContext->needsExtraInfo) != napi_ok) {
839             NAPI_ERR_LOG("requestMedia ParseArgGetEfficientImageDataHandler error");
840             NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE,
841                 "requestMedia ParseArgGetEfficientImageDataHandler error");
842             return napi_invalid_arg;
843         }
844     }
845     asyncContext->hasReadPermission = HasReadPermission();
846     return napi_ok;
847 }
848 
InitUserFileClient(napi_env env,napi_callback_info info,const int32_t userId)849 bool MediaAssetManagerNapi::InitUserFileClient(napi_env env, napi_callback_info info, const int32_t userId)
850 {
851     if (UserFileClient::IsValid(userId)) {
852         return true;
853     }
854 
855     std::unique_lock<std::mutex> helperLock(MediaLibraryNapi::sUserFileClientMutex_);
856     if (!UserFileClient::IsValid(userId)) {
857         UserFileClient::Init(env, info, userId);
858     }
859     helperLock.unlock();
860     return UserFileClient::IsValid(userId);
861 }
862 
GetPhotoSubtype(napi_env env,napi_value photoAssetArg)863 static int32_t GetPhotoSubtype(napi_env env, napi_value photoAssetArg)
864 {
865     if (photoAssetArg == nullptr) {
866         NAPI_ERR_LOG(
867             "Dfx adaptation to moving photo collector error: failed to get photo subtype, photo asset is null");
868         return -1;
869     }
870     FileAssetNapi *obj = nullptr;
871     napi_unwrap(env, photoAssetArg, reinterpret_cast<void**>(&obj));
872     if (obj == nullptr) {
873         NAPI_ERR_LOG("Dfx adaptation to moving photo collector error: failed to unwrap file asset");
874         return -1;
875     }
876     return obj->GetFileAssetInstance()->GetPhotoSubType();
877 }
878 
JSRequestImageData(napi_env env,napi_callback_info info)879 napi_value MediaAssetManagerNapi::JSRequestImageData(napi_env env, napi_callback_info info)
880 {
881     NAPI_INFO_LOG("Begin JSRequestImageData");
882     if (env == nullptr || info == nullptr) {
883         NAPI_ERR_LOG("JSRequestImageData js arg invalid");
884         NapiError::ThrowError(env, JS_INNER_FAIL, "JSRequestImageData js arg invalid");
885         return nullptr;
886     }
887 
888     MediaLibraryTracer tracer;
889     tracer.Start("JSRequestImageData");
890     unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
891     asyncContext->returnDataType = ReturnDataType::TYPE_ARRAY_BUFFER;
892     if (ParseRequestMediaArgs(env, info, asyncContext) != napi_ok) {
893         NAPI_ERR_LOG("failed to parse requestImagedata args");
894         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to parse requestImagedata args");
895         return nullptr;
896     }
897     if (!InitUserFileClient(env, info, asyncContext->userId)) {
898         NAPI_ERR_LOG("JSRequestEfficientIImage init user file client failed");
899         NapiError::ThrowError(env, JS_INNER_FAIL, "handler is invalid");
900         return nullptr;
901     }
902     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef) != napi_ok
903             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr) != napi_ok) {
904         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
905         return nullptr;
906     }
907     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef2) != napi_ok
908             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr2) != napi_ok) {
909         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
910         return nullptr;
911     }
912 
913     asyncContext->requestId = GenerateRequestId();
914     asyncContext->subType = static_cast<PhotoSubType>(GetPhotoSubtype(env, asyncContext->argv[PARAM1]));
915 
916     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRequestImageData", JSRequestExecute,
917         JSRequestComplete);
918 }
919 
JSRequestImage(napi_env env,napi_callback_info info)920 napi_value MediaAssetManagerNapi::JSRequestImage(napi_env env, napi_callback_info info)
921 {
922     NAPI_INFO_LOG("Begin JSRequestImage");
923     if (env == nullptr || info == nullptr) {
924         NAPI_ERR_LOG("JSRequestImage js arg invalid");
925         NapiError::ThrowError(env, JS_INNER_FAIL, "JSRequestImage js arg invalid");
926         return nullptr;
927     }
928 
929     MediaLibraryTracer tracer;
930     tracer.Start("JSRequestImage");
931 
932     unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
933     asyncContext->returnDataType = ReturnDataType::TYPE_IMAGE_SOURCE;
934     if (ParseRequestMediaArgs(env, info, asyncContext) != napi_ok) {
935         NAPI_ERR_LOG("failed to parse requestImage args");
936         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to parse requestImage args");
937         return nullptr;
938     }
939     if (!InitUserFileClient(env, info, asyncContext->userId)) {
940         NAPI_ERR_LOG("JSRequestImage init user file client failed");
941         NapiError::ThrowError(env, JS_INNER_FAIL, "handler is invalid");
942         return nullptr;
943     }
944     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef) != napi_ok
945             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr) != napi_ok) {
946         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
947         return nullptr;
948     }
949     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef2) != napi_ok
950             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr2) != napi_ok) {
951         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
952         return nullptr;
953     }
954 
955     asyncContext->requestId = GenerateRequestId();
956     asyncContext->subType = static_cast<PhotoSubType>(GetPhotoSubtype(env, asyncContext->argv[PARAM1]));
957 
958     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRequestImage", JSRequestExecute,
959         JSRequestComplete);
960 }
961 
JSRequestEfficientIImage(napi_env env,napi_callback_info info)962 napi_value MediaAssetManagerNapi::JSRequestEfficientIImage(napi_env env, napi_callback_info info)
963 {
964     NAPI_DEBUG_LOG("JSRequestEfficientIImage");
965     if (env == nullptr || info == nullptr) {
966         NAPI_ERR_LOG("JSRequestEfficientIImage js arg invalid");
967         NapiError::ThrowError(env, JS_INNER_FAIL, "JSRequestEfficientIImage js arg invalid");
968         return nullptr;
969     }
970 
971     MediaLibraryTracer tracer;
972     tracer.Start("JSRequestEfficientIImage");
973 
974     unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
975     asyncContext->returnDataType = ReturnDataType::TYPE_PICTURE;
976     if (ParseEfficentRequestMediaArgs(env, info, asyncContext) != napi_ok) {
977         NAPI_ERR_LOG("failed to parse JSRequestEfficientIImage args");
978         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to parse JSRequestEfficientIImage args");
979         return nullptr;
980     }
981     if (!InitUserFileClient(env, info, asyncContext->userId)) {
982         NAPI_ERR_LOG("JSRequestEfficientIImage init user file client failed");
983         NapiError::ThrowError(env, JS_INNER_FAIL, "handler is invalid");
984         return nullptr;
985     }
986     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef) != napi_ok
987             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr) != napi_ok) {
988         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
989         return nullptr;
990     }
991     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef2) != napi_ok
992             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr2) != napi_ok) {
993         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
994         return nullptr;
995     }
996 
997     asyncContext->requestId = GenerateRequestId();
998     asyncContext->subType = static_cast<PhotoSubType>(GetPhotoSubtype(env, asyncContext->argv[PARAM1]));
999 
1000     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRequestEfficientIImage", JSRequestExecute,
1001         JSRequestComplete);
1002 }
1003 
ReleaseSafeFunc(napi_threadsafe_function & threadSafeFunc)1004 void MediaAssetManagerNapi::ReleaseSafeFunc(napi_threadsafe_function &threadSafeFunc)
1005 {
1006     if (threadSafeFunc == nullptr) {
1007         return;
1008     }
1009     napi_release_threadsafe_function(threadSafeFunc, napi_tsfn_release);
1010     threadSafeFunc = nullptr;
1011 }
1012 
CreateOnProgressHandlerInfo(napi_env env,unique_ptr<MediaAssetManagerAsyncContext> & asyncContext)1013 bool MediaAssetManagerNapi::CreateOnProgressHandlerInfo(napi_env env,
1014     unique_ptr<MediaAssetManagerAsyncContext> &asyncContext)
1015 {
1016     if (asyncContext->compatibleMode != CompatibleMode::COMPATIBLE_FORMAT_MODE) {
1017         return true;
1018     }
1019     if (asyncContext->mediaAssetProgressHandler == nullptr) {
1020         if (CreateOnProgressThreadSafeFunc(env, asyncContext, asyncContext->onProgressPtr) != napi_ok) {
1021             NAPI_ERR_LOG("CreateOnProgressThreadSafeFunc failed");
1022             return false;
1023         }
1024         return true;
1025     }
1026     if (CreateProgressHandlerRef(env, asyncContext, asyncContext->progressHandlerRef) != napi_ok ||
1027         CreateOnProgressThreadSafeFunc(env, asyncContext, asyncContext->onProgressPtr) != napi_ok) {
1028         NAPI_ERR_LOG("CreateProgressHandlerRef or CreateOnProgressThreadSafeFunc failed");
1029         return false;
1030     }
1031     return true;
1032 }
1033 
JSRequestVideoFile(napi_env env,napi_callback_info info)1034 napi_value MediaAssetManagerNapi::JSRequestVideoFile(napi_env env, napi_callback_info info)
1035 {
1036     if (env == nullptr || info == nullptr) {
1037         NAPI_ERR_LOG("JSRequestVideoFile js arg invalid");
1038         NapiError::ThrowError(env, JS_INNER_FAIL, "JSRequestVideoFile js arg invalid");
1039         return nullptr;
1040     }
1041     MediaLibraryTracer tracer;
1042     tracer.Start("JSRequestVideoFile");
1043 
1044     unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
1045     asyncContext->returnDataType = ReturnDataType::TYPE_TARGET_PATH;
1046     if (ParseRequestMediaArgs(env, info, asyncContext) != napi_ok) {
1047         NAPI_ERR_LOG("failed to parse requestVideo args");
1048         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to parse requestVideo args");
1049         return nullptr;
1050     }
1051     if (!InitUserFileClient(env, info, asyncContext->userId)) {
1052         NAPI_ERR_LOG("JSRequestEfficientIImage init user file client failed");
1053         NapiError::ThrowError(env, JS_INNER_FAIL, "handler is invalid");
1054         return nullptr;
1055     }
1056     if (asyncContext->photoUri.length() > MAX_URI_SIZE || asyncContext->destUri.length() > MAX_URI_SIZE) {
1057         NAPI_ERR_LOG("request video file uri lens out of limit photoUri lens: %{public}zu, destUri lens: %{public}zu",
1058             asyncContext->photoUri.length(), asyncContext->destUri.length());
1059         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "request video file uri lens out of limit");
1060         return nullptr;
1061     }
1062     if (MediaFileUtils::GetMediaType(asyncContext->displayName) != MEDIA_TYPE_VIDEO ||
1063         MediaFileUtils::GetMediaType(MediaFileUtils::GetFileName(asyncContext->destUri)) != MEDIA_TYPE_VIDEO) {
1064         NAPI_ERR_LOG("request video file type invalid");
1065         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "request video file type invalid");
1066         return nullptr;
1067     }
1068     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef) != napi_ok
1069             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr) != napi_ok) {
1070         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
1071         return nullptr;
1072     }
1073     if (!CreateOnProgressHandlerInfo(env, asyncContext)) {
1074         NAPI_ERR_LOG("CreateOnProgressHandlerInfo failed");
1075         return nullptr;
1076     }
1077 
1078     asyncContext->requestId = GenerateRequestId();
1079     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRequestVideoFile",
1080         JSRequestVideoFileExecute, JSRequestComplete);
1081 }
1082 
OnHandleRequestImage(napi_env env,MediaAssetManagerAsyncContext * asyncContext)1083 void MediaAssetManagerNapi::OnHandleRequestImage(napi_env env, MediaAssetManagerAsyncContext *asyncContext)
1084 {
1085     CHECK_NULL_PTR_RETURN_VOID(asyncContext, "asyncContext is nullptr");
1086     NAPI_INFO_LOG("OnHandleRequestImage mode: %{public}d.", static_cast<int32_t>(asyncContext->deliveryMode));
1087     MultiStagesCapturePhotoStatus status = MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
1088     switch (asyncContext->deliveryMode) {
1089         case DeliveryMode::FAST:
1090             if (asyncContext->needsExtraInfo) {
1091                 asyncContext->photoQuality =
1092                     MediaAssetManagerNapi::QueryPhotoStatus(asyncContext->fileId, asyncContext->photoUri,
1093                     asyncContext->photoId, asyncContext->hasReadPermission, asyncContext->userId);
1094             }
1095             MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(env, asyncContext);
1096             ReleaseSafeFunc(asyncContext->onDataPreparedPtr2);
1097             break;
1098         case DeliveryMode::HIGH_QUALITY:
1099             status = MediaAssetManagerNapi::QueryPhotoStatus(asyncContext->fileId,
1100                 asyncContext->photoUri, asyncContext->photoId, asyncContext->hasReadPermission, asyncContext->userId);
1101             asyncContext->photoQuality = status;
1102             if (status == MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) {
1103                 MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(env, asyncContext);
1104                 ReleaseSafeFunc(asyncContext->onDataPreparedPtr2);
1105             } else {
1106                 RegisterTaskObserver(env, asyncContext);
1107                 ReleaseSafeFunc(asyncContext->onDataPreparedPtr);
1108             }
1109             break;
1110         case DeliveryMode::BALANCED_MODE:
1111             status = MediaAssetManagerNapi::QueryPhotoStatus(asyncContext->fileId,
1112                 asyncContext->photoUri, asyncContext->photoId, asyncContext->hasReadPermission, asyncContext->userId);
1113             asyncContext->photoQuality = status;
1114             MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(env, asyncContext);
1115             if (status == MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS) {
1116                 RegisterTaskObserver(env, asyncContext);
1117             } else {
1118                 ReleaseSafeFunc(asyncContext->onDataPreparedPtr2);
1119             }
1120             break;
1121         default: {
1122             NAPI_ERR_LOG("invalid delivery mode");
1123             return;
1124         }
1125     }
1126 }
1127 
OnHandleRequestVideo(napi_env env,MediaAssetManagerAsyncContext * asyncContext)1128 void MediaAssetManagerNapi::OnHandleRequestVideo(napi_env env, MediaAssetManagerAsyncContext *asyncContext)
1129 {
1130     switch (asyncContext->deliveryMode) {
1131         case DeliveryMode::FAST:
1132             MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(env, asyncContext);
1133             break;
1134         case DeliveryMode::HIGH_QUALITY:
1135             MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(env, asyncContext);
1136             break;
1137         case DeliveryMode::BALANCED_MODE:
1138             MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(env, asyncContext);
1139             break;
1140         default: {
1141             NAPI_ERR_LOG("invalid delivery mode");
1142             return;
1143         }
1144     }
1145 }
1146 
NotifyDataPreparedWithoutRegister(napi_env env,MediaAssetManagerAsyncContext * asyncContext)1147 void MediaAssetManagerNapi::NotifyDataPreparedWithoutRegister(napi_env env,
1148     MediaAssetManagerAsyncContext *asyncContext)
1149 {
1150     AssetHandler *assetHandler = InsertDataHandler(NotifyMode::FAST_NOTIFY, env, asyncContext);
1151     if (assetHandler == nullptr) {
1152         NAPI_ERR_LOG("assetHandler is nullptr");
1153         return;
1154     }
1155     asyncContext->assetHandler = assetHandler;
1156 }
1157 
OnHandleProgress(napi_env env,MediaAssetManagerAsyncContext * asyncContext)1158 void MediaAssetManagerNapi::OnHandleProgress(napi_env env, MediaAssetManagerAsyncContext *asyncContext)
1159 {
1160     ProgressHandler *progressHandler = InsertProgressHandler(env, asyncContext);
1161     if (progressHandler == nullptr) {
1162         NAPI_ERR_LOG("progressHandler is nullptr");
1163         return;
1164     }
1165     asyncContext->progressHandler = progressHandler;
1166 }
1167 
PhotoQualityToString(MultiStagesCapturePhotoStatus photoQuality)1168 static string PhotoQualityToString(MultiStagesCapturePhotoStatus photoQuality)
1169 {
1170     static const string HIGH_QUALITY_STRING = "high";
1171     static const string LOW_QUALITY_STRING = "low";
1172     if (photoQuality != MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS &&
1173         photoQuality != MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS) {
1174         NAPI_ERR_LOG("Invalid photo quality: %{public}d", static_cast<int>(photoQuality));
1175         return HIGH_QUALITY_STRING;
1176     }
1177 
1178     return (photoQuality == MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) ? HIGH_QUALITY_STRING :
1179         LOW_QUALITY_STRING;
1180 }
1181 
GetInfoMapNapiValue(napi_env env,AssetHandler * assetHandler)1182 static napi_value GetInfoMapNapiValue(napi_env env, AssetHandler* assetHandler)
1183 {
1184     napi_status status;
1185     napi_value mapNapiValue {nullptr};
1186     status = napi_create_map(env, &mapNapiValue);
1187     CHECK_COND_RET(status == napi_ok && mapNapiValue != nullptr, nullptr,
1188         "Failed to create map napi value, napi status: %{public}d", static_cast<int>(status));
1189 
1190     napi_value qualityInfo {nullptr};
1191     status = napi_create_string_utf8(env, PhotoQualityToString(assetHandler->photoQuality).c_str(),
1192         NAPI_AUTO_LENGTH, &qualityInfo);
1193     CHECK_COND_RET(status == napi_ok && qualityInfo != nullptr, nullptr,
1194         "Failed to create quality string, napi status: %{public}d", static_cast<int>(status));
1195 
1196     status = napi_set_named_property(env, mapNapiValue, "quality", qualityInfo);
1197     CHECK_COND_RET(status == napi_ok, nullptr, "Failed to set quality property, napi status: %{public}d",
1198         static_cast<int>(status));
1199 
1200     status = napi_map_set_named_property(env, mapNapiValue, "quality", qualityInfo);
1201     CHECK_COND_RET(status == napi_ok, nullptr, "Failed to set quality map key-value, napi status: %{public}d",
1202         static_cast<int>(status));
1203 
1204     return mapNapiValue;
1205 }
1206 
GetNapiValueOfMedia(napi_env env,const std::shared_ptr<NapiMediaAssetDataHandler> & dataHandler,bool & isPicture)1207 static napi_value GetNapiValueOfMedia(napi_env env, const std::shared_ptr<NapiMediaAssetDataHandler>& dataHandler,
1208     bool& isPicture)
1209 {
1210     NAPI_DEBUG_LOG("GetNapiValueOfMedia");
1211     napi_value napiValueOfMedia = nullptr;
1212     if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_ARRAY_BUFFER) {
1213         MediaAssetManagerNapi::GetByteArrayNapiObject(dataHandler->GetRequestUri(), napiValueOfMedia,
1214             dataHandler->GetSourceMode() == SourceMode::ORIGINAL_MODE, env);
1215     } else if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_IMAGE_SOURCE) {
1216         MediaAssetManagerNapi::GetImageSourceNapiObject(dataHandler->GetRequestUri(), napiValueOfMedia,
1217             dataHandler->GetSourceMode() == SourceMode::ORIGINAL_MODE, env);
1218     } else if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_TARGET_PATH) {
1219         WriteData param;
1220         param.compatibleMode = dataHandler->GetCompatibleMode();
1221         param.destUri = dataHandler->GetDestUri();
1222         param.requestUri = dataHandler->GetRequestUri();
1223         param.env = env;
1224         param.isSource = dataHandler->GetSourceMode() == SourceMode::ORIGINAL_MODE;
1225         MediaAssetManagerNapi::WriteDataToDestPath(param, napiValueOfMedia, dataHandler->GetRequestId());
1226     } else if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_MOVING_PHOTO) {
1227         MovingPhotoParam movingPhotoParam;
1228         movingPhotoParam.compatibleMode =  dataHandler->GetCompatibleMode();
1229         movingPhotoParam.requestId = dataHandler->GetRequestId();
1230         movingPhotoParam.progressHandlerRef = dataHandler->GetProgressHandlerRef();
1231         movingPhotoParam.threadsafeFunction = dataHandler->GetThreadsafeFunction();
1232         napiValueOfMedia = MovingPhotoNapi::NewMovingPhotoNapi(env, dataHandler->GetRequestUri(),
1233             dataHandler->GetSourceMode(), movingPhotoParam);
1234     } else if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_PICTURE) {
1235         MediaAssetManagerNapi::GetPictureNapiObject(dataHandler->GetRequestUri(), napiValueOfMedia,
1236             dataHandler->GetSourceMode() == SourceMode::ORIGINAL_MODE, env, isPicture);
1237     } else {
1238         NAPI_ERR_LOG("source mode type invalid");
1239     }
1240     return napiValueOfMedia;
1241 }
1242 
IsSaveCallbackInfoByTranscoder(napi_value napiValueOfMedia,napi_env env,AssetHandler * assetHandler,napi_value napiValueOfInfoMap)1243 bool IsSaveCallbackInfoByTranscoder(napi_value napiValueOfMedia, napi_env env, AssetHandler *assetHandler,
1244     napi_value napiValueOfInfoMap)
1245 {
1246     auto dataHandler = assetHandler->dataHandler;
1247     if (dataHandler == nullptr) {
1248         NAPI_ERR_LOG("data handler is nullptr");
1249         return false;
1250     }
1251     if (napiValueOfMedia == nullptr) {
1252         napi_get_undefined(env, &napiValueOfMedia);
1253     }
1254     bool isTranscoder;
1255     if (!isTranscoderMap_.Find(assetHandler->requestId, isTranscoder)) {
1256         NAPI_INFO_LOG("not find key from map");
1257         isTranscoder = false;
1258     }
1259     NAPI_INFO_LOG("IsSaveCallbackInfoByTranscoder isTranscoder_ %{public}d", isTranscoder);
1260     if (isTranscoder) {
1261         onPreparedResult_.EnsureInsert(assetHandler->requestId, assetHandler);
1262         onPreparedResultValue_.EnsureInsert(assetHandler->requestId, napiValueOfMedia);
1263         return true;
1264     }
1265     dataHandler->JsOnDataPrepared(env, napiValueOfMedia, napiValueOfInfoMap);
1266     return false;
1267 }
1268 
SavePicture(std::string & fileUri)1269 static void SavePicture(std::string &fileUri)
1270 {
1271     std::string uriStr = PATH_SAVE_PICTURE;
1272     std::string tempStr = fileUri.substr(PhotoColumn::PHOTO_URI_PREFIX.length());
1273     std::size_t index = tempStr.find("/");
1274     std::string fileId = tempStr.substr(0, index);
1275     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
1276     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, PhotoColumn::MEDIA_ID, fileId);
1277     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, IMAGE_FILE_TYPE, "1");
1278     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, "uri", fileUri);
1279     Uri uri(uriStr);
1280     DataShare::DataShareValuesBucket valuesBucket;
1281     valuesBucket.Put(PhotoColumn::PHOTO_IS_TEMP, false);
1282     DataShare::DataSharePredicates predicate;
1283     UserFileClient::Update(uri, predicate, valuesBucket);
1284 }
1285 
OnDataPrepared(napi_env env,napi_value cb,void * context,void * data)1286 void MediaAssetManagerNapi::OnDataPrepared(napi_env env, napi_value cb, void *context, void *data)
1287 {
1288     NAPI_INFO_LOG("Begin OnDataPrepared.");
1289     AssetHandler *assetHandler = reinterpret_cast<AssetHandler *>(data);
1290     CHECK_NULL_PTR_RETURN_VOID(assetHandler, "assetHandler is nullptr");
1291     auto dataHandler = assetHandler->dataHandler;
1292     if (dataHandler == nullptr) {
1293         NAPI_ERR_LOG("data handler is nullptr");
1294         DeleteAssetHandlerSafe(assetHandler, env);
1295         return;
1296     }
1297 
1298     NotifyMode notifyMode = dataHandler->GetNotifyMode();
1299     if (notifyMode == NotifyMode::FAST_NOTIFY) {
1300         AssetHandler *tmp;
1301         if (!inProcessFastRequests.Find(assetHandler->requestId, tmp)) {
1302             NAPI_ERR_LOG("The request has been canceled");
1303             DeleteAssetHandlerSafe(assetHandler, env);
1304             return;
1305         }
1306     }
1307 
1308     napi_value napiValueOfInfoMap = nullptr;
1309     if (assetHandler->needsExtraInfo) {
1310         napiValueOfInfoMap = GetInfoMapNapiValue(env, assetHandler);
1311         if (napiValueOfInfoMap == nullptr) {
1312             NAPI_ERR_LOG("Failed to get info map");
1313             napi_get_undefined(env, &napiValueOfInfoMap);
1314         }
1315     }
1316     bool isPicture = true;
1317     if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_ARRAY_BUFFER ||
1318         dataHandler->GetReturnDataType() == ReturnDataType::TYPE_IMAGE_SOURCE) {
1319         string uri = dataHandler->GetRequestUri();
1320         SavePicture(uri);
1321     }
1322     napi_value napiValueOfMedia = assetHandler->isError ? nullptr : GetNapiValueOfMedia(env, dataHandler, isPicture);
1323     if (dataHandler->GetReturnDataType() == ReturnDataType::TYPE_PICTURE) {
1324         if (isPicture) {
1325             dataHandler->JsOnDataPrepared(env, napiValueOfMedia, nullptr, napiValueOfInfoMap);
1326         } else {
1327             if (napiValueOfMedia == nullptr) {
1328                 napi_get_undefined(env, &napiValueOfMedia);
1329             }
1330             dataHandler->JsOnDataPrepared(env, nullptr, napiValueOfMedia, napiValueOfInfoMap);
1331         }
1332     } else {
1333         if (IsSaveCallbackInfoByTranscoder(napiValueOfMedia, env, assetHandler, napiValueOfInfoMap)) {
1334             return;
1335         }
1336     }
1337     DeleteDataHandler(notifyMode, assetHandler->requestUri, assetHandler->requestId);
1338     NAPI_DEBUG_LOG("delete assetHandler");
1339     DeleteAssetHandlerSafe(assetHandler, env);
1340 }
1341 
CallPreparedCallbackAfterProgress(napi_env env,ProgressHandler * progressHandler,napi_value napiValueOfMedia)1342 void CallPreparedCallbackAfterProgress(napi_env env, ProgressHandler *progressHandler, napi_value napiValueOfMedia)
1343 {
1344     MediaCallTranscode::CallTranscodeRelease(progressHandler->requestId);
1345     MediaAssetManagerNapi::progressHandlerMap_.Erase(progressHandler->requestId);
1346     AssetHandler *assetHandler = nullptr;
1347     if (!onPreparedResult_.Find(progressHandler->requestId, assetHandler)) {
1348         NAPI_ERR_LOG("not find key from map");
1349         return;
1350     }
1351     onPreparedResult_.Erase(progressHandler->requestId);
1352     auto dataHandler = assetHandler->dataHandler;
1353     if (dataHandler == nullptr) {
1354         NAPI_ERR_LOG("data handler is nullptr");
1355         DeleteAssetHandlerSafe(assetHandler, env);
1356         return;
1357     }
1358 
1359     NotifyMode notifyMode = dataHandler->GetNotifyMode();
1360     napi_value napiValueOfInfoMap = nullptr;
1361     if (assetHandler->needsExtraInfo) {
1362         napiValueOfInfoMap = GetInfoMapNapiValue(env, assetHandler);
1363         if (napiValueOfInfoMap == nullptr) {
1364             NAPI_ERR_LOG("Failed to get info map");
1365             napi_get_undefined(env, &napiValueOfInfoMap);
1366         }
1367     }
1368     dataHandler->JsOnDataPrepared(env, napiValueOfMedia, napiValueOfInfoMap);
1369     NAPI_INFO_LOG("delete assetHandler");
1370     DeleteProcessHandlerSafe(progressHandler, env);
1371     DeleteDataHandler(notifyMode, assetHandler->requestUri, assetHandler->requestId);
1372     DeleteAssetHandlerSafe(assetHandler, env);
1373 }
1374 
CallProgressCallback(napi_env env,ProgressHandler * progressHandler,int32_t process)1375 void CallProgressCallback(napi_env env, ProgressHandler* progressHandler, int32_t process)
1376 {
1377     if (progressHandler == nullptr) {
1378         NAPI_ERR_LOG("progressHandler is nullptr");
1379         return;
1380     }
1381     napi_value result;
1382     napi_status status = napi_create_int32(env, process, &result);
1383     if (status != napi_ok) {
1384         NAPI_ERR_LOG("OnProgress napi_create_int32 fail");
1385     }
1386     napi_value callback;
1387     if (process < 0 || process > PROGRESS_MAX || progressHandler->progressRef == nullptr) {
1388         NAPI_ERR_LOG("progressHandler->progressRef is nullptr or process out of range");
1389         return;
1390     }
1391     status = napi_get_reference_value(env, progressHandler->progressRef, &callback);
1392     if (status != napi_ok) {
1393         NAPI_ERR_LOG("OnProgress napi_get_reference_value fail, napi status: %{public}d",
1394             static_cast<int>(status));
1395         DeleteProcessHandlerSafe(progressHandler, env);
1396         return;
1397     }
1398     napi_value jsOnProgress;
1399     status = napi_get_named_property(env, callback, ON_PROGRESS_FUNC, &jsOnProgress);
1400     if (status != napi_ok) {
1401         NAPI_ERR_LOG("jsOnProgress napi_get_named_property fail, napi status: %{public}d",
1402             static_cast<int>(status));
1403         DeleteProcessHandlerSafe(progressHandler, env);
1404         return;
1405     }
1406     constexpr size_t maxArgs = 1;
1407     napi_value argv[maxArgs];
1408     size_t argc = ARGS_ONE;
1409     argv[PARAM0] = result;
1410     argc = ARGS_ONE;
1411     napi_value promise;
1412     status = napi_call_function(env, nullptr, jsOnProgress, argc, argv, &promise);
1413     if (status != napi_ok) {
1414         NAPI_ERR_LOG("call js function failed %{public}d", static_cast<int32_t>(status));
1415         NapiError::ThrowError(env, JS_INNER_FAIL, "calling onDataPrepared failed");
1416     }
1417     NAPI_INFO_LOG("CallProgressCallback process %{public}d", process);
1418 }
1419 
OnProgress(napi_env env,napi_value cb,void * context,void * data)1420 void MediaAssetManagerNapi::OnProgress(napi_env env, napi_value cb, void *context, void *data)
1421 {
1422     ProgressHandler *progressHandler = reinterpret_cast<ProgressHandler *>(data);
1423     if (progressHandler == nullptr) {
1424         NAPI_ERR_LOG("progressHandler handler is nullptr");
1425         DeleteProcessHandlerSafe(progressHandler, env);
1426         return;
1427     }
1428     int32_t process = progressHandler->retProgressValue.progress;
1429     int32_t type = progressHandler->retProgressValue.type;
1430 
1431     if (type == INFO_TYPE_TRANSCODER_COMPLETED || type == INFO_TYPE_ERROR) {
1432         bool isTranscoder;
1433         if (isTranscoderMap_.Find(progressHandler->requestId, isTranscoder)) {
1434             isTranscoderMap_.Erase(progressHandler->requestId);
1435         }
1436 
1437         napi_value napiValueOfMedia;
1438         if (onPreparedResultValue_.Find(progressHandler->requestId, napiValueOfMedia)) {
1439             onPreparedResultValue_.Erase(progressHandler->requestId);
1440         }
1441         if (type == INFO_TYPE_ERROR) {
1442             napi_get_boolean(env, false, &napiValueOfMedia);
1443         }
1444         NAPI_INFO_LOG("CallPreparedCallbackAfterProgress type %{public}d", type);
1445         CallPreparedCallbackAfterProgress(env, progressHandler, napiValueOfMedia);
1446         return;
1447     }
1448     if (progressHandler->progressRef == nullptr) {
1449         NAPI_INFO_LOG("progressHandler->progressRef == nullptr");
1450         return;
1451     }
1452     CallProgressCallback(env, progressHandler, process);
1453 }
1454 
NotifyMediaDataPrepared(AssetHandler * assetHandler)1455 void MediaAssetManagerNapi::NotifyMediaDataPrepared(AssetHandler *assetHandler)
1456 {
1457     napi_status status = napi_call_threadsafe_function(assetHandler->threadSafeFunc, (void *)assetHandler,
1458         napi_tsfn_blocking);
1459     if (status != napi_ok) {
1460         NAPI_ERR_LOG("napi_call_threadsafe_function fail, %{public}d", static_cast<int32_t>(status));
1461         napi_release_threadsafe_function(assetHandler->threadSafeFunc, napi_tsfn_release);
1462         DeleteAssetHandlerSafe(assetHandler, nullptr);
1463     }
1464 }
1465 
OnChange(const ChangeInfo & changeInfo)1466 void MultiStagesTaskObserver::OnChange(const ChangeInfo &changeInfo)
1467 {
1468     if (changeInfo.changeType_ != static_cast<int32_t>(NotifyType::NOTIFY_UPDATE)) {
1469         NAPI_DEBUG_LOG("ignore notify change, type: %{public}d", changeInfo.changeType_);
1470         return;
1471     }
1472     for (auto &uri : changeInfo.uris_) {
1473         string uriString = uri.ToString();
1474         NAPI_INFO_LOG("Onchange, before onDataPrepared, uri: %{public}s", uriString.c_str());
1475         std::string photoId = "";
1476         if (uriString.find(HIGH_TEMPERATURE) == std::string::npos &&
1477             MediaAssetManagerNapi::QueryPhotoStatus(fileId_, uriString, photoId, true, -1) !=
1478             MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) {
1479             NAPI_ERR_LOG("requested data not prepared");
1480             continue;
1481         }
1482         std::string uriHightemp = uriString;
1483         auto index = uriString.find(HIGH_TEMPERATURE);
1484         uriString = uriString.substr(0, index);
1485 
1486         std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
1487         if (inProcessUriMap.find(uriString) == inProcessUriMap.end()) {
1488             NAPI_INFO_LOG("current uri does not in process, uri: %{public}s", uriString.c_str());
1489             return;
1490         }
1491         std::map<std::string, AssetHandler *> assetHandlers = inProcessUriMap[uriString];
1492         for (auto handler : assetHandlers) {
1493             DeleteRecordNoLock(handler.second->requestUri, handler.second->requestId);
1494         }
1495         for (auto handler : assetHandlers) {
1496             auto assetHandler = handler.second;
1497             if (uriHightemp.find(HIGH_TEMPERATURE) != std::string::npos) {
1498                 NAPI_INFO_LOG("OnChange receive high_temperature");
1499                 assetHandler->isError = true;
1500             }
1501             assetHandler->photoQuality = MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
1502             MediaAssetManagerNapi::NotifyMediaDataPrepared(assetHandler);
1503         }
1504     }
1505 }
1506 
NotifyOnProgress(int32_t type,int32_t progress,std::string requestId)1507 void MediaAssetManagerNapi::NotifyOnProgress(int32_t type, int32_t progress, std::string requestId)
1508 {
1509     NAPI_DEBUG_LOG("NotifyOnProgress start %{public}d, type:%{public}d, requestId:%{public}s", progress, type,
1510         requestId.c_str());
1511     ProgressHandler *progressHandler = nullptr;
1512     if (!MediaAssetManagerNapi::progressHandlerMap_.Find(requestId, progressHandler)) {
1513         NAPI_ERR_LOG("not find key from map");
1514         return;
1515     }
1516     if (progressHandler == nullptr) {
1517         NAPI_ERR_LOG("ProgressHandler is nullptr.");
1518         return;
1519     }
1520     progressHandler->retProgressValue.progress = progress;
1521     progressHandler->retProgressValue.type = type;
1522 
1523     napi_status status = napi_acquire_threadsafe_function(progressHandler->progressFunc);
1524     if (status != napi_ok) {
1525         NAPI_ERR_LOG("napi_acquire_threadsafe_function fail, status: %{public}d", static_cast<int32_t>(status));
1526         return;
1527     }
1528     status = napi_call_threadsafe_function(progressHandler->progressFunc, (void *)progressHandler, napi_tsfn_blocking);
1529     if (status != napi_ok) {
1530         NAPI_ERR_LOG("napi_call_threadsafe_function fail, status: %{public}d", static_cast<int32_t>(status));
1531         DeleteProcessHandlerSafe(progressHandler, progressHandler->env);
1532         return;
1533     }
1534 }
1535 
GetImageSourceNapiObject(const std::string & fileUri,napi_value & imageSourceNapiObj,bool isSource,napi_env env)1536 void MediaAssetManagerNapi::GetImageSourceNapiObject(const std::string &fileUri, napi_value &imageSourceNapiObj,
1537     bool isSource, napi_env env)
1538 {
1539     if (env == nullptr) {
1540         NAPI_ERR_LOG(" create image source object failed, need to initialize js env");
1541         return;
1542     }
1543     napi_value tempImageSourceNapi;
1544     ImageSourceNapi::CreateImageSourceNapi(env, &tempImageSourceNapi);
1545     ImageSourceNapi* imageSourceNapi = nullptr;
1546     napi_unwrap(env, tempImageSourceNapi, reinterpret_cast<void**>(&imageSourceNapi));
1547     if (imageSourceNapi == nullptr) {
1548         NAPI_ERR_LOG("unwrap image napi object failed");
1549         return;
1550     }
1551     std::string tmpUri = fileUri;
1552     if (isSource) {
1553         MediaFileUtils::UriAppendKeyValue(tmpUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
1554         NAPI_INFO_LOG("request source image's imageSource");
1555     }
1556     Uri uri(tmpUri);
1557     int fd = UserFileClient::OpenFile(uri, "r");
1558     if (fd < 0) {
1559         NAPI_ERR_LOG("get image fd failed, errno: %{public}d", errno);
1560         return;
1561     }
1562 
1563     SourceOptions opts;
1564     uint32_t errCode = 0;
1565     auto nativeImageSourcePtr = ImageSource::CreateImageSource(fd, opts, errCode);
1566     close(fd);
1567     if (nativeImageSourcePtr == nullptr) {
1568         NAPI_ERR_LOG("get ImageSource::CreateImageSource failed nullptr, errCode:%{public}d", errCode);
1569         return;
1570     }
1571     imageSourceNapi->SetNativeImageSource(std::move(nativeImageSourcePtr));
1572     imageSourceNapiObj = tempImageSourceNapi;
1573 }
1574 
GetPictureNapiObject(const std::string & fileUri,napi_value & pictureNapiObj,bool isSource,napi_env env,bool & isPicture)1575 void MediaAssetManagerNapi::GetPictureNapiObject(const std::string &fileUri, napi_value &pictureNapiObj,
1576     bool isSource, napi_env env,  bool& isPicture)
1577 {
1578     if (env == nullptr) {
1579         NAPI_ERR_LOG(" create image source object failed, need to initialize js env");
1580         return;
1581     }
1582     NAPI_DEBUG_LOG("GetPictureNapiObject");
1583 
1584     std::string tempStr = fileUri.substr(PhotoColumn::PHOTO_URI_PREFIX.length());
1585     std::size_t index = tempStr.find("/");
1586     std::string fileId = tempStr.substr(0, index);
1587     auto pic = PictureHandlerClient::RequestPicture(std::atoi(fileId.c_str()));
1588     if (pic == nullptr) {
1589         NAPI_ERR_LOG("picture is null");
1590         isPicture = false;
1591         GetImageSourceNapiObject(fileUri, pictureNapiObj, isSource, env);
1592         return;
1593     }
1594     NAPI_ERR_LOG("picture is not null");
1595     napi_value tempPictureNapi;
1596     PictureNapi::CreatePictureNapi(env, &tempPictureNapi);
1597     PictureNapi* pictureNapi = nullptr;
1598     napi_unwrap(env, tempPictureNapi, reinterpret_cast<void**>(&pictureNapi));
1599     if (pictureNapi == nullptr) {
1600         NAPI_ERR_LOG("GetPictureNapiObject unwrap image napi object failed");
1601         return;
1602     }
1603     pictureNapi->SetNativePicture(pic);
1604     pictureNapiObj = tempPictureNapi;
1605 }
1606 
1607 
GetByteArrayNapiObject(const std::string & requestUri,napi_value & arrayBuffer,bool isSource,napi_env env)1608 void MediaAssetManagerNapi::GetByteArrayNapiObject(const std::string &requestUri, napi_value &arrayBuffer,
1609     bool isSource, napi_env env)
1610 {
1611     if (env == nullptr) {
1612         NAPI_ERR_LOG("create byte array object failed, need to initialize js env");
1613         return;
1614     }
1615 
1616     std::string tmpUri = requestUri;
1617     if (isSource) {
1618         MediaFileUtils::UriAppendKeyValue(tmpUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
1619     }
1620     Uri uri(tmpUri);
1621     int imageFd = UserFileClient::OpenFile(uri, MEDIA_FILEMODE_READONLY);
1622     if (imageFd < 0) {
1623         NAPI_ERR_LOG("get image fd failed, %{public}d", errno);
1624         return;
1625     }
1626     ssize_t imgLen = lseek(imageFd, 0, SEEK_END);
1627     void* buffer = nullptr;
1628     if (napi_create_arraybuffer(env, imgLen, &buffer, &arrayBuffer) != napi_ok) {
1629         NAPI_ERR_LOG("create napi arraybuffer failed");
1630         close(imageFd);
1631         return;
1632     }
1633     lseek(imageFd, 0, SEEK_SET);
1634     ssize_t readRet = read(imageFd, buffer, imgLen);
1635     close(imageFd);
1636     if (readRet != imgLen) {
1637         NAPI_ERR_LOG("read image failed");
1638         return;
1639     }
1640 }
1641 
IsMovingPhoto(int32_t photoSubType,int32_t effectMode,int32_t sourceMode)1642 bool IsMovingPhoto(int32_t photoSubType, int32_t effectMode, int32_t sourceMode)
1643 {
1644     return photoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) ||
1645         (MediaLibraryNapiUtils::IsSystemApp() && sourceMode == static_cast<int32_t>(SourceMode::ORIGINAL_MODE) &&
1646         effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY));
1647 }
1648 
ParseArgsForRequestMovingPhoto(napi_env env,size_t argc,const napi_value argv[],unique_ptr<MediaAssetManagerAsyncContext> & context)1649 static napi_value ParseArgsForRequestMovingPhoto(napi_env env, size_t argc, const napi_value argv[],
1650     unique_ptr<MediaAssetManagerAsyncContext> &context)
1651 {
1652     CHECK_COND_WITH_MESSAGE(env, (argc == ARGS_FOUR), "Invalid number of arguments");
1653 
1654     FileAssetNapi *fileAssetNapi = nullptr;
1655     CHECK_COND_WITH_MESSAGE(env,
1656         (napi_unwrap(env, argv[PARAM1], reinterpret_cast<void**>(&fileAssetNapi)) == napi_ok),
1657         "Failed to parse photo asset");
1658     CHECK_COND_WITH_MESSAGE(env, fileAssetNapi != nullptr, "Failed to parse photo asset");
1659     auto fileAssetPtr = fileAssetNapi->GetFileAssetInstance();
1660     CHECK_COND_WITH_MESSAGE(env, fileAssetPtr != nullptr, "fileAsset is null");
1661     context->photoUri = fileAssetPtr->GetUri();
1662     context->fileId = fileAssetPtr->GetId();
1663     context->returnDataType = ReturnDataType::TYPE_MOVING_PHOTO;
1664     context->hasReadPermission = HasReadPermission();
1665     context->subType = PhotoSubType::MOVING_PHOTO;
1666     context->userId = fileAssetPtr->GetUserId();
1667 
1668     CHECK_COND_WITH_MESSAGE(env,
1669         ParseArgGetRequestOption(env, argv[PARAM2], context->deliveryMode, context->sourceMode) == napi_ok,
1670         "Failed to parse request option");
1671     CHECK_COND_WITH_MESSAGE(env,
1672         ParseArgGetRequestOptionMore(env, argv[PARAM2], context->compatibleMode,
1673         context->mediaAssetProgressHandler) == napi_ok, "Failed to parse request option more");
1674     CHECK_COND_WITH_MESSAGE(env, IsMovingPhoto(fileAssetPtr->GetPhotoSubType(),
1675         fileAssetPtr->GetMovingPhotoEffectMode(), static_cast<int32_t>(context->sourceMode)),
1676         "Asset is not a moving photo");
1677     if (fileAssetPtr->GetUserId() != -1) {
1678         MediaFileUtils::UriAppendKeyValue(context->photoUri, "user", to_string(fileAssetPtr->GetUserId()));
1679     }
1680     if (ParseArgGetDataHandler(env, argv[PARAM3], context->dataHandler, context->needsExtraInfo) != napi_ok) {
1681         NAPI_ERR_LOG("requestMovingPhoto ParseArgGetDataHandler error");
1682         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMovingPhoto ParseArgGetDataHandler error");
1683         return nullptr;
1684     }
1685 
1686     RETURN_NAPI_TRUE(env);
1687 }
1688 
CreateMovingPhotoThreadSafeFunc(napi_env env,unique_ptr<MediaAssetManagerAsyncContext> & context,napi_threadsafe_function & progressFunc)1689 napi_status MediaAssetManagerNapi::CreateMovingPhotoThreadSafeFunc(napi_env env,
1690     unique_ptr<MediaAssetManagerAsyncContext> &context, napi_threadsafe_function &progressFunc)
1691 {
1692     if (env == nullptr || context == nullptr) {
1693         NAPI_ERR_LOG("env or context is nullptr");
1694         return napi_invalid_arg;
1695     }
1696     napi_value workName = nullptr;
1697     napi_create_string_utf8(env, "ProgressThread", NAPI_AUTO_LENGTH, &workName);
1698     napi_status status = napi_ok;
1699     status = napi_create_threadsafe_function(env, context->mediaAssetProgressHandler, NULL, workName, 0, 1,
1700         NULL, NULL, NULL, MovingPhotoCallTranscoder::OnProgress, &progressFunc);
1701     if (status != napi_ok) {
1702         NAPI_ERR_LOG("napi_create_threadsafe_function fail");
1703         progressFunc = nullptr;
1704         NapiError::ThrowError(env, JS_INNER_FAIL, "napi_create_threadsafe_function fail");
1705     }
1706     return status;
1707 }
1708 
CreateMovingPhotoHandlerInfo(napi_env env,unique_ptr<MediaAssetManagerAsyncContext> & asyncContext)1709 bool MediaAssetManagerNapi::CreateMovingPhotoHandlerInfo(napi_env env,
1710     unique_ptr<MediaAssetManagerAsyncContext> &asyncContext)
1711 {
1712     if (env == nullptr || asyncContext == nullptr) {
1713         NAPI_ERR_LOG("env or asyncContext is nullptr");
1714         return false;
1715     }
1716     if (asyncContext->compatibleMode != CompatibleMode::COMPATIBLE_FORMAT_MODE) {
1717         return true;
1718     }
1719     if (asyncContext->mediaAssetProgressHandler == nullptr) {
1720         if (CreateMovingPhotoThreadSafeFunc(env, asyncContext, asyncContext->onProgressPtr) != napi_ok) {
1721             NAPI_ERR_LOG("CreateMovingPhotoThreadSafeFunc failed");
1722             return false;
1723         }
1724         return true;
1725     }
1726     if (CreateProgressHandlerRef(env, asyncContext, asyncContext->progressHandlerRef) != napi_ok ||
1727         CreateMovingPhotoThreadSafeFunc(env, asyncContext, asyncContext->onProgressPtr) != napi_ok) {
1728         NAPI_ERR_LOG("CreateProgressHandlerRef or CreateMovingPhotoThreadSafeFunc failed");
1729         return false;
1730     }
1731     return true;
1732 }
1733 
JSRequestMovingPhoto(napi_env env,napi_callback_info info)1734 napi_value MediaAssetManagerNapi::JSRequestMovingPhoto(napi_env env, napi_callback_info info)
1735 {
1736     MediaLibraryTracer tracer;
1737     tracer.Start("JSRequestMovingPhoto");
1738 
1739     unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
1740     CHECK_ARGS(env, napi_get_cb_info(env, info, &(asyncContext->argc), asyncContext->argv, nullptr, nullptr),
1741         JS_INNER_FAIL);
1742     CHECK_NULLPTR_RET(ParseArgsForRequestMovingPhoto(env, asyncContext->argc, asyncContext->argv, asyncContext));
1743     CHECK_COND(env, InitUserFileClient(env, info, asyncContext->userId), JS_INNER_FAIL);
1744     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef) != napi_ok
1745             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr) != napi_ok) {
1746         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
1747         return nullptr;
1748     }
1749     if (CreateDataHandlerRef(env, asyncContext, asyncContext->dataHandlerRef2) != napi_ok
1750             || CreateOnDataPreparedThreadSafeFunc(env, asyncContext, asyncContext->onDataPreparedPtr2) != napi_ok) {
1751         NAPI_ERR_LOG("CreateDataHandlerRef or CreateOnDataPreparedThreadSafeFunc failed");
1752         return nullptr;
1753     }
1754     if (!CreateMovingPhotoHandlerInfo(env, asyncContext)) {
1755         NAPI_ERR_LOG("CreateMovingPhotoHandlerInfo failed");
1756         return nullptr;
1757     }
1758     asyncContext->requestId = GenerateRequestId();
1759 
1760     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSRequestMovingPhoto", JSRequestExecute,
1761         JSRequestComplete);
1762 }
1763 
WriteDataToDestPath(WriteData & writeData,napi_value & resultNapiValue,std::string requestId)1764 void MediaAssetManagerNapi::WriteDataToDestPath(WriteData &writeData, napi_value &resultNapiValue,
1765     std::string requestId)
1766 {
1767     if (writeData.env == nullptr) {
1768         NAPI_ERR_LOG("create byte array object failed, need to initialize js env");
1769         return;
1770     }
1771     if (writeData.requestUri.empty() || writeData.destUri.empty()) {
1772         napi_get_boolean(writeData.env, false, &resultNapiValue);
1773         NAPI_ERR_LOG("requestUri or responseUri is nullptr");
1774         return;
1775     }
1776     std::string tmpUri = writeData.requestUri;
1777     if (writeData.isSource) {
1778         MediaFileUtils::UriAppendKeyValue(tmpUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
1779     }
1780     Uri srcUri(tmpUri);
1781     int srcFd = UserFileClient::OpenFile(srcUri, MEDIA_FILEMODE_READONLY);
1782     if (srcFd < 0) {
1783         napi_get_boolean(writeData.env, false, &resultNapiValue);
1784         NAPI_ERR_LOG("get source file fd failed %{public}d", srcFd);
1785         return;
1786     }
1787     UniqueFd uniqueSrcFd(srcFd);
1788     struct stat statSrc;
1789     if (fstat(uniqueSrcFd.Get(), &statSrc) == -1) {
1790         napi_get_boolean(writeData.env, false, &resultNapiValue);
1791         NAPI_DEBUG_LOG("File get stat failed, %{public}d", errno);
1792         return;
1793     }
1794     int destFd = GetFdFromSandBoxUri(writeData.destUri);
1795     if (destFd < 0) {
1796         napi_get_boolean(writeData.env, false, &resultNapiValue);
1797         NAPI_ERR_LOG("get dest fd failed %{public}d", destFd);
1798         return;
1799     }
1800     UniqueFd uniqueDestFd(destFd);
1801     NAPI_INFO_LOG("WriteDataToDestPath compatibleMode %{public}d", writeData.compatibleMode);
1802     if (writeData.compatibleMode == CompatibleMode::COMPATIBLE_FORMAT_MODE) {
1803         isTranscoderMap_.Insert(requestId, true);
1804         MediaCallTranscode::RegisterCallback(NotifyOnProgress);
1805         MediaCallTranscode::CallTranscodeHandle(writeData.env, uniqueSrcFd.Get(), uniqueDestFd.Get(), resultNapiValue,
1806             statSrc.st_size, requestId);
1807     } else {
1808         SendFile(writeData.env, uniqueSrcFd.Get(), uniqueDestFd.Get(), resultNapiValue, statSrc.st_size);
1809     }
1810     return;
1811 }
1812 
SendFile(napi_env env,int srcFd,int destFd,napi_value & result,off_t fileSize)1813 void MediaAssetManagerNapi::SendFile(napi_env env, int srcFd, int destFd, napi_value &result, off_t fileSize)
1814 {
1815     if (srcFd < 0 || destFd < 0) {
1816         NAPI_ERR_LOG("srcFd or destFd is invalid");
1817         napi_get_boolean(env, false, &result);
1818         return;
1819     }
1820     if (sendfile(destFd, srcFd, nullptr, fileSize) == -1) {
1821         close(srcFd);
1822         close(destFd);
1823         napi_get_boolean(env, false, &result);
1824         NAPI_ERR_LOG("send file failed, %{public}d", errno);
1825         return;
1826     }
1827     napi_get_boolean(env, true, &result);
1828 }
1829 
IsFastRequestCanceled(const std::string & requestId,std::string & photoId)1830 static bool IsFastRequestCanceled(const std::string &requestId, std::string &photoId)
1831 {
1832     AssetHandler *assetHandler = nullptr;
1833     if (!inProcessFastRequests.Find(requestId, assetHandler)) {
1834         NAPI_ERR_LOG("requestId(%{public}s) not in progress.", requestId.c_str());
1835         return false;
1836     }
1837 
1838     if (assetHandler == nullptr) {
1839         NAPI_ERR_LOG("assetHandler is nullptr.");
1840         return false;
1841     }
1842     photoId = assetHandler->photoId;
1843     inProcessFastRequests.Erase(requestId);
1844     return true;
1845 }
1846 
IsMapRecordCanceled(const std::string & requestId,std::string & photoId,napi_env env)1847 static bool IsMapRecordCanceled(const std::string &requestId, std::string &photoId, napi_env env)
1848 {
1849     AssetHandler *assetHandler = nullptr;
1850     std::lock_guard<std::mutex> lock(multiStagesCaptureLock);
1851     if (!IsInProcessInMapRecord(requestId, assetHandler)) {
1852         NAPI_ERR_LOG("requestId(%{public}s) not in progress.", requestId.c_str());
1853         return false;
1854     }
1855 
1856     if (assetHandler == nullptr) {
1857         NAPI_ERR_LOG("assetHandler is nullptr.");
1858         return false;
1859     }
1860     photoId = assetHandler->photoId;
1861     DeleteInProcessMapRecord(assetHandler->requestUri, assetHandler->requestId);
1862     DeleteAssetHandlerSafe(assetHandler, env);
1863     return true;
1864 }
1865 
JSCancelRequest(napi_env env,napi_callback_info info)1866 napi_value MediaAssetManagerNapi::JSCancelRequest(napi_env env, napi_callback_info info)
1867 {
1868     size_t argc = ARGS_TWO;
1869     napi_value argv[ARGS_TWO];
1870     napi_value thisVar = nullptr;
1871 
1872     GET_JS_ARGS(env, info, argc, argv, thisVar);
1873     NAPI_ASSERT(env, (argc == ARGS_TWO), "requires 2 paramters");
1874 
1875     string requestId;
1876     CHECK_ARGS_THROW_INVALID_PARAM(env,
1877         MediaLibraryNapiUtils::GetParamStringWithLength(env, argv[ARGS_ONE], REQUEST_ID_MAX_LEN, requestId));
1878     std::string photoId = "";
1879     bool hasFastRequestInProcess = IsFastRequestCanceled(requestId, photoId);
1880     bool hasMapRecordInProcess = IsMapRecordCanceled(requestId, photoId, env);
1881     if (hasFastRequestInProcess || hasMapRecordInProcess) {
1882         unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
1883         asyncContext->photoId = photoId;
1884         return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSCancelRequest", JSCancelRequestExecute,
1885             JSCancelRequestComplete);
1886     }
1887     RETURN_NAPI_UNDEFINED(env);
1888 }
1889 
ParseArgsForLoadMovingPhoto(napi_env env,size_t argc,const napi_value argv[],unique_ptr<MediaAssetManagerAsyncContext> & context)1890 static napi_value ParseArgsForLoadMovingPhoto(napi_env env, size_t argc, const napi_value argv[],
1891     unique_ptr<MediaAssetManagerAsyncContext> &context)
1892 {
1893     CHECK_COND_WITH_MESSAGE(env, (argc == ARGS_THREE), "Invalid number of arguments");
1894 
1895     std::string imageFileUri;
1896     CHECK_COND_WITH_MESSAGE(env,
1897         MediaLibraryNapiUtils::GetParamStringPathMax(env, argv[PARAM1], imageFileUri) == napi_ok,
1898         "Failed to parse image file uri");
1899     std::string videoFileUri;
1900     CHECK_COND_WITH_MESSAGE(env,
1901         MediaLibraryNapiUtils::GetParamStringPathMax(env, argv[PARAM2], videoFileUri) == napi_ok,
1902         "Failed to parse video file uri");
1903     std::string uri(imageFileUri + MOVING_PHOTO_URI_SPLIT + videoFileUri);
1904     context->photoUri = uri;
1905     RETURN_NAPI_TRUE(env);
1906 }
1907 
JSLoadMovingPhotoComplete(napi_env env,napi_status status,void * data)1908 static void JSLoadMovingPhotoComplete(napi_env env, napi_status status, void *data)
1909 {
1910     MediaAssetManagerAsyncContext *context = static_cast<MediaAssetManagerAsyncContext*>(data);
1911     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
1912 
1913     MediaLibraryTracer tracer;
1914     tracer.Start("JSLoadMovingPhotoComplete");
1915 
1916     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
1917     jsContext->status = false;
1918 
1919     if (context->error == ERR_DEFAULT) {
1920         MovingPhotoParam movingPhotoParam;
1921         movingPhotoParam.compatibleMode = CompatibleMode::ORIGINAL_FORMAT_MODE;
1922         movingPhotoParam.requestId = context->requestId;
1923         napi_value movingPhoto = MovingPhotoNapi::NewMovingPhotoNapi(env, context->photoUri,
1924             SourceMode::EDITED_MODE, movingPhotoParam);
1925         jsContext->data = movingPhoto;
1926         napi_get_undefined(env, &jsContext->error);
1927         jsContext->status = true;
1928     } else {
1929         context->HandleError(env, jsContext->error);
1930         napi_get_undefined(env, &jsContext->data);
1931     }
1932 
1933     tracer.Finish();
1934     if (context->work != nullptr) {
1935         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
1936             context->work, *jsContext);
1937     }
1938     delete context;
1939 }
1940 
JSLoadMovingPhotoExecute(napi_env env,void * data)1941 static void JSLoadMovingPhotoExecute(napi_env env, void *data)
1942 {
1943 }
1944 
JSLoadMovingPhoto(napi_env env,napi_callback_info info)1945 napi_value MediaAssetManagerNapi::JSLoadMovingPhoto(napi_env env, napi_callback_info info)
1946 {
1947     unique_ptr<MediaAssetManagerAsyncContext> asyncContext = make_unique<MediaAssetManagerAsyncContext>();
1948     CHECK_ARGS(env, napi_get_cb_info(env, info, &(asyncContext->argc), asyncContext->argv, nullptr, nullptr),
1949         JS_INNER_FAIL);
1950     CHECK_NULLPTR_RET(ParseArgsForLoadMovingPhoto(env, asyncContext->argc, asyncContext->argv, asyncContext));
1951     return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSLoadMovingPhoto", JSLoadMovingPhotoExecute,
1952         JSLoadMovingPhotoComplete);
1953 }
1954 
GetFdFromSandBoxUri(const std::string & sandBoxUri)1955 int32_t MediaAssetManagerNapi::GetFdFromSandBoxUri(const std::string &sandBoxUri)
1956 {
1957     AppFileService::ModuleFileUri::FileUri destUri(sandBoxUri);
1958     string destPath = destUri.GetRealPath();
1959     if (!MediaFileUtils::IsFileExists(destPath) && !MediaFileUtils::CreateFile(destPath)) {
1960         NAPI_DEBUG_LOG("Create empty dest file in sandbox failed, path:%{private}s", destPath.c_str());
1961         return E_ERR;
1962     }
1963     string absDestPath;
1964     if (!PathToRealPath(destPath, absDestPath)) {
1965         NAPI_DEBUG_LOG("PathToRealPath failed, path:%{private}s", destPath.c_str());
1966         return E_ERR;
1967     }
1968     return MediaFileUtils::OpenFile(absDestPath, MEDIA_FILEMODE_WRITETRUNCATE);
1969 }
1970 
CreateDataHandlerRef(napi_env env,const unique_ptr<MediaAssetManagerAsyncContext> & context,napi_ref & dataHandlerRef)1971 napi_status MediaAssetManagerNapi::CreateDataHandlerRef(napi_env env,
1972     const unique_ptr<MediaAssetManagerAsyncContext> &context, napi_ref &dataHandlerRef)
1973 {
1974     napi_status status = napi_create_reference(env, context->dataHandler, PARAM1, &dataHandlerRef);
1975     if (status != napi_ok) {
1976         dataHandlerRef = nullptr;
1977         NAPI_ERR_LOG("napi_create_reference failed");
1978         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "napi_create_reference fail");
1979     }
1980     return status;
1981 }
1982 
CreateProgressHandlerRef(napi_env env,const unique_ptr<MediaAssetManagerAsyncContext> & context,napi_ref & dataHandlerRef)1983 napi_status MediaAssetManagerNapi::CreateProgressHandlerRef(napi_env env,
1984     const unique_ptr<MediaAssetManagerAsyncContext> &context, napi_ref &dataHandlerRef)
1985 {
1986     napi_status status = napi_create_reference(env, context->mediaAssetProgressHandler, PARAM1, &dataHandlerRef);
1987     if (status != napi_ok) {
1988         dataHandlerRef = nullptr;
1989         NAPI_ERR_LOG("napi_create_reference failed");
1990         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "napi_create_reference fail");
1991     }
1992     return status;
1993 }
1994 
CreateOnDataPreparedThreadSafeFunc(napi_env env,const unique_ptr<MediaAssetManagerAsyncContext> & context,napi_threadsafe_function & threadSafeFunc)1995 napi_status MediaAssetManagerNapi::CreateOnDataPreparedThreadSafeFunc(napi_env env,
1996     const unique_ptr<MediaAssetManagerAsyncContext> &context, napi_threadsafe_function &threadSafeFunc)
1997 {
1998     NAPI_DEBUG_LOG("CreateOnDataPreparedThreadSafeFunc");
1999     napi_value workName = nullptr;
2000     napi_create_string_utf8(env, "Data Prepared", NAPI_AUTO_LENGTH, &workName);
2001     napi_status status = napi_create_threadsafe_function(env, context->dataHandler, NULL, workName, 0, 1,
2002         NULL, NULL, NULL, MediaAssetManagerNapi::OnDataPrepared, &threadSafeFunc);
2003     if (status != napi_ok) {
2004         NAPI_ERR_LOG("napi_create_threadsafe_function fail");
2005         threadSafeFunc = nullptr;
2006         NapiError::ThrowError(env, JS_INNER_FAIL, "napi_create_threadsafe_function fail");
2007     }
2008     return status;
2009 }
2010 
CreateOnProgressThreadSafeFunc(napi_env env,unique_ptr<MediaAssetManagerAsyncContext> & context,napi_threadsafe_function & progressFunc)2011 napi_status MediaAssetManagerNapi::CreateOnProgressThreadSafeFunc(napi_env env,
2012     unique_ptr<MediaAssetManagerAsyncContext> &context, napi_threadsafe_function &progressFunc)
2013 {
2014     napi_value workName = nullptr;
2015     napi_create_string_utf8(env, "ProgressThread", NAPI_AUTO_LENGTH, &workName);
2016     napi_status status = napi_ok;
2017     status = napi_create_threadsafe_function(env, context->mediaAssetProgressHandler, NULL, workName, 0, 1,
2018         NULL, NULL, NULL, MediaAssetManagerNapi::OnProgress, &progressFunc);
2019     if (status != napi_ok) {
2020         NAPI_ERR_LOG("napi_create_threadsafe_function fail");
2021         progressFunc = nullptr;
2022         NapiError::ThrowError(env, JS_INNER_FAIL, "napi_create_threadsafe_function fail");
2023     }
2024     return status;
2025 }
2026 
JSRequestExecute(napi_env env,void * data)2027 void MediaAssetManagerNapi::JSRequestExecute(napi_env env, void *data)
2028 {
2029     MediaLibraryTracer tracer;
2030     tracer.Start("JSRequestExecute");
2031     MediaAssetManagerAsyncContext *context = static_cast<MediaAssetManagerAsyncContext*>(data);
2032     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2033     OnHandleRequestImage(env, context);
2034     if (context->subType == PhotoSubType::MOVING_PHOTO) {
2035         string uri = LOG_MOVING_PHOTO;
2036         Uri logMovingPhotoUri(uri);
2037         DataShare::DataShareValuesBucket valuesBucket;
2038         string result;
2039         valuesBucket.Put("adapted", context->returnDataType == ReturnDataType::TYPE_MOVING_PHOTO);
2040         AdaptedReqBody reqBody;
2041         reqBody.adapted = context->returnDataType == ReturnDataType::TYPE_MOVING_PHOTO;
2042         IPC::UserDefineIPCClient().SetUserId(context->userId).Call(
2043             static_cast<uint32_t>(MediaLibraryBusinessCode::LOG_MOVING_PHOTO), reqBody);
2044     }
2045 }
2046 
JSRequestVideoFileExecute(napi_env env,void * data)2047 void MediaAssetManagerNapi::JSRequestVideoFileExecute(napi_env env, void *data)
2048 {
2049     MediaLibraryTracer tracer;
2050     tracer.Start("JSRequestVideoFileExecute");
2051     MediaAssetManagerAsyncContext *context = static_cast<MediaAssetManagerAsyncContext*>(data);
2052     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2053     OnHandleRequestVideo(env, context);
2054     OnHandleProgress(env, context);
2055 }
2056 
JSRequestComplete(napi_env env,napi_status,void * data)2057 void MediaAssetManagerNapi::JSRequestComplete(napi_env env, napi_status, void *data)
2058 {
2059     MediaAssetManagerAsyncContext *context = static_cast<MediaAssetManagerAsyncContext*>(data);
2060     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2061     if (context->dataHandlerRef != nullptr) {
2062         napi_delete_reference(env, context->dataHandlerRef);
2063         context->dataHandlerRef = nullptr;
2064     }
2065     if (context->dataHandlerRef2 != nullptr) {
2066         napi_delete_reference(env, context->dataHandlerRef2);
2067         context->dataHandlerRef2 = nullptr;
2068     }
2069 
2070     MediaLibraryTracer tracer;
2071     tracer.Start("JSRequestComplete");
2072 
2073     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2074     jsContext->status = false;
2075     if (context->assetHandler) {
2076         NotifyMediaDataPrepared(context->assetHandler);
2077         context->assetHandler = nullptr;
2078     }
2079     if (context->error == ERR_DEFAULT) {
2080         napi_value requestId;
2081         napi_create_string_utf8(env, context->requestId.c_str(), NAPI_AUTO_LENGTH, &requestId);
2082         jsContext->data = requestId;
2083         napi_get_undefined(env, &jsContext->error);
2084         jsContext->status = true;
2085     } else {
2086         context->HandleError(env, jsContext->error);
2087         napi_get_undefined(env, &jsContext->data);
2088     }
2089 
2090     if (context->work != nullptr) {
2091         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2092             context->work, *jsContext);
2093     }
2094     delete context;
2095 }
2096 
JSCancelRequestExecute(napi_env env,void * data)2097 void MediaAssetManagerNapi::JSCancelRequestExecute(napi_env env, void *data)
2098 {
2099     MediaAssetManagerAsyncContext *context = static_cast<MediaAssetManagerAsyncContext*>(data);
2100     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2101     MediaAssetManagerNapi::CancelProcessImage(context->photoId);
2102 }
2103 
JSCancelRequestComplete(napi_env env,napi_status,void * data)2104 void MediaAssetManagerNapi::JSCancelRequestComplete(napi_env env, napi_status, void *data)
2105 {
2106     MediaAssetManagerAsyncContext *context = static_cast<MediaAssetManagerAsyncContext*>(data);
2107     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
2108 
2109     MediaLibraryTracer tracer;
2110     tracer.Start("JSCancelRequestComplete");
2111 
2112     unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
2113     jsContext->status = false;
2114 
2115     if (context->error == ERR_DEFAULT) {
2116         napi_get_undefined(env, &jsContext->error);
2117         jsContext->status = true;
2118     } else {
2119         context->HandleError(env, jsContext->error);
2120     }
2121     napi_get_undefined(env, &jsContext->data);
2122 
2123     if (context->work != nullptr) {
2124         MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
2125             context->work, *jsContext);
2126     }
2127     delete context;
2128 }
2129 } // namespace Media
2130 } // namespace OHOS