1 /* 2 * Copyright (C) 2024 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 "CloudEnhancementNapi" 17 18 #include "cloud_enhancement_napi.h" 19 20 #include <unordered_set> 21 22 #include "media_column.h" 23 #include "medialibrary_client_errno.h" 24 #include "medialibrary_errno.h" 25 #include "medialibrary_napi_log.h" 26 #include "medialibrary_tracer.h" 27 #include "userfile_client.h" 28 #include "userfile_manager_types.h" 29 #include "media_library_napi.h" 30 #include "media_file_uri.h" 31 #include "media_file_utils.h" 32 #include "result_set_utils.h" 33 #include "cloud_enhancement_task_state_napi.h" 34 #ifdef ABILITY_CLOUD_ENHANCEMENT_SUPPORT 35 #include "media_enhance_constants_c_api.h" 36 #include "media_enhance_handles.h" 37 #include "media_enhance_client_c_api.h" 38 #include "media_enhance_bundle_c_api.h" 39 #endif 40 41 using namespace std; 42 using namespace OHOS::DataShare; 43 using namespace OHOS::NativeRdb; 44 #ifdef ABILITY_CLOUD_ENHANCEMENT_SUPPORT 45 using namespace OHOS::MediaEnhance; 46 #endif 47 48 namespace OHOS::Media { 49 static const string CLOUD_ENHANCEMENT_CLASS = "CloudEnhancement"; 50 thread_local napi_ref CloudEnhancementNapi::constructor_ = nullptr; 51 52 constexpr int32_t STRONG_ASSOCIATION = 1; 53 54 #ifdef ABILITY_CLOUD_ENHANCEMENT_SUPPORT 55 static void* dynamicHandler = nullptr; 56 static MediaEnhanceClientHandle* clientWrapper = nullptr; 57 static mutex mtx; 58 59 using CreateMCEClient = MediaEnhanceClientHandle* (*)(MediaEnhance_TASK_TYPE taskType); 60 using DestroyMCEClient = void (*)(MediaEnhanceClientHandle* client); 61 using CreateMCEBundle = MediaEnhanceBundleHandle* (*)(); 62 using DestroyMCEBundle = void (*)(MediaEnhanceBundleHandle* bundle); 63 using ClientLoadSA = int32_t (*)(MediaEnhanceClientHandle* client); 64 using ClientIsConnected = bool (*)(MediaEnhanceClientHandle* client); 65 using ClientQueryTaskState = MediaEnhanceBundleHandle* (*)(MediaEnhanceClientHandle* client, const char* taskId); 66 using BundleHandleGetInt = int32_t (*)(MediaEnhanceBundleHandle* bundle, const char* key); 67 68 69 static CreateMCEClient createMCEClientFunc = nullptr; 70 static DestroyMCEClient destroyMCEClientFunc = nullptr; 71 static CreateMCEBundle createMCEBundleFunc = nullptr; 72 static DestroyMCEBundle destroyMCEBundleFunc = nullptr; 73 static ClientLoadSA clientLoadSaFunc = nullptr; 74 static ClientIsConnected clientIsConnectedFunc = nullptr; 75 static ClientQueryTaskState clientQueryTaskStateFunc = nullptr; 76 static BundleHandleGetInt bundleHandleGetIntFunc = nullptr; 77 InitCloudEnhancementBasicFunc(void * dynamicHandler)78 static void InitCloudEnhancementBasicFunc(void* dynamicHandler) 79 { 80 if (dynamicHandler == nullptr) { 81 NAPI_ERR_LOG("dynamicHandler is null. error:%{public}s", dlerror()); 82 return; 83 } 84 85 if (createMCEClientFunc == nullptr) { 86 createMCEClientFunc = (CreateMCEClient)dlsym(dynamicHandler, "CreateMediaEnhanceClient"); 87 } 88 if (createMCEClientFunc == nullptr) { 89 NAPI_ERR_LOG("CreateMediaEnhanceClient dlsym failed.error:%{public}s", dlerror()); 90 return; 91 } 92 93 if (destroyMCEClientFunc == nullptr) { 94 destroyMCEClientFunc = (DestroyMCEClient)dlsym(dynamicHandler, "DestroyMediaEnhanceClient"); 95 } 96 if (destroyMCEClientFunc == nullptr) { 97 NAPI_ERR_LOG("DestroyMediaEnhanceClient dlsym failed.error:%{public}s", dlerror()); 98 return; 99 } 100 101 if (createMCEBundleFunc == nullptr) { 102 createMCEBundleFunc = (CreateMCEBundle)dlsym(dynamicHandler, "CreateMediaEnhanceBundle"); 103 } 104 if (createMCEBundleFunc == nullptr) { 105 NAPI_ERR_LOG("CreateMediaEnhanceBundle dlsym failed.error:%{public}s", dlerror()); 106 return; 107 } 108 109 if (destroyMCEBundleFunc == nullptr) { 110 destroyMCEBundleFunc = (DestroyMCEBundle)dlsym(dynamicHandler, "DestroyMediaEnhanceBundle"); 111 } 112 if (destroyMCEBundleFunc == nullptr) { 113 NAPI_ERR_LOG("DestroyMediaEnhanceBundle dlsym failed.error:%{public}s", dlerror()); 114 return; 115 } 116 } 117 InitCloudEnhancementExtraFunc(void * dynamicHandler)118 static void InitCloudEnhancementExtraFunc(void* dynamicHandler) 119 { 120 if (dynamicHandler == nullptr) { 121 NAPI_ERR_LOG("dynamicHandler is null. error:%{public}s", dlerror()); 122 return; 123 } 124 125 if (clientLoadSaFunc == nullptr) { 126 clientLoadSaFunc = (ClientLoadSA)dlsym(dynamicHandler, "MediaEnhanceClient_LoadSA"); 127 } 128 if (clientLoadSaFunc == nullptr) { 129 NAPI_ERR_LOG("MediaEnhanceClient_LoadSA dlsym failed.error:%{public}s", dlerror()); 130 return; 131 } 132 133 if (clientIsConnectedFunc == nullptr) { 134 clientIsConnectedFunc = (ClientIsConnected)dlsym(dynamicHandler, "MediaEnhanceClient_IsConnected"); 135 } 136 if (clientIsConnectedFunc == nullptr) { 137 NAPI_ERR_LOG("MediaEnhanceClient_IsConnected dlsym failed.error:%{public}s", dlerror()); 138 return; 139 } 140 141 if (clientQueryTaskStateFunc == nullptr) { 142 clientQueryTaskStateFunc = (ClientQueryTaskState)dlsym(dynamicHandler, "MediaEnhanceClient_QueryTaskState"); 143 } 144 if (clientQueryTaskStateFunc == nullptr) { 145 NAPI_ERR_LOG("MediaEnhanceClient_QueryTaskState dlsym failed. error:%{public}s", dlerror()); 146 return; 147 } 148 149 if (bundleHandleGetIntFunc == nullptr) { 150 bundleHandleGetIntFunc = (BundleHandleGetInt)dlsym(dynamicHandler, "MediaEnhanceBundle_GetInt"); 151 } 152 if (bundleHandleGetIntFunc == nullptr) { 153 NAPI_ERR_LOG("MediaEnhanceBundle_GetInt dlsym failed. error:%{public}s", dlerror()); 154 return; 155 } 156 } 157 InitEnhancementClient()158 static void InitEnhancementClient() 159 { 160 if (createMCEClientFunc == nullptr) { 161 createMCEClientFunc = (CreateMCEClient)dlsym(dynamicHandler, "CreateMediaEnhanceClient"); 162 } 163 if (createMCEClientFunc == nullptr) { 164 NAPI_ERR_LOG("CreateMediaEnhanceClient dlsym failed.error:%{public}s", dlerror()); 165 return; 166 } 167 if (clientWrapper == nullptr && createMCEClientFunc != nullptr) { 168 NAPI_INFO_LOG("createMCEClientFunc by dlopen func."); 169 clientWrapper = createMCEClientFunc(MediaEnhance_TASK_TYPE::TYPE_CAMERA); 170 } 171 } 172 DestroyEnhancementClient()173 static void DestroyEnhancementClient() 174 { 175 if (destroyMCEClientFunc == nullptr) { 176 destroyMCEClientFunc = (DestroyMCEClient)dlsym(dynamicHandler, "DestroyMediaEnhanceClient"); 177 } 178 if (destroyMCEClientFunc == nullptr) { 179 NAPI_ERR_LOG("DestroyMediaEnhanceClient dlsym failed.error:%{public}s", dlerror()); 180 return; 181 } 182 destroyMCEClientFunc(clientWrapper); 183 clientWrapper = nullptr; 184 } 185 CreateBundle()186 static MediaEnhanceBundleHandle* CreateBundle() 187 { 188 if (createMCEBundleFunc == nullptr) { 189 createMCEBundleFunc = (CreateMCEBundle)dlsym(dynamicHandler, "CreateMediaEnhanceBundle"); 190 } 191 if (createMCEBundleFunc == nullptr) { 192 NAPI_ERR_LOG("createMCEBundleFunc dlsym failed.error:%{public}s", dlerror()); 193 return nullptr; 194 } 195 return createMCEBundleFunc(); 196 } 197 DestroyBundle(MediaEnhanceBundleHandle * bundle)198 static void DestroyBundle(MediaEnhanceBundleHandle* bundle) 199 { 200 if (destroyMCEBundleFunc == nullptr) { 201 destroyMCEBundleFunc = (DestroyMCEBundle)dlsym(dynamicHandler, 202 "DestroyMediaEnhanceBundle"); 203 } 204 if (destroyMCEBundleFunc == nullptr) { 205 NAPI_ERR_LOG("destroyMCEBundleFunc dlsym failed.error:%{public}s", dlerror()); 206 return; 207 } 208 destroyMCEBundleFunc(bundle); 209 } 210 LoadSA()211 static int32_t LoadSA() 212 { 213 if (clientWrapper == nullptr) { 214 NAPI_ERR_LOG("clientWrapper is nullptr!"); 215 return E_ERR; 216 } 217 if (clientLoadSaFunc == nullptr) { 218 clientLoadSaFunc = (ClientLoadSA)dlsym(dynamicHandler, "MediaEnhanceClient_LoadSA"); 219 } 220 if (clientLoadSaFunc == nullptr) { 221 NAPI_ERR_LOG("MediaEnhanceClient_LoadSA dlsym failed.error:%{public}s", dlerror()); 222 return E_ERR; 223 } 224 int32_t ret = clientLoadSaFunc(clientWrapper); 225 if (ret != E_OK) { 226 NAPI_ERR_LOG("Enhancement Service LoadSA failed:%{public}d", ret); 227 } 228 return ret; 229 } 230 IsConnected(MediaEnhanceClientHandle * clientWrapper)231 static bool IsConnected(MediaEnhanceClientHandle* clientWrapper) 232 { 233 if (clientWrapper == nullptr) { 234 NAPI_ERR_LOG("clientWrapper is nullptr!"); 235 return E_ERR; 236 } 237 if (clientIsConnectedFunc == nullptr) { 238 clientIsConnectedFunc = (ClientIsConnected)dlsym(dynamicHandler, 239 "MediaEnhanceClient_IsConnected"); 240 } 241 if (clientIsConnectedFunc == nullptr) { 242 NAPI_ERR_LOG("MediaEnhanceClient_IsConnected dlsym failed.error:%{public}s", dlerror()); 243 return false; 244 } 245 return clientIsConnectedFunc(clientWrapper); 246 } 247 QueryTaskState(const string & photoId)248 static MediaEnhanceBundleHandle* QueryTaskState(const string &photoId) 249 { 250 if (clientWrapper == nullptr) { 251 NAPI_ERR_LOG("clientWrapper is nullptr!"); 252 return nullptr; 253 } 254 if (clientQueryTaskStateFunc == nullptr) { 255 clientQueryTaskStateFunc = (ClientQueryTaskState)dlsym(dynamicHandler, "MediaEnhanceClient_QueryTaskState"); 256 } 257 if (clientQueryTaskStateFunc == nullptr) { 258 NAPI_ERR_LOG("MediaEnhanceClient_QueryTaskState dlsym failed. error:%{public}s", dlerror()); 259 return nullptr; 260 } 261 NAPI_INFO_LOG("QueryTaskState photoId: %{public}s", photoId.c_str()); 262 return clientQueryTaskStateFunc(clientWrapper, photoId.c_str()); 263 } 264 GetInt(MediaEnhanceBundleHandle * bundle,const char * key)265 static int32_t GetInt(MediaEnhanceBundleHandle* bundle, const char* key) 266 { 267 if (bundleHandleGetIntFunc == nullptr) { 268 bundleHandleGetIntFunc = (BundleHandleGetInt)dlsym(dynamicHandler, "MediaEnhanceBundle_GetInt"); 269 } 270 if (bundleHandleGetIntFunc == nullptr) { 271 NAPI_ERR_LOG("MediaEnhanceBundle_GetInt dlsym failed. error:%{public}s", dlerror()); 272 return E_ERR; 273 } 274 return bundleHandleGetIntFunc(bundle, key); 275 } 276 InitCloudEnhancementFunc()277 static void InitCloudEnhancementFunc() 278 { 279 string path = "/system/lib64/platformsdk/libmedia_cloud_enhance_plugin.z.so"; 280 dynamicHandler = dlopen(path.c_str(), RTLD_NOW); 281 InitCloudEnhancementBasicFunc(dynamicHandler); 282 InitCloudEnhancementExtraFunc(dynamicHandler); 283 } 284 #endif 285 Init(napi_env env,napi_value exports)286 napi_value CloudEnhancementNapi::Init(napi_env env, napi_value exports) 287 { 288 NapiClassInfo info = { .name = CLOUD_ENHANCEMENT_CLASS, 289 .ref = &constructor_, 290 .constructor = Constructor, 291 .props = { 292 DECLARE_NAPI_STATIC_FUNCTION("getCloudEnhancementInstance", JSGetCloudEnhancementInstance), 293 DECLARE_NAPI_FUNCTION("submitCloudEnhancementTasks", JSSubmitCloudEnhancementTasks), 294 DECLARE_NAPI_FUNCTION("prioritizeCloudEnhancementTask", JSPrioritizeCloudEnhancementTask), 295 DECLARE_NAPI_FUNCTION("cancelCloudEnhancementTasks", JSCancelCloudEnhancementTasks), 296 DECLARE_NAPI_FUNCTION("cancelAllCloudEnhancementTasks", JSCancelAllCloudEnhancementTasks), 297 DECLARE_NAPI_FUNCTION("queryCloudEnhancementTaskState", JSQueryCloudEnhancementTaskState), 298 DECLARE_NAPI_FUNCTION("syncCloudEnhancementTaskStatus", JSSyncCloudEnhancementTaskStatus), 299 DECLARE_NAPI_FUNCTION("getCloudEnhancementPair", JSGetCloudEnhancementPair), 300 } }; 301 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info); 302 #ifdef ABILITY_CLOUD_ENHANCEMENT_SUPPORT 303 InitCloudEnhancementFunc(); 304 #endif 305 return exports; 306 } 307 Constructor(napi_env env,napi_callback_info info)308 napi_value CloudEnhancementNapi::Constructor(napi_env env, napi_callback_info info) 309 { 310 if (!MediaLibraryNapiUtils::IsSystemApp()) { 311 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, 312 "The cloud enhancement instance can be called only by system apps"); 313 return nullptr; 314 } 315 napi_value newTarget = nullptr; 316 CHECK_ARGS(env, napi_get_new_target(env, info, &newTarget), JS_INNER_FAIL); 317 CHECK_COND_RET(newTarget != nullptr, nullptr, "Failed to check new.target"); 318 319 size_t argc = ARGS_ONE; 320 napi_value argv[ARGS_ONE] = { 0 }; 321 napi_value thisVar = nullptr; 322 CHECK_ARGS(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr), JS_INNER_FAIL); 323 CHECK_COND_WITH_MESSAGE(env, argc == ARGS_ONE, "Number of args is invalid"); 324 325 unique_ptr<CloudEnhancementNapi> obj = make_unique<CloudEnhancementNapi>(); 326 CHECK_COND(env, obj != nullptr, JS_INNER_FAIL); 327 CHECK_ARGS(env, 328 napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()), CloudEnhancementNapi::Destructor, nullptr, 329 nullptr), 330 JS_INNER_FAIL); 331 obj.release(); 332 return thisVar; 333 } 334 Destructor(napi_env env,void * nativeObject,void * finalizeHint)335 void CloudEnhancementNapi::Destructor(napi_env env, void* nativeObject, void* finalizeHint) 336 { 337 auto* cloudEnhancement = reinterpret_cast<CloudEnhancementNapi*>(nativeObject); 338 if (cloudEnhancement == nullptr) { 339 return; 340 } 341 delete cloudEnhancement; 342 cloudEnhancement = nullptr; 343 } 344 CheckWhetherInitSuccess(napi_env env,napi_value value,bool checkIsValid)345 static bool CheckWhetherInitSuccess(napi_env env, napi_value value, bool checkIsValid) 346 { 347 napi_value propertyNames; 348 uint32_t propertyLength; 349 napi_valuetype valueType = napi_undefined; 350 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false); 351 if (valueType != napi_object) { 352 return false; 353 } 354 355 NAPI_CALL_BASE(env, napi_get_property_names(env, value, &propertyNames), false); 356 NAPI_CALL_BASE(env, napi_get_array_length(env, propertyNames, &propertyLength), false); 357 if (propertyLength == 0) { 358 return false; 359 } 360 if (checkIsValid && (!UserFileClient::IsValid())) { 361 NAPI_ERR_LOG("UserFileClient is not valid"); 362 return false; 363 } 364 return true; 365 } 366 JSGetCloudEnhancementInstance(napi_env env,napi_callback_info info)367 napi_value CloudEnhancementNapi::JSGetCloudEnhancementInstance(napi_env env, napi_callback_info info) 368 { 369 MediaLibraryTracer tracer; 370 tracer.Start("GetCloudEnhancementInstance"); 371 372 constexpr size_t ARG_CONTEXT = 1; 373 size_t argc = ARG_CONTEXT; 374 napi_value argv[ARGS_TWO] = {0}; 375 376 napi_value thisVar = nullptr; 377 napi_value ctor = nullptr; 378 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); 379 NAPI_CALL(env, napi_get_reference_value(env, constructor_, &ctor)); 380 381 napi_value result = nullptr; 382 NAPI_CALL(env, napi_new_instance(env, ctor, argc, argv, &result)); 383 if (!CheckWhetherInitSuccess(env, result, false)) { 384 NAPI_ERR_LOG("Init Cloud Enhancement Instance is failed"); 385 NAPI_CALL(env, napi_get_undefined(env, &result)); 386 } 387 return result; 388 } 389 InitUserFileClient(napi_env env,napi_callback_info info)390 bool CloudEnhancementNapi::InitUserFileClient(napi_env env, napi_callback_info info) 391 { 392 if (UserFileClient::IsValid()) { 393 return true; 394 } 395 396 std::unique_lock<std::mutex> helperLock(MediaLibraryNapi::sUserFileClientMutex_); 397 if (!UserFileClient::IsValid()) { 398 UserFileClient::Init(env, info); 399 } 400 helperLock.unlock(); 401 return UserFileClient::IsValid(); 402 } 403 ParseArgGetPhotoAsset(napi_env env,napi_value arg,int & fileId,std::string & uri,std::string & displayName)404 napi_status CloudEnhancementNapi::ParseArgGetPhotoAsset(napi_env env, napi_value arg, int &fileId, std::string &uri, 405 std::string &displayName) 406 { 407 if (arg == nullptr) { 408 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "ParseArgGetPhotoAsset failed to get photoAsset"); 409 return napi_invalid_arg; 410 } 411 FileAssetNapi *obj = nullptr; 412 napi_unwrap(env, arg, reinterpret_cast<void**>(&obj)); 413 if (obj == nullptr) { 414 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "failed to get asset napi object"); 415 return napi_invalid_arg; 416 } 417 fileId = obj->GetFileId(); 418 uri = obj->GetFileUri(); 419 displayName = obj->GetFileDisplayName(); 420 return napi_ok; 421 } 422 ParseArgsSubmitCloudEnhancementTasks(napi_env env,napi_callback_info info,unique_ptr<CloudEnhancementAsyncContext> & context)423 static napi_value ParseArgsSubmitCloudEnhancementTasks(napi_env env, napi_callback_info info, 424 unique_ptr<CloudEnhancementAsyncContext>& context) 425 { 426 CHECK_COND_WITH_MESSAGE(env, 427 MediaLibraryNapiUtils::AsyncContextGetArgs(env, info, context, ARGS_TWO, ARGS_TWO) == napi_ok, 428 "Failed to get args"); 429 CHECK_COND(env, CloudEnhancementNapi::InitUserFileClient(env, info), JS_INNER_FAIL); 430 431 napi_valuetype valueType = napi_undefined; 432 CHECK_ARGS(env, napi_typeof(env, context->argv[PARAM1], &valueType), JS_INNER_FAIL); 433 CHECK_COND(env, valueType == napi_boolean, JS_INNER_FAIL); 434 435 bool hasCloudWatermark = false; 436 if (napi_get_value_bool(env, context->argv[PARAM1], &hasCloudWatermark) != napi_ok) { 437 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID); 438 return nullptr; 439 } 440 441 vector<string> uris; 442 vector<napi_value> napiValues; 443 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetNapiValueArray(env, context->argv[PARAM0], napiValues)); 444 CHECK_COND_WITH_MESSAGE(env, !napiValues.empty(), "array is empty"); 445 CHECK_ARGS(env, napi_typeof(env, napiValues.front(), &valueType), JS_INNER_FAIL); 446 if (valueType == napi_object) { // array of asset object 447 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetUriArrayFromAssets(env, napiValues, uris)); 448 } else { 449 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Invalid type"); 450 return nullptr; 451 } 452 453 CHECK_COND_WITH_MESSAGE(env, !uris.empty(), "Failed to check empty array"); 454 for (const auto& uri : uris) { 455 CHECK_COND(env, uri.find(PhotoColumn::PHOTO_URI_PREFIX) != string::npos, JS_E_URI); 456 } 457 458 context->hasCloudWatermark_ = hasCloudWatermark; 459 context->predicates.In(PhotoColumn::MEDIA_ID, uris); 460 context->uris.assign(uris.begin(), uris.end()); 461 RETURN_NAPI_TRUE(env); 462 } 463 SubmitCloudEnhancementTasksExecute(napi_env env,void * data)464 static void SubmitCloudEnhancementTasksExecute(napi_env env, void* data) 465 { 466 MediaLibraryTracer tracer; 467 tracer.Start("SubmitCloudEnhancementTasksExecute"); 468 469 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 470 string uriStr = PAH_CLOUD_ENHANCEMENT_ADD; 471 MediaLibraryNapiUtils::UriAppendKeyValue(uriStr, MEDIA_OPERN_KEYWORD, to_string(context->hasCloudWatermark_)); 472 Uri addTaskUri(uriStr); 473 context->valuesBucket.Put(PhotoColumn::PHOTO_STRONG_ASSOCIATION, STRONG_ASSOCIATION); 474 int32_t changeRows = UserFileClient::Update(addTaskUri, context->predicates, context->valuesBucket); 475 if (changeRows < 0) { 476 context->SaveError(changeRows); 477 NAPI_ERR_LOG("Submit cloud enhancement tasks failed, err: %{public}d", changeRows); 478 return; 479 } 480 NAPI_INFO_LOG("SubmitCloudEnhancementTasksExecute Success"); 481 } 482 SubmitCloudEnhancementTasksCompleteCallback(napi_env env,napi_status status,void * data)483 static void SubmitCloudEnhancementTasksCompleteCallback(napi_env env, napi_status status, void* data) 484 { 485 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 486 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 487 auto jsContext = make_unique<JSAsyncContextOutput>(); 488 jsContext->status = false; 489 napi_get_undefined(env, &jsContext->data); 490 napi_get_undefined(env, &jsContext->error); 491 if (context->error == ERR_DEFAULT) { 492 jsContext->status = true; 493 } else { 494 context->HandleError(env, jsContext->error); 495 } 496 497 if (context->work != nullptr) { 498 MediaLibraryNapiUtils::InvokeJSAsyncMethod( 499 env, context->deferred, context->callbackRef, context->work, *jsContext); 500 } 501 delete context; 502 } 503 JSSubmitCloudEnhancementTasks(napi_env env,napi_callback_info info)504 napi_value CloudEnhancementNapi::JSSubmitCloudEnhancementTasks(napi_env env, napi_callback_info info) 505 { 506 if (!MediaLibraryNapiUtils::IsSystemApp()) { 507 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 508 return nullptr; 509 } 510 MediaLibraryTracer tracer; 511 tracer.Start("JSSubmitCloudEnhancementTasks"); 512 513 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 514 CHECK_COND_WITH_MESSAGE(env, ParseArgsSubmitCloudEnhancementTasks(env, info, asyncContext), "Failed to parse args"); 515 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "SubmitCloudEnhancementTasks", 516 SubmitCloudEnhancementTasksExecute, SubmitCloudEnhancementTasksCompleteCallback); 517 } 518 ParseArgPrioritize(napi_env env,napi_callback_info info,unique_ptr<CloudEnhancementAsyncContext> & context)519 static napi_status ParseArgPrioritize(napi_env env, napi_callback_info info, 520 unique_ptr<CloudEnhancementAsyncContext>& context) 521 { 522 napi_value thisVar = nullptr; 523 context->argc = ARGS_ONE; 524 GET_JS_ARGS(env, info, context->argc, context->argv, thisVar); 525 526 if (CloudEnhancementNapi::ParseArgGetPhotoAsset(env, context->argv[PARAM0], context->fileId, context->photoUri, 527 context->displayName) != napi_ok) { 528 NAPI_ERR_LOG("requestMedia ParseArgGetPhotoAsset error"); 529 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetPhotoAsset error"); 530 return napi_invalid_arg; 531 } 532 533 NAPI_INFO_LOG("Parse Arg: %{public}d, %{private}s, %{public}s", context->fileId, context->photoUri.c_str(), 534 context->displayName.c_str()); 535 536 return napi_ok; 537 } 538 PrioritizeCloudEnhancementTaskExecute(napi_env env,void * data)539 static void PrioritizeCloudEnhancementTaskExecute(napi_env env, void* data) 540 { 541 MediaLibraryTracer tracer; 542 tracer.Start("PrioritizeCloudEnhancementTaskExecute"); 543 544 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 545 string uriStr = PAH_CLOUD_ENHANCEMENT_PRIORITIZE; 546 Uri prioritizeTaskUri(uriStr); 547 context->predicates.EqualTo(MediaColumn::MEDIA_ID, context->photoUri); 548 context->valuesBucket.Put(PhotoColumn::PHOTO_STRONG_ASSOCIATION, STRONG_ASSOCIATION); 549 int32_t changedRows = UserFileClient::Update(prioritizeTaskUri, context->predicates, context->valuesBucket); 550 if (changedRows < 0) { 551 context->SaveError(changedRows); 552 NAPI_ERR_LOG("Prioritize cloud enhancement task failed, err: %{public}d", changedRows); 553 } 554 NAPI_INFO_LOG("PrioritizeCloudEnhancementTaskExecute Success"); 555 } 556 PrioritizeCloudEnhancementTaskCompleteCallback(napi_env env,napi_status status,void * data)557 static void PrioritizeCloudEnhancementTaskCompleteCallback(napi_env env, napi_status status, void* data) 558 { 559 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 560 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 561 auto jsContext = make_unique<JSAsyncContextOutput>(); 562 jsContext->status = false; 563 napi_get_undefined(env, &jsContext->data); 564 napi_get_undefined(env, &jsContext->error); 565 if (context->error == ERR_DEFAULT) { 566 jsContext->status = true; 567 } else { 568 context->HandleError(env, jsContext->error); 569 } 570 571 if (context->work != nullptr) { 572 MediaLibraryNapiUtils::InvokeJSAsyncMethod( 573 env, context->deferred, context->callbackRef, context->work, *jsContext); 574 } 575 delete context; 576 } 577 JSPrioritizeCloudEnhancementTask(napi_env env,napi_callback_info info)578 napi_value CloudEnhancementNapi::JSPrioritizeCloudEnhancementTask(napi_env env, napi_callback_info info) 579 { 580 if (!MediaLibraryNapiUtils::IsSystemApp()) { 581 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 582 return nullptr; 583 } 584 MediaLibraryTracer tracer; 585 tracer.Start("JSPrioritizeCloudEnhancementTask"); 586 587 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 588 CHECK_COND(env, CloudEnhancementNapi::InitUserFileClient(env, info), JS_INNER_FAIL); 589 CHECK_COND_WITH_MESSAGE(env, ParseArgPrioritize(env, info, asyncContext) == napi_ok, "Failed to parse args"); 590 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSPrioritizeCloudEnhancementTask", 591 PrioritizeCloudEnhancementTaskExecute, PrioritizeCloudEnhancementTaskCompleteCallback); 592 } 593 ParseArgsCancelCloudEnhancementTasks(napi_env env,napi_callback_info info,unique_ptr<CloudEnhancementAsyncContext> & context)594 static napi_value ParseArgsCancelCloudEnhancementTasks(napi_env env, napi_callback_info info, 595 unique_ptr<CloudEnhancementAsyncContext>& context) 596 { 597 CHECK_COND_WITH_MESSAGE(env, 598 MediaLibraryNapiUtils::AsyncContextGetArgs(env, info, context, ARGS_ONE, ARGS_ONE) == napi_ok, 599 "Failed to get args"); 600 CHECK_COND(env, CloudEnhancementNapi::InitUserFileClient(env, info), JS_INNER_FAIL); 601 602 napi_valuetype valueType = napi_undefined; 603 CHECK_ARGS(env, napi_typeof(env, context->argv[PARAM0], &valueType), JS_INNER_FAIL); 604 CHECK_COND(env, valueType == napi_object, JS_INNER_FAIL); 605 606 vector<string> uris; 607 vector<napi_value> napiValues; 608 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetNapiValueArray(env, context->argv[PARAM0], napiValues)); 609 CHECK_COND_WITH_MESSAGE(env, !napiValues.empty(), "array is empty"); 610 CHECK_ARGS(env, napi_typeof(env, napiValues.front(), &valueType), JS_INNER_FAIL); 611 if (valueType == napi_object) { // array of asset object 612 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetUriArrayFromAssets(env, napiValues, uris)); 613 } else { 614 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Invalid type"); 615 return nullptr; 616 } 617 618 CHECK_COND_WITH_MESSAGE(env, !uris.empty(), "Failed to check empty array"); 619 for (const auto& uri : uris) { 620 NAPI_INFO_LOG("CloudEnhancementNapi ParseArgsCancelCloudEnhancementTasks: %{public}s", uri.c_str()); 621 CHECK_COND(env, uri.find(PhotoColumn::PHOTO_URI_PREFIX) != string::npos, JS_E_URI); 622 } 623 624 context->predicates.In(PhotoColumn::MEDIA_ID, uris); 625 context->uris.assign(uris.begin(), uris.end()); 626 RETURN_NAPI_TRUE(env); 627 } 628 CancelCloudEnhancementTasksExecute(napi_env env,void * data)629 static void CancelCloudEnhancementTasksExecute(napi_env env, void* data) 630 { 631 MediaLibraryTracer tracer; 632 tracer.Start("CancelCloudEnhancementTasksExecute"); 633 634 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 635 string uriStr = PAH_CLOUD_ENHANCEMENT_CANCEL; 636 Uri cancelTaskUri(uriStr); 637 string fileUri = context->uris.front(); 638 context->valuesBucket.Put(MediaColumn::MEDIA_ID, fileUri); 639 int32_t changeRows = UserFileClient::Update(cancelTaskUri, context->predicates, context->valuesBucket); 640 if (changeRows < 0) { 641 context->SaveError(changeRows); 642 NAPI_ERR_LOG("Cancel cloud enhancement tasks failed, err: %{public}d", changeRows); 643 } 644 NAPI_INFO_LOG("CancelCloudEnhancementTasksExecute Success"); 645 } 646 CancelCloudEnhancementTasksCompleteCallback(napi_env env,napi_status status,void * data)647 static void CancelCloudEnhancementTasksCompleteCallback(napi_env env, napi_status status, void* data) 648 { 649 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 650 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 651 auto jsContext = make_unique<JSAsyncContextOutput>(); 652 jsContext->status = false; 653 napi_get_undefined(env, &jsContext->data); 654 napi_get_undefined(env, &jsContext->error); 655 if (context->error == ERR_DEFAULT) { 656 jsContext->status = true; 657 } else { 658 context->HandleError(env, jsContext->error); 659 } 660 661 if (context->work != nullptr) { 662 MediaLibraryNapiUtils::InvokeJSAsyncMethod( 663 env, context->deferred, context->callbackRef, context->work, *jsContext); 664 } 665 delete context; 666 } 667 JSCancelCloudEnhancementTasks(napi_env env,napi_callback_info info)668 napi_value CloudEnhancementNapi::JSCancelCloudEnhancementTasks(napi_env env, napi_callback_info info) 669 { 670 if (!MediaLibraryNapiUtils::IsSystemApp()) { 671 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 672 return nullptr; 673 } 674 MediaLibraryTracer tracer; 675 tracer.Start("JSCancelCloudEnhancementTasks"); 676 677 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 678 CHECK_COND_WITH_MESSAGE(env, ParseArgsCancelCloudEnhancementTasks(env, info, asyncContext), "Failed to parse args"); 679 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "CancelCloudEnhancementTasks", 680 CancelCloudEnhancementTasksExecute, CancelCloudEnhancementTasksCompleteCallback); 681 } 682 CancelAllCloudEnhancementTasksExecute(napi_env env,void * data)683 static void CancelAllCloudEnhancementTasksExecute(napi_env env, void* data) 684 { 685 MediaLibraryTracer tracer; 686 tracer.Start("CancelAllCloudEnhancementTasksExecute"); 687 688 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 689 string uriStr = PAH_CLOUD_ENHANCEMENT_CANCEL_ALL; 690 Uri cancelAllTaskUri(uriStr); 691 context->valuesBucket.Put(PhotoColumn::PHOTO_STRONG_ASSOCIATION, STRONG_ASSOCIATION); 692 int32_t changeRows = UserFileClient::Update(cancelAllTaskUri, context->predicates, context->valuesBucket); 693 if (changeRows < 0) { 694 context->SaveError(changeRows); 695 NAPI_ERR_LOG("Cancel all cloud enhancement tasks failed, err: %{public}d", changeRows); 696 } 697 NAPI_INFO_LOG("CancelAllCloudEnhancementTasksExecute Success"); 698 } 699 CancelAllCloudEnhancementTasksCompleteCallback(napi_env env,napi_status status,void * data)700 static void CancelAllCloudEnhancementTasksCompleteCallback(napi_env env, napi_status status, void* data) 701 { 702 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 703 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 704 auto jsContext = make_unique<JSAsyncContextOutput>(); 705 jsContext->status = false; 706 napi_get_undefined(env, &jsContext->data); 707 napi_get_undefined(env, &jsContext->error); 708 if (context->error == ERR_DEFAULT) { 709 jsContext->status = true; 710 } else { 711 context->HandleError(env, jsContext->error); 712 } 713 714 if (context->work != nullptr) { 715 MediaLibraryNapiUtils::InvokeJSAsyncMethod( 716 env, context->deferred, context->callbackRef, context->work, *jsContext); 717 } 718 delete context; 719 } 720 JSCancelAllCloudEnhancementTasks(napi_env env,napi_callback_info info)721 napi_value CloudEnhancementNapi::JSCancelAllCloudEnhancementTasks(napi_env env, napi_callback_info info) 722 { 723 if (!MediaLibraryNapiUtils::IsSystemApp()) { 724 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 725 return nullptr; 726 } 727 MediaLibraryTracer tracer; 728 tracer.Start("JSCancelAllCloudEnhancementTasks"); 729 730 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 731 CHECK_COND_WITH_MESSAGE(env, 732 MediaLibraryNapiUtils::AsyncContextGetArgs(env, info, asyncContext, ARGS_ZERO, ARGS_ZERO) == napi_ok, 733 "Failed to parse args"); 734 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "CancelAllCloudEnhancementTasks", 735 CancelAllCloudEnhancementTasksExecute, CancelAllCloudEnhancementTasksCompleteCallback); 736 } 737 ParseArgQuery(napi_env env,napi_callback_info info,unique_ptr<CloudEnhancementAsyncContext> & context)738 static napi_status ParseArgQuery(napi_env env, napi_callback_info info, 739 unique_ptr<CloudEnhancementAsyncContext>& context) 740 { 741 napi_value thisVar = nullptr; 742 context->argc = ARGS_ONE; 743 GET_JS_ARGS(env, info, context->argc, context->argv, thisVar); 744 745 if (CloudEnhancementNapi::ParseArgGetPhotoAsset(env, context->argv[PARAM0], context->fileId, context->photoUri, 746 context->displayName) != napi_ok) { 747 NAPI_ERR_LOG("requestMedia ParseArgGetPhotoAsset error"); 748 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "requestMedia ParseArgGetPhotoAsset error"); 749 return napi_invalid_arg; 750 } 751 752 NAPI_INFO_LOG("Parse Arg: %{public}d, %{private}s, %{public}s", context->fileId, context->photoUri.c_str(), 753 context->displayName.c_str()); 754 755 return napi_ok; 756 } 757 FillTaskStageWithClientQuery(CloudEnhancementAsyncContext * context,string & photoId)758 static void FillTaskStageWithClientQuery(CloudEnhancementAsyncContext* context, string &photoId) 759 { 760 #ifdef ABILITY_CLOUD_ENHANCEMENT_SUPPORT 761 lock_guard<mutex> lock(mtx); 762 InitCloudEnhancementFunc(); 763 if (dynamicHandler == nullptr) { 764 NAPI_ERR_LOG("dynamicHandler is nullptr!"); 765 return; 766 } 767 InitEnhancementClient(); 768 if (clientWrapper == nullptr) { 769 NAPI_ERR_LOG("clientWrapper is nullptr!"); 770 return; 771 } 772 if (!IsConnected(clientWrapper)) { 773 LoadSA(); 774 } 775 MediaEnhanceBundleHandle* bundle = CreateBundle(); 776 bundle = QueryTaskState(photoId); 777 if (bundle == nullptr) { 778 NAPI_ERR_LOG("queryTaskState result is nullptr!"); 779 DestroyEnhancementClient(); 780 return; 781 } 782 int32_t currentState = GetInt(bundle, MediaEnhance_Query::CURRENT_STATE); 783 NAPI_INFO_LOG("clientQueryTaskStateFunc stage = %{public}d", currentState); 784 if (currentState == MediaEnhance_Query::EN_EXCEPTION) { 785 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_EXCEPTION; 786 } else if (currentState == MediaEnhance_Query::EN_PREPARING) { 787 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_PREPARING; 788 } else if (currentState == MediaEnhance_Query::EN_UPLOADING) { 789 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_UPLOADING; 790 context->transferredFileSize_ = GetInt(bundle, MediaEnhance_Query::UPLOAD_PROGRESS); 791 context->totalFileSize_ = GetInt(bundle, MediaEnhance_Query::UPLOAD_SIZE); 792 } else if (currentState == MediaEnhance_Query::EN_EXECUTING) { 793 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_EXECUTING; 794 context->expectedDuration_ = GetInt(bundle, MediaEnhance_Query::EXECUTE_TIME); 795 } else if (currentState == MediaEnhance_Query::EN_DOWNLOADING) { 796 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_DOWNLOADING; 797 context->transferredFileSize_ = GetInt(bundle, MediaEnhance_Query::DOWNLOAD_PROGRESS); 798 context->totalFileSize_ = GetInt(bundle, MediaEnhance_Query::DOWNLOAD_SIZE); 799 } 800 DestroyBundle(bundle); 801 DestroyEnhancementClient(); 802 #endif 803 } 804 QueryCloudEnhancementTaskStateExecute(napi_env env,void * data)805 static void QueryCloudEnhancementTaskStateExecute(napi_env env, void* data) 806 { 807 MediaLibraryTracer tracer; 808 tracer.Start("QueryCloudEnhancementTaskStateExecute"); 809 810 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 811 string uriStr = PAH_CLOUD_ENHANCEMENT_QUERY; 812 Uri queryTaskUri(uriStr); 813 vector<string> columns = { 814 MediaColumn::MEDIA_ID, PhotoColumn::PHOTO_ID, 815 PhotoColumn::PHOTO_CE_AVAILABLE, PhotoColumn::PHOTO_CE_STATUS_CODE 816 }; 817 int errCode = 0; 818 context->predicates.EqualTo(MediaColumn::MEDIA_ID, context->photoUri); 819 auto resultSet = UserFileClient::Query(queryTaskUri, context->predicates, columns, errCode); 820 if (resultSet == nullptr || resultSet->GoToNextRow() != E_OK) { 821 NAPI_ERR_LOG("ResultSet is nullptr, errCode is %{public}d", errCode); 822 context->SaveError(JS_INNER_FAIL); 823 return; 824 } 825 int32_t fileId = get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32)); 826 string photoId = get<string>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_ID, resultSet, TYPE_STRING)); 827 int32_t ceAvailable = 828 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_CE_AVAILABLE, resultSet, TYPE_INT32)); 829 int32_t CEErrorCode = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_CE_STATUS_CODE, 830 resultSet, TYPE_INT32)); 831 NAPI_INFO_LOG("query fileId: %{public}d, photoId: %{private}s, ceAvailable: %{public}d", 832 fileId, photoId.c_str(), ceAvailable); 833 834 if (ceAvailable == static_cast<int32_t>(CE_AVAILABLE::NOT_SUPPORT)) { 835 NAPI_ERR_LOG("photo not support cloud enhancement, fileId: %{public}d", fileId); 836 return; 837 } 838 // 任务成功或失败,不能再查云增强,否则会让云增强误报准备中 839 if (ceAvailable == static_cast<int32_t>(CE_AVAILABLE::SUCCESS)) { 840 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_COMPLETED; 841 return; 842 } 843 if (ceAvailable == static_cast<int32_t>(CE_AVAILABLE::FAILED_RETRY) || 844 ceAvailable == static_cast<int32_t>(CE_AVAILABLE::FAILED)) { 845 context->cloudEnhancementTaskStage_ = CloudEnhancementTaskStage::TASK_STAGE_FAILED; 846 context->statusCode_ = CEErrorCode; 847 NAPI_INFO_LOG("TASK_STAGE_FAILED, fileId: %{public}d, statusCode: %{public}d", fileId, ceAvailable); 848 return; 849 } 850 FillTaskStageWithClientQuery(context, photoId); 851 } 852 QueryCloudEnhancementTaskStateCompleteCallback(napi_env env,napi_status status,void * data)853 static void QueryCloudEnhancementTaskStateCompleteCallback(napi_env env, napi_status status, void* data) 854 { 855 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 856 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 857 auto jsContext = make_unique<JSAsyncContextOutput>(); 858 jsContext->status = false; 859 napi_get_undefined(env, &jsContext->data); 860 napi_get_undefined(env, &jsContext->error); 861 if (context->error == ERR_DEFAULT) { 862 napi_value cloudEnhancementTaskState = 863 CloudEnhancementTaskStateNapi::NewCloudEnhancementTaskStateNapi(env, context); 864 jsContext->data = cloudEnhancementTaskState; 865 jsContext->status = true; 866 } else { 867 context->HandleError(env, jsContext->error); 868 } 869 870 if (context->work != nullptr) { 871 MediaLibraryNapiUtils::InvokeJSAsyncMethod( 872 env, context->deferred, context->callbackRef, context->work, *jsContext); 873 } 874 delete context; 875 } 876 JSQueryCloudEnhancementTaskState(napi_env env,napi_callback_info info)877 napi_value CloudEnhancementNapi::JSQueryCloudEnhancementTaskState(napi_env env, napi_callback_info info) 878 { 879 if (!MediaLibraryNapiUtils::IsSystemApp()) { 880 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 881 return nullptr; 882 } 883 MediaLibraryTracer tracer; 884 tracer.Start("JSQueryCloudEnhancementTaskState"); 885 886 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 887 CHECK_COND(env, CloudEnhancementNapi::InitUserFileClient(env, info), JS_INNER_FAIL); 888 CHECK_COND_WITH_MESSAGE(env, ParseArgQuery(env, info, asyncContext) == napi_ok, "Failed to parse args"); 889 890 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "QueryCloudEnhancementTaskState", 891 QueryCloudEnhancementTaskStateExecute, QueryCloudEnhancementTaskStateCompleteCallback); 892 } 893 SyncCloudEnhancementTaskStatusExecute(napi_env env,void * data)894 static void SyncCloudEnhancementTaskStatusExecute(napi_env env, void* data) 895 { 896 MediaLibraryTracer tracer; 897 tracer.Start("SyncCloudEnhancementTaskStatusExecute"); 898 899 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 900 string uriStr = PAH_CLOUD_ENHANCEMENT_SYNC; 901 Uri syncUri(uriStr); 902 context->valuesBucket.Put(PhotoColumn::PHOTO_STRONG_ASSOCIATION, STRONG_ASSOCIATION); 903 int32_t changeRows = UserFileClient::Update(syncUri, context->predicates, context->valuesBucket); 904 if (changeRows < 0) { 905 context->SaveError(changeRows); 906 NAPI_ERR_LOG("sync cloud enhancement failed, err: %{public}d", changeRows); 907 } 908 NAPI_INFO_LOG("CloudEnhancementNapi SyncCloudEnhancementTaskStatusExecute Success"); 909 } 910 SyncCloudEnhancementTaskStatusCompleteCallback(napi_env env,napi_status status,void * data)911 static void SyncCloudEnhancementTaskStatusCompleteCallback(napi_env env, napi_status status, void* data) 912 { 913 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 914 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 915 auto jsContext = make_unique<JSAsyncContextOutput>(); 916 jsContext->status = false; 917 napi_get_undefined(env, &jsContext->data); 918 napi_get_undefined(env, &jsContext->error); 919 if (context->error == ERR_DEFAULT) { 920 jsContext->status = true; 921 } else { 922 context->HandleError(env, jsContext->error); 923 } 924 925 if (context->work != nullptr) { 926 MediaLibraryNapiUtils::InvokeJSAsyncMethod( 927 env, context->deferred, context->callbackRef, context->work, *jsContext); 928 } 929 delete context; 930 } 931 JSSyncCloudEnhancementTaskStatus(napi_env env,napi_callback_info info)932 napi_value CloudEnhancementNapi::JSSyncCloudEnhancementTaskStatus(napi_env env, napi_callback_info info) 933 { 934 if (!MediaLibraryNapiUtils::IsSystemApp()) { 935 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 936 return nullptr; 937 } 938 MediaLibraryTracer tracer; 939 tracer.Start("JSSyncCloudEnhancementTaskStatus"); 940 941 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 942 CHECK_COND_WITH_MESSAGE(env, 943 MediaLibraryNapiUtils::AsyncContextGetArgs(env, info, asyncContext, ARGS_ZERO, ARGS_ZERO) == napi_ok, 944 "Failed to parse args"); 945 946 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "SyncCloudEnhancementTaskStatus", 947 SyncCloudEnhancementTaskStatusExecute, SyncCloudEnhancementTaskStatusCompleteCallback); 948 } 949 GetPairAsset()950 bool CloudEnhancementAsyncContext::GetPairAsset() 951 { 952 if (fetchFileResult->GetCount() != 1) { 953 NAPI_ERR_LOG("Object number of fetchfileResult is not one"); 954 return false; 955 } 956 fileAsset = fetchFileResult->GetFirstObject(); 957 if (fileAsset == nullptr) { 958 NAPI_ERR_LOG("Fail to get fileAsset from fetchFileResult"); 959 return false; 960 } 961 return true; 962 } 963 GetCloudEnhancementPairExecute(napi_env env,void * data)964 static void GetCloudEnhancementPairExecute(napi_env env, void* data) 965 { 966 MediaLibraryTracer tracer; 967 tracer.Start("GetCloudEnhancementPairExecute"); 968 969 auto* context = static_cast<CloudEnhancementAsyncContext*>(data); 970 CHECK_NULL_PTR_RETURN_VOID(context, "AsyncContext is null"); 971 std::string uriStr = PAH_CLOUD_ENHANCEMENT_GET_PAIR; 972 Uri getPairUri(uriStr); 973 std::vector<std::string> columns; 974 int errCode = 0; 975 NAPI_INFO_LOG("CloudEnhancementNAPI context->photoUri is %{private}s", context->photoUri.c_str()); 976 context->predicates.EqualTo(MediaColumn::MEDIA_ID, context->photoUri); 977 shared_ptr<DataShare::DataShareResultSet> resultSet = 978 UserFileClient::Query(getPairUri, context->predicates, columns, errCode); 979 if (resultSet == nullptr || resultSet->GoToNextRow() != E_OK) { 980 NAPI_ERR_LOG("Resultset is nullptr, errCode is %{public}d", errCode); 981 context->SaveError(JS_INNER_FAIL); 982 return; 983 } 984 context->fetchFileResult = make_unique<FetchResult<FileAsset>>(move(resultSet)); 985 if (!context->GetPairAsset()) { 986 NAPI_ERR_LOG("Fail to getPairAsset"); 987 return; 988 } 989 990 NAPI_INFO_LOG("CloudEnhancementNapi GetCloudEnhancementPairExecute Success"); 991 } 992 GetNapiPairFileAsset(napi_env env,CloudEnhancementAsyncContext * context,unique_ptr<JSAsyncContextOutput> & jsContext)993 static void GetNapiPairFileAsset(napi_env env, CloudEnhancementAsyncContext *context, 994 unique_ptr<JSAsyncContextOutput> &jsContext) 995 { 996 // Create PhotiAsset object using the contents of fileAsset 997 if (context->fileAsset == nullptr) { 998 NAPI_ERR_LOG("No fetch file result found!"); 999 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT, 1000 "Failed to obtain Fetch File Result"); 1001 return; 1002 } 1003 if (context->fileAsset->GetPhotoEditTime() != 0) { 1004 NAPI_WARN_LOG("PhotoAsset is edited"); 1005 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT, 1006 "Failed to obtain Fetch File Result"); 1007 return; 1008 } 1009 context->fileAsset->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER); 1010 napi_value jsFileAsset = FileAssetNapi::CreateFileAsset(env, context->fileAsset); 1011 if (jsFileAsset == nullptr) { 1012 MediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT, 1013 "Failed to create js object for Fetch File Result"); 1014 } else { 1015 jsContext->data = jsFileAsset; 1016 jsContext->status = true; 1017 napi_get_undefined(env, &jsContext->error); 1018 } 1019 } 1020 GetCloudEnhancementPairCompleteCallback(napi_env env,napi_status status,void * data)1021 static void GetCloudEnhancementPairCompleteCallback(napi_env env, napi_status status, void* data) 1022 { 1023 MediaLibraryTracer tracer; 1024 tracer.Start("GetCloudEnhancementPairCompleteCallback"); 1025 1026 CloudEnhancementAsyncContext *context = static_cast<CloudEnhancementAsyncContext*>(data); 1027 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null"); 1028 1029 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>(); 1030 jsContext->status = false; 1031 napi_get_undefined(env, &jsContext->data); 1032 1033 if (context->error != ERR_DEFAULT) { 1034 context->HandleError(env, jsContext->error); 1035 } else { 1036 GetNapiPairFileAsset(env, context, jsContext); 1037 } 1038 1039 tracer.Finish(); 1040 if (context->work != nullptr) { 1041 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, 1042 context->work, *jsContext); 1043 } 1044 delete context; 1045 } 1046 JSGetCloudEnhancementPair(napi_env env,napi_callback_info info)1047 napi_value CloudEnhancementNapi::JSGetCloudEnhancementPair(napi_env env, napi_callback_info info) 1048 { 1049 MediaLibraryTracer tracer; 1050 tracer.Start("JSGetCloudEnhancementPair"); 1051 if (!MediaLibraryNapiUtils::IsSystemApp()) { 1052 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); 1053 return nullptr; 1054 } 1055 auto asyncContext = make_unique<CloudEnhancementAsyncContext>(); 1056 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER; 1057 asyncContext->assetType = TYPE_PHOTO; 1058 1059 CHECK_COND(env, CloudEnhancementNapi::InitUserFileClient(env, info), JS_INNER_FAIL); 1060 CHECK_COND_WITH_MESSAGE(env, ParseArgQuery(env, info, asyncContext) == napi_ok, "Failed to parse args"); 1061 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "GetCloudEnhancementPair", 1062 GetCloudEnhancementPairExecute, GetCloudEnhancementPairCompleteCallback); 1063 } 1064 } // namespace OHOS::Media 1065