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