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