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