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