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