• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define MLOG_TAG "MediaAssetManagerNapi"
17 
18 #include "media_asset_manager_napi.h"
19 
20 #include <fcntl.h>
21 #include <string>
22 #include <unordered_map>
23 
24 #include "dataobs_mgr_client.h"
25 #include "file_asset_napi.h"
26 #include "file_uri.h"
27 #include "image_source.h"
28 #include "image_source_napi.h"
29 #include "media_column.h"
30 #include "media_file_utils.h"
31 #include "medialibrary_client_errno.h"
32 #include "media_library_napi.h"
33 #include "medialibrary_errno.h"
34 #include "medialibrary_napi_log.h"
35 #include "medialibrary_napi_utils.h"
36 #include "medialibrary_tracer.h"
37 #include "userfile_client.h"
38 
39 namespace OHOS {
40 namespace Media {
41 static const std::string MEDIA_ASSET_MANAGER_CLASS = "MediaAssetManager";
42 static std::mutex multiStagesCaptureLock;
43 
44 const int32_t LOW_QUALITY_IMAGE = 1;
45 const int32_t HIGH_QUALITY_IMAGE = 0;
46 
47 thread_local unique_ptr<ChangeListenerNapi> g_multiStagesRequestListObj = nullptr;
48 thread_local napi_ref constructor_ = nullptr;
49 napi_env MediaAssetManagerNapi::env_ = nullptr;
50 
51 static std::map<std::string, std::shared_ptr<MultiStagesTaskObserver>> multiStagesObserverMap;
52 static std::map<std::string, std::list<NapiMediaAssetDataHandler>> inProcessUriMap;
53 
Init(napi_env env,napi_value exports)54 napi_value MediaAssetManagerNapi::Init(napi_env env, napi_value exports)
55 {
56     NapiClassInfo info = {.name = MEDIA_ASSET_MANAGER_CLASS,
57         .ref = &constructor_,
58         .constructor = Constructor,
59         .props = {
60             DECLARE_NAPI_STATIC_FUNCTION("requestImage", JSRequestImage),
61             DECLARE_NAPI_STATIC_FUNCTION("requestImageData", JSRequestImageData),
62         }};
63         MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
64         return exports;
65 }
66 
Constructor(napi_env env,napi_callback_info info)67 napi_value MediaAssetManagerNapi::Constructor(napi_env env, napi_callback_info info)
68 {
69     napi_value newTarget = nullptr;
70     CHECK_ARGS(env, napi_get_new_target(env, info, &newTarget), JS_INNER_FAIL);
71     bool isConstructor = newTarget != nullptr;
72     if (isConstructor) {
73         napi_value thisVar = nullptr;
74         unique_ptr<MediaAssetManagerNapi> obj = make_unique<MediaAssetManagerNapi>();
75         CHECK_COND_WITH_MESSAGE(env, obj != nullptr, "Create MediaAssetManagerNapi failed");
76         CHECK_ARGS(env,
77             napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()), MediaAssetManagerNapi::Destructor,
78                 nullptr, nullptr),
79             JS_INNER_FAIL);
80         obj.release();
81         return thisVar;
82     }
83     napi_value constructor = nullptr;
84     napi_value result = nullptr;
85     NAPI_CALL(env, napi_get_reference_value(env, constructor_, &constructor));
86     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
87     return result;
88 }
89 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)90 void MediaAssetManagerNapi::Destructor(napi_env env, void* nativeObject, void* finalizeHint)
91 {
92     auto* mediaAssetManager = reinterpret_cast<MediaAssetManagerNapi*>(nativeObject);
93     if (mediaAssetManager != nullptr) {
94         delete mediaAssetManager;
95         mediaAssetManager = nullptr;
96     }
97 }
98 
GetMediaAssetManagerJsEnv()99 napi_env MediaAssetManagerNapi::GetMediaAssetManagerJsEnv()
100 {
101     return env_;
102 }
103 
SetMediaAssetManagerJsEnv(napi_env env)104 void MediaAssetManagerNapi::SetMediaAssetManagerJsEnv(napi_env env)
105 {
106     if (env_ != nullptr) {
107         NAPI_ERR_LOG("env already initialized no need set again");
108         return;
109     }
110     env_ = env;
111 }
112 
queryPhotoStatus(int fileId)113 MultiStagesCapturePhotoStatus MediaAssetManagerNapi::queryPhotoStatus(int fileId)
114 {
115     DataShare::DataSharePredicates predicates;
116     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
117     std::vector<std::string> fetchColumn { PhotoColumn::PHOTO_QUALITY };
118     Uri uri(PAH_QUERY_PHOTO);
119     int errCode = 0;
120     auto resultSet = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
121     if (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK) {
122         NAPI_ERR_LOG("query resultSet is nullptr");
123         return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
124     }
125     int columnIndexQuality = -1;
126     resultSet->GetColumnIndex(PhotoColumn::PHOTO_QUALITY, columnIndexQuality);
127     int currentPhotoQuality = HIGH_QUALITY_IMAGE;
128     resultSet->GetInt(columnIndexQuality, currentPhotoQuality);
129     if (currentPhotoQuality == LOW_QUALITY_IMAGE) {
130         NAPI_DEBUG_LOG("query photo status : lowQuality");
131         return MultiStagesCapturePhotoStatus::LOW_QUALITY_STATUS;
132     }
133     NAPI_DEBUG_LOG("query photo status quality: %{public}d", currentPhotoQuality);
134     return MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS;
135 }
136 
ProcessImage(const int fileId,const int deliveryMode,const std::string & packageName)137 void MediaAssetManagerNapi::ProcessImage(const int fileId, const int deliveryMode, const std::string &packageName)
138 {
139     std::string uriStr = PAH_PROCESS_IMAGE;
140     MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
141     Uri uri(uriStr);
142     DataShare::DataSharePredicates predicates;
143     int errCode = 0;
144     std::vector<std::string> columns { std::to_string(fileId), std::to_string(deliveryMode), packageName };
145     UserFileClient::Query(uri, predicates, columns, errCode);
146 }
147 
AddImage(const int fileId,DeliveryMode deliveryMode)148 void MediaAssetManagerNapi::AddImage(const int fileId, DeliveryMode deliveryMode)
149 {
150     Uri updateAssetUri(PAH_ADD_IMAGE);
151     DataShare::DataSharePredicates predicates;
152     DataShare::DataShareValuesBucket valuesBucket;
153     valuesBucket.Put(MediaColumn::MEDIA_ID, fileId);
154     valuesBucket.Put("deliveryMode", static_cast<int>(deliveryMode));
155     UserFileClient::Update(updateAssetUri, predicates, valuesBucket);
156 }
157 
GetDeliveryMode(napi_env env,const napi_value arg,const string & propName,DeliveryMode & deliveryMode)158 napi_status GetDeliveryMode(napi_env env, const napi_value arg, const string &propName,
159     DeliveryMode& deliveryMode)
160 {
161     bool present = false;
162     napi_value property = nullptr;
163     int mode = -1;
164     CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present),
165         "Failed to check property name");
166     if (!present) {
167         NAPI_ERR_LOG("delivery mode invalid argument ");
168         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "GetDeliveryMode failed");
169         return napi_invalid_arg;
170     }
171     CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
172     napi_get_value_int32(env, property, &mode);
173 
174     // delivery mode's valid range is 0 - 2
175     if (mode < 0 || mode > 2) {
176         NAPI_ERR_LOG("delivery mode invalid argument ");
177         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "invalid delivery mode value");
178         return napi_invalid_arg;
179     }
180     deliveryMode = static_cast<DeliveryMode>(mode);
181     return napi_ok;
182 }
183 
GetSourceMode(napi_env env,const napi_value arg,const string & propName,SourceMode & sourceMode)184 napi_status GetSourceMode(napi_env env, const napi_value arg, const string &propName,
185     SourceMode& sourceMode)
186 {
187     bool present = false;
188     napi_value property = nullptr;
189     int mode = -1;
190     CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present), "Failed to check property name");
191     if (!present) {
192         NAPI_ERR_LOG("source mode invalid argument ");
193         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "GetSourceMode failed");
194         return napi_invalid_arg;
195     }
196     CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
197     napi_get_value_int32(env, property, &mode);
198 
199     // source mode's valid range is 0 - 1
200     if (mode < 0 || mode > 1) {
201         NAPI_ERR_LOG("source mode invalid argument ");
202         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "invalid source mode value");
203         return napi_invalid_arg;
204     }
205     sourceMode = static_cast<SourceMode>(mode);
206     return napi_ok;
207 }
208 
ParseArgGetRequestOption(napi_env env,napi_value arg,DeliveryMode & deliveryMode,SourceMode & sourceMode)209 napi_status ParseArgGetRequestOption(napi_env env, napi_value arg, DeliveryMode &deliveryMode, SourceMode &sourceMode)
210 {
211     CHECK_STATUS_RET(GetDeliveryMode(env, arg, "deliveryMode", deliveryMode), "Failed to parse deliveryMode");
212     CHECK_STATUS_RET(GetSourceMode(env, arg, "sourceMode", sourceMode), "Failed to parse sourceMode");
213     return napi_ok;
214 }
215 
ParseArgGetCallingPakckageName(napi_env env,napi_value arg,std::string & callingPackageName)216 napi_status ParseArgGetCallingPakckageName(napi_env env, napi_value arg, std::string &callingPackageName)
217 {
218     if (arg == nullptr) {
219         NAPI_ERR_LOG("arg is invalid");
220         return napi_invalid_arg;
221     }
222     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, arg);
223     if (context == nullptr) {
224         NAPI_ERR_LOG("Failed to get context");
225         return napi_invalid_arg;
226     }
227     auto abilityContext = OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(context);
228     if (abilityContext == nullptr) {
229         NAPI_ERR_LOG("abilityContext invalid");
230         return napi_invalid_arg;
231     }
232     auto abilityInfo = abilityContext->GetAbilityInfo();
233     callingPackageName = abilityInfo->bundleName;
234     return napi_ok;
235 }
236 
ParseArgGetPhotoAsset(napi_env env,napi_value arg,int & fileId,std::string & uri,std::string & displayName)237 napi_status ParseArgGetPhotoAsset(napi_env env, napi_value arg, int &fileId, std::string &uri,
238     std::string &displayName)
239 {
240     if (arg == nullptr) {
241         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "ParseArgGetPhotoAsset failed to get photoAsset");
242         return napi_invalid_arg;
243     }
244     FileAssetNapi *obj = nullptr;
245     napi_unwrap(env, arg, reinterpret_cast<void**>(&obj));
246     if (obj == nullptr) {
247         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to get asset napi object");
248         return napi_invalid_arg;
249     }
250     fileId = obj->GetFileId();
251     uri = obj->GetFileUri();
252     displayName = obj->GetFileDisplayName();
253     return napi_ok;
254 }
255 
RegisterTaskObserver(const std::string & photoUri,const int fileId,napi_value napiMediaDataHandler,ReturnDataType returnDataType,SourceMode sourceMode)256 void MediaAssetManagerNapi::RegisterTaskObserver(const std::string &photoUri, const int fileId,
257     napi_value napiMediaDataHandler, ReturnDataType returnDataType, SourceMode sourceMode)
258 {
259     if (napiMediaDataHandler == nullptr) {
260         NAPI_ERR_LOG("apiMeidaDatalandler is null");
261         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "GetDeliveryMode failed");
262         return;
263     }
264     auto dataObserver = std::make_shared<MultiStagesTaskObserver>(photoUri, fileId, sourceMode);
265     Uri uri(photoUri);
266     if (multiStagesObserverMap.find(photoUri) == multiStagesObserverMap.end()) {
267         UserFileClient::RegisterObserverExt(uri,
268             static_cast<std::shared_ptr<DataShare::DataShareObserver>>(dataObserver), false);
269         multiStagesObserverMap.insert(std::make_pair(photoUri, dataObserver));
270     }
271 
272     NapiMediaAssetDataHandler mediaAssetDataHandler(MediaAssetManagerNapi::GetMediaAssetManagerJsEnv(),
273         napiMediaDataHandler, returnDataType);
274     if (inProcessUriMap.find(photoUri) != inProcessUriMap.end()) {
275         inProcessUriMap[photoUri].push_back(mediaAssetDataHandler);
276     } else {
277         std::list<NapiMediaAssetDataHandler> requestHandler({mediaAssetDataHandler});
278         inProcessUriMap[photoUri] = requestHandler;
279     }
280 }
281 
DeleteInProcessMapRecord(const std::string & requestUri)282 void MediaAssetManagerNapi::DeleteInProcessMapRecord(const std::string &requestUri)
283 {
284     NAPI_INFO_LOG("DeleteInProcessMapRecord %{public}s deleted", requestUri.c_str());
285     if (multiStagesObserverMap.find(requestUri) != multiStagesObserverMap.end()) {
286         UserFileClient::UnregisterObserverExt(Uri(requestUri),
287             static_cast<std::shared_ptr<DataShare::DataShareObserver>>(multiStagesObserverMap[requestUri]));
288     }
289     multiStagesObserverMap.erase(requestUri);
290     inProcessUriMap.erase(requestUri);
291 }
292 
ParseRequestImageArgs(napi_env env,napi_callback_info info,unique_ptr<RequestImageAsyncContext> & asyncContext)293 napi_status MediaAssetManagerNapi::ParseRequestImageArgs(napi_env env, napi_callback_info info,
294     unique_ptr<RequestImageAsyncContext> &asyncContext)
295 {
296     GET_JS_ARGS(env, info, asyncContext->argc, asyncContext->argv, asyncContext->thisVar);
297     if (asyncContext->argc != ARGS_FOUR) {
298         NAPI_ERR_LOG("requestImage argc error");
299         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "requestImage argc invalid");
300         return napi_invalid_arg;
301     }
302     if (ParseArgGetCallingPakckageName(env, asyncContext->argv[PARAM0], asyncContext->callingPkgName) != napi_ok) {
303         NAPI_ERR_LOG("requestImage ParseArgGetCallingPakckageName error");
304         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "requestImage ParseArgGetPhotoAsset error");
305         return napi_invalid_arg;
306     }
307     if (ParseArgGetPhotoAsset(env, asyncContext->argv[PARAM1], asyncContext->fileId, asyncContext->photoUri,
308         asyncContext->displayName) != napi_ok) {
309         NAPI_ERR_LOG("requestImage ParseArgGetPhotoAsset error");
310         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "requestImage ParseArgGetPhotoAsset error");
311         return napi_invalid_arg;
312     }
313     if (ParseArgGetRequestOption(env, asyncContext->argv[PARAM2], asyncContext->deliveryMode,
314         asyncContext->sourceMode) != napi_ok) {
315             NAPI_ERR_LOG("requestImage ParseArgGetRequestOption error");
316         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "requestImage ParseArgGetRequestOption error");
317         return napi_invalid_arg;
318     }
319     return napi_ok;
320 }
321 
InitUserFileClient(napi_env env,napi_callback_info info)322 bool MediaAssetManagerNapi::InitUserFileClient(napi_env env, napi_callback_info info)
323 {
324     if (UserFileClient::IsValid()) {
325         return true;
326     }
327 
328     std::unique_lock<std::mutex> helperLock(MediaLibraryNapi::sUserFileClientMutex_);
329     if (!UserFileClient::IsValid()) {
330         UserFileClient::Init(env, info);
331     }
332     helperLock.unlock();
333     return UserFileClient::IsValid();
334 }
335 
JSRequestImageData(napi_env env,napi_callback_info info)336 napi_value MediaAssetManagerNapi::JSRequestImageData(napi_env env, napi_callback_info info)
337 {
338     if (env == nullptr || info == nullptr) {
339         NAPI_ERR_LOG("JSRequestImageData js arg invalid");
340         NapiError::ThrowError(env, JS_INNER_FAIL, "JSRequestImageData js arg invalid");
341         return nullptr;
342     }
343     if (!InitUserFileClient(env, info)) {
344         NAPI_ERR_LOG("JSRequestImageData init user file client failed");
345         NapiError::ThrowError(env, JS_INNER_FAIL, "handler is invalid");
346         return nullptr;
347     }
348     if (GetMediaAssetManagerJsEnv() == nullptr) {
349         NAPI_INFO_LOG("js env is null need to intialize napi env");
350         SetMediaAssetManagerJsEnv(env);
351     }
352     MediaLibraryTracer tracer;
353     tracer.Start("JSRequestImageData");
354     unique_ptr<RequestImageAsyncContext> asyncContext = make_unique<RequestImageAsyncContext>();
355     asyncContext->returnDataType = ReturnDataType::TYPE_ARRAY_BUFFER;
356     if (ParseRequestImageArgs(env, info, asyncContext) != napi_ok) {
357         NAPI_ERR_LOG("failed to parse requestImagedata args");
358         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to parse requestImagedata args");
359         return nullptr;
360     }
361     onHandleRequestImage(asyncContext);
362     napi_value promise;
363     napi_value requestId;
364     napi_deferred deferred;
365     napi_create_promise(env, &deferred, &promise);
366     napi_create_string_utf8(env, "1", NAPI_AUTO_LENGTH, &requestId);
367     napi_resolve_deferred(env, deferred, requestId);
368     return promise;
369 }
370 
JSRequestImage(napi_env env,napi_callback_info info)371 napi_value MediaAssetManagerNapi::JSRequestImage(napi_env env, napi_callback_info info)
372 {
373     if (env == nullptr || info == nullptr) {
374         NAPI_ERR_LOG("JSRequestImage js arg invalid");
375         NapiError::ThrowError(env, JS_INNER_FAIL, "JSRequestImage js arg invalid");
376         return nullptr;
377     }
378     if (!InitUserFileClient(env, info)) {
379         NAPI_ERR_LOG("JSRequestImage init user file client failed");
380         NapiError::ThrowError(env, JS_INNER_FAIL, "handler is invalid");
381         return nullptr;
382     }
383     if (GetMediaAssetManagerJsEnv() == nullptr) {
384         NAPI_INFO_LOG("js env is null");
385         SetMediaAssetManagerJsEnv(env);
386     }
387     MediaLibraryTracer tracer;
388     tracer.Start("JSRequestImage");
389 
390     unique_ptr<RequestImageAsyncContext> asyncContext = make_unique<RequestImageAsyncContext>();
391     asyncContext->returnDataType = ReturnDataType::TYPE_IMAGE_SOURCE;
392     if (ParseRequestImageArgs(env, info, asyncContext) != napi_ok) {
393         NAPI_ERR_LOG("failed to parse requestImage args");
394         NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to parse requestImage args");
395         return nullptr;
396     }
397     onHandleRequestImage(asyncContext);
398     napi_value promise;
399     napi_value requestId;
400     napi_deferred deferred;
401     napi_create_promise(env, &deferred, &promise);
402     napi_create_string_utf8(env, "1", NAPI_AUTO_LENGTH, &requestId);
403     napi_resolve_deferred(env, deferred, requestId);
404     return promise;
405 }
406 
onHandleRequestImage(const unique_ptr<RequestImageAsyncContext> & asyncContext)407 void MediaAssetManagerNapi::onHandleRequestImage(const unique_ptr<RequestImageAsyncContext> &asyncContext)
408 {
409     MultiStagesCapturePhotoStatus status;
410     switch (asyncContext->deliveryMode) {
411         case DeliveryMode::FAST:
412             MediaAssetManagerNapi::notifyDataPreparedWithoutRegister(asyncContext->photoUri,
413                 asyncContext->argv[PARAM3], asyncContext->returnDataType, asyncContext->sourceMode);
414             break;
415         case DeliveryMode::HIGH_QUALITY:
416             status = MediaAssetManagerNapi::queryPhotoStatus(asyncContext->fileId);
417             if (status == MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) {
418                 MediaAssetManagerNapi::notifyDataPreparedWithoutRegister(asyncContext->photoUri,
419                     asyncContext->argv[PARAM3], asyncContext->returnDataType, asyncContext->sourceMode);
420             }
421             break;
422         case DeliveryMode::BALANCED_MODE:
423             status = MediaAssetManagerNapi::queryPhotoStatus(asyncContext->fileId);
424             MediaAssetManagerNapi::notifyDataPreparedWithoutRegister(asyncContext->photoUri,
425                 asyncContext->argv[PARAM3], asyncContext->returnDataType, asyncContext->sourceMode);
426             break;
427         default: {
428             NAPI_ERR_LOG("invalid delivery mode");
429             return;
430         }
431     }
432 
433     MediaAssetManagerNapi::ProcessImage(asyncContext->fileId, static_cast<int32_t>(asyncContext->deliveryMode),
434         asyncContext->callingPkgName);
435 }
436 
notifyDataPreparedWithoutRegister(std::string & requestUri,napi_value napiMediaDataHandler,ReturnDataType returnDataType,SourceMode sourceMode)437 void MediaAssetManagerNapi::notifyDataPreparedWithoutRegister(std::string &requestUri, napi_value napiMediaDataHandler,
438     ReturnDataType returnDataType, SourceMode sourceMode)
439 {
440     if (napiMediaDataHandler == nullptr) {
441         NAPI_ERR_LOG("apiMeidaDatalandler is null");
442         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "handler is invalid");
443         return;
444     }
445     NapiMediaAssetDataHandler mediaAssetDataHandler(MediaAssetManagerNapi::GetMediaAssetManagerJsEnv(),
446         napiMediaDataHandler, returnDataType);
447     napi_value imageSourceNapiValue = nullptr;
448     napi_value arrayBufferNapiValue = nullptr;
449     if (returnDataType == ReturnDataType::TYPE_ARRAY_BUFFER) {
450         if (arrayBufferNapiValue == nullptr) {
451             GetByteArrayNapiObject(requestUri, arrayBufferNapiValue,
452                 sourceMode == SourceMode::ORIGINAL_MODE);
453         }
454         mediaAssetDataHandler.JsOnDataPreared(arrayBufferNapiValue);
455     } else if (returnDataType == ReturnDataType::TYPE_IMAGE_SOURCE) {
456         if (imageSourceNapiValue == nullptr) {
457             GetImageSourceNapiObject(requestUri, imageSourceNapiValue,
458                 sourceMode == SourceMode::ORIGINAL_MODE);
459         }
460         mediaAssetDataHandler.JsOnDataPreared(imageSourceNapiValue);
461     } else {
462         NAPI_ERR_LOG("source mode type invalid");
463         NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "source mode type invalid");
464     }
465 }
466 
notifyImageDataPrepared(const std::string requestUri,SourceMode sourceMode)467 void MediaAssetManagerNapi::notifyImageDataPrepared(const std::string requestUri, SourceMode sourceMode)
468 {
469     auto iter = inProcessUriMap.find(requestUri);
470     if (iter == inProcessUriMap.end()) {
471         NAPI_ERR_LOG("current does not in process");
472         DeleteInProcessMapRecord(requestUri);
473         return;
474     }
475     auto handlerList = iter->second;
476     napi_value imageSourceNapiValue = nullptr;
477     napi_value arrayBufferNapiValue = nullptr;
478     for (auto listIter = handlerList.begin(); listIter != handlerList.end(); listIter++) {
479         if (listIter->GetHandlerType() == ReturnDataType::TYPE_ARRAY_BUFFER) {
480             NAPI_INFO_LOG("array buffer prepared");
481             if (arrayBufferNapiValue == nullptr) {
482                 GetByteArrayNapiObject(requestUri, arrayBufferNapiValue,
483                     sourceMode == SourceMode::ORIGINAL_MODE);
484             }
485             listIter->JsOnDataPreared(arrayBufferNapiValue);
486         } else if (listIter->GetHandlerType() == ReturnDataType::TYPE_IMAGE_SOURCE) {
487             NAPI_INFO_LOG("imageSource prepared");
488             if (imageSourceNapiValue == nullptr) {
489                 GetImageSourceNapiObject(requestUri, imageSourceNapiValue,
490                     sourceMode == SourceMode::ORIGINAL_MODE);
491             }
492             listIter->JsOnDataPreared(imageSourceNapiValue);
493         } else {
494             NAPI_ERR_LOG("notifyImageDataPrepared source mode type invalid");
495             NapiError::ThrowError(env_, OHOS_INVALID_PARAM_CODE, "source mode type invalid");
496         }
497     }
498     DeleteInProcessMapRecord(requestUri);
499 }
500 
OnChange(const ChangeInfo & changeInfo)501 void MultiStagesTaskObserver::OnChange(const ChangeInfo &changeInfo)
502 {
503     if (MediaAssetManagerNapi::queryPhotoStatus(fileId_) != MultiStagesCapturePhotoStatus::HIGH_QUALITY_STATUS) {
504         NAPI_ERR_LOG("requested data not prepared");
505         return;
506     }
507     MediaAssetManagerNapi::notifyImageDataPrepared(requestUri_, sourceMode_);
508 }
509 
GetImageSourceNapiObject(std::string fileUri,napi_value & imageSourceNapiObj,bool isSource)510 void MediaAssetManagerNapi::GetImageSourceNapiObject(std::string fileUri, napi_value &imageSourceNapiObj,
511     bool isSource)
512 {
513     uint32_t errCode = 0;
514     SourceOptions opts;
515     napi_value tempImageSourceNapi;
516     napi_env localEnv = MediaAssetManagerNapi::GetMediaAssetManagerJsEnv();
517     ImageSourceNapi* imageSourceNapi = nullptr;
518     if (localEnv == nullptr) {
519         NAPI_ERR_LOG(" create image source object failed, need to initialize js env");
520         NapiError::ThrowError(env_, JS_INNER_FAIL, "js env invalid error");
521         return;
522     }
523     ImageSourceNapi::CreateImageSourceNapi(localEnv, &tempImageSourceNapi);
524     napi_unwrap(localEnv, tempImageSourceNapi, reinterpret_cast<void**>(&imageSourceNapi));
525     if (imageSourceNapi == nullptr) {
526         NAPI_ERR_LOG("unwrap image napi object failed");
527         NapiError::ThrowError(env_, JS_INNER_FAIL, "CreateImageSource error");
528         return;
529     }
530     std::string tmpUri = fileUri;
531     if (isSource) {
532         MediaFileUtils::UriAppendKeyValue(tmpUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
533         NAPI_INFO_LOG("request source image's imageSource");
534     }
535     Uri uri(tmpUri);
536     int fd = UserFileClient::OpenFile(uri, "r");
537     if (fd < 0) {
538         NAPI_ERR_LOG("get iamge fd failed");
539         NapiError::ThrowError(env_, OHOS_PERMISSION_DENIED_CODE, "open Image file error");
540         return;
541     }
542     auto nativeImageSourcePtr = ImageSource::CreateImageSource(fd, opts, errCode);
543     close(fd);
544     if (nativeImageSourcePtr == nullptr) {
545         NAPI_ERR_LOG("get ImageSource::CreateImageSource failed nullptr");
546         NapiError::ThrowError(env_, JS_INNER_FAIL, "CreateImageSource error");
547         return;
548     }
549     imageSourceNapi->SetNativeImageSource(std::move(nativeImageSourcePtr));
550     imageSourceNapiObj = tempImageSourceNapi;
551 }
552 
GetByteArrayNapiObject(std::string requestUri,napi_value & arrayBuffer,bool isSource)553 void MediaAssetManagerNapi::GetByteArrayNapiObject(std::string requestUri, napi_value &arrayBuffer, bool isSource)
554 {
555     napi_env localEnv = MediaAssetManagerNapi::GetMediaAssetManagerJsEnv();
556     std::string tmpUri = requestUri;
557     if (isSource) {
558         MediaFileUtils::UriAppendKeyValue(tmpUri, MEDIA_OPERN_KEYWORD, SOURCE_REQUEST);
559     }
560     Uri uri(tmpUri);
561     int imageFd = UserFileClient::OpenFile(uri, MEDIA_FILEMODE_READONLY);
562     if (imageFd < 0) {
563         NAPI_ERR_LOG("get iamge fd failed");
564         NapiError::ThrowError(localEnv, OHOS_PERMISSION_DENIED_CODE, "open Image file error");
565         return;
566     }
567     size_t imgLen = lseek(imageFd, 0, SEEK_END);
568     lseek(imageFd, 0, SEEK_SET);
569     char buf[imgLen];
570     size_t readRet = read(imageFd, buf, imgLen);
571     close(imageFd);
572     if (readRet != imgLen) {
573         NAPI_ERR_LOG("read image failed");
574         NapiError::ThrowError(localEnv, JS_INNER_FAIL, "open Image file error");
575         return;
576     }
577     napi_create_arraybuffer(localEnv, imgLen, (void**)&buf, &arrayBuffer);
578 }
579 } // namespace Media
580 } // namespace OHOS