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", ¶mCountNapi);
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, ¶mCount);
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", ¶mCountNapi);
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, ¶mCount);
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