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