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