1 /*
2 * Copyright (C) 2022 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 #define MLOG_TAG "SendableMediaLibraryNapiUtils"
16
17 #include "sendable_medialibrary_napi_utils.h"
18
19 #include "basic/result_set.h"
20 #include "datashare_predicates.h"
21 #include "location_column.h"
22 #include "ipc_skeleton.h"
23 #include "js_proxy.h"
24 #include "sendable_photo_album_napi.h"
25 #include "sendable_fetch_file_result_napi.h"
26 #include "sendable_photo_access_helper_napi.h"
27 #include "media_device_column.h"
28 #include "media_file_uri.h"
29 #include "media_file_utils.h"
30 #include "media_library_napi.h"
31 #include "medialibrary_client_errno.h"
32 #include "medialibrary_db_const.h"
33 #include "medialibrary_errno.h"
34 #include "medialibrary_napi_utils.h"
35 #include "medialibrary_tracer.h"
36 #include "photo_album_napi.h"
37 #include "photo_map_column.h"
38 #include "smart_album_napi.h"
39 #include "tokenid_kit.h"
40 #include "userfile_client.h"
41 #include "vision_album_column.h"
42 #include "vision_column.h"
43 #include "vision_face_tag_column.h"
44 #include "vision_pose_column.h"
45 #include "vision_image_face_column.h"
46 #include "userfile_manager_types.h"
47
48 using namespace std;
49 using namespace OHOS::DataShare;
50
51 namespace OHOS {
52 namespace Media {
53 static const string EMPTY_STRING = "";
54 using json = nlohmann::json;
55 using SendablePAHAsyncContext = SendablePhotoAccessHelperAsyncContext;
56 using SendablePANAsyncContext = SendablePhotoAlbumNapiAsyncContext;
57 using SendableFAAsyncContext = SendableFileAssetAsyncContext;
58
GetUInt32(napi_env env,napi_value arg,uint32_t & value)59 napi_status SendableMediaLibraryNapiUtils::GetUInt32(napi_env env, napi_value arg, uint32_t &value)
60 {
61 napi_valuetype valueType = napi_undefined;
62 CHECK_STATUS_RET(napi_typeof(env, arg, &valueType), "Failed to get type");
63 CHECK_COND_RET(valueType == napi_number, napi_number_expected, "Type is not as expected number");
64 CHECK_STATUS_RET(napi_get_value_uint32(env, arg, &value), "Failed to get uint32 value");
65 return napi_ok;
66 }
67
GetInt32(napi_env env,napi_value arg,int32_t & value)68 napi_status SendableMediaLibraryNapiUtils::GetInt32(napi_env env, napi_value arg, int32_t &value)
69 {
70 napi_valuetype valueType = napi_undefined;
71 CHECK_STATUS_RET(napi_typeof(env, arg, &valueType), "Failed to get type");
72 CHECK_COND_RET(valueType == napi_number, napi_number_expected, "Type is not as expected number");
73 CHECK_STATUS_RET(napi_get_value_int32(env, arg, &value), "Failed to get int32 value");
74 return napi_ok;
75 }
76
GetParamBool(napi_env env,napi_value arg,bool & value)77 napi_status SendableMediaLibraryNapiUtils::GetParamBool(napi_env env, napi_value arg, bool &value)
78 {
79 napi_valuetype valueType = napi_undefined;
80 CHECK_STATUS_RET(napi_typeof(env, arg, &valueType), "Failed to get type");
81 CHECK_COND_RET(valueType == napi_boolean, napi_boolean_expected, "Type is not as expected boolean");
82 CHECK_STATUS_RET(napi_get_value_bool(env, arg, &value), "Failed to get param");
83 return napi_ok;
84 }
85
GetParamFunction(napi_env env,napi_value arg,napi_ref & callbackRef)86 napi_status SendableMediaLibraryNapiUtils::GetParamFunction(napi_env env, napi_value arg, napi_ref &callbackRef)
87 {
88 napi_valuetype valueType = napi_undefined;
89 CHECK_STATUS_RET(napi_typeof(env, arg, &valueType), "Failed to get type");
90 CHECK_COND_RET(valueType == napi_function, napi_function_expected, "Type is not as expected function");
91 CHECK_STATUS_RET(napi_create_reference(env, arg, NAPI_INIT_REF_COUNT, &callbackRef), "Failed to make callbackref");
92 return napi_ok;
93 }
94
GetParamStr(napi_env env,napi_value arg,const size_t size,string & result)95 static napi_status GetParamStr(napi_env env, napi_value arg, const size_t size, string &result)
96 {
97 size_t res = 0;
98 unique_ptr<char[]> buffer = make_unique<char[]>(size);
99 CHECK_COND_RET(buffer != nullptr, napi_invalid_arg, "Failed to alloc buffer for parameter");
100 napi_valuetype valueType = napi_undefined;
101 CHECK_STATUS_RET(napi_typeof(env, arg, &valueType), "Failed to get type");
102 CHECK_COND_RET(valueType == napi_string, napi_string_expected, "Type is not as expected string");
103 CHECK_STATUS_RET(napi_get_value_string_utf8(env, arg, buffer.get(), size, &res), "Failed to get string value");
104 result = string(buffer.get());
105 return napi_ok;
106 }
107
GetParamStringWithLength(napi_env env,napi_value arg,int32_t maxLen,string & result)108 napi_status SendableMediaLibraryNapiUtils::GetParamStringWithLength(napi_env env, napi_value arg, int32_t maxLen,
109 string &result)
110 {
111 CHECK_STATUS_RET(GetParamStr(env, arg, maxLen, result), "Failed to get string parameter");
112 return napi_ok;
113 }
114
GetParamStringPathMax(napi_env env,napi_value arg,string & result)115 napi_status SendableMediaLibraryNapiUtils::GetParamStringPathMax(napi_env env, napi_value arg, string &result)
116 {
117 CHECK_STATUS_RET(GetParamStr(env, arg, PATH_MAX, result), "Failed to get string parameter");
118 return napi_ok;
119 }
120
GetProperty(napi_env env,const napi_value arg,const string & propName,string & propValue)121 napi_status SendableMediaLibraryNapiUtils::GetProperty(napi_env env, const napi_value arg, const string &propName,
122 string &propValue)
123 {
124 bool present = false;
125 napi_value property = nullptr;
126 CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present),
127 "Failed to check property name");
128 if (present) {
129 CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
130 CHECK_STATUS_RET(GetParamStringPathMax(env, property, propValue), "Failed to get string buffer");
131 }
132 return napi_ok;
133 }
134
GetStringArray(napi_env env,napi_value arg,vector<string> & array)135 napi_status SendableMediaLibraryNapiUtils::GetStringArray(napi_env env, napi_value arg, vector<string> &array)
136 {
137 bool isArray = false;
138 uint32_t len = 0;
139 CHECK_STATUS_RET(napi_is_array(env, arg, &isArray), "Failed to check array type");
140 CHECK_COND_RET(isArray, napi_array_expected, "Expected array type");
141 CHECK_STATUS_RET(napi_get_array_length(env, arg, &len), "Failed to get array length");
142 for (uint32_t i = 0; i < len; i++) {
143 napi_value item = nullptr;
144 string val;
145 CHECK_STATUS_RET(napi_get_element(env, arg, i, &item), "Failed to get array item");
146 CHECK_STATUS_RET(GetParamStringPathMax(env, item, val), "Failed to get string buffer");
147 array.push_back(val);
148 }
149 return napi_ok;
150 }
151
GetArrayProperty(napi_env env,napi_value arg,const string & propName,vector<string> & array)152 napi_status SendableMediaLibraryNapiUtils::GetArrayProperty(napi_env env, napi_value arg, const string &propName,
153 vector<string> &array)
154 {
155 bool present = false;
156 CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present), "Failed to check property name");
157 if (present) {
158 napi_value property = nullptr;
159 CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property),
160 "Failed to get selectionArgs property");
161 GetStringArray(env, property, array);
162 }
163 return napi_ok;
164 }
165
HasCallback(napi_env env,const size_t argc,const napi_value argv[],bool & isCallback)166 napi_status SendableMediaLibraryNapiUtils::HasCallback(napi_env env, const size_t argc, const napi_value argv[],
167 bool &isCallback)
168 {
169 isCallback = false;
170 if (argc < ARGS_ONE) {
171 return napi_ok;
172 }
173 napi_valuetype valueType = napi_undefined;
174 CHECK_STATUS_RET(napi_typeof(env, argv[argc - 1], &valueType), "Failed to get type");
175 isCallback = (valueType == napi_function);
176 return napi_ok;
177 }
178
hasFetchOpt(napi_env env,const napi_value arg,bool & hasFetchOpt)179 napi_status SendableMediaLibraryNapiUtils::hasFetchOpt(napi_env env, const napi_value arg, bool &hasFetchOpt)
180 {
181 hasFetchOpt = false;
182 napi_valuetype valueType = napi_undefined;
183 CHECK_STATUS_RET(napi_typeof(env, arg, &valueType), "Failed to get type");
184 if (valueType != napi_object) {
185 hasFetchOpt = false;
186 return napi_ok;
187 }
188 CHECK_STATUS_RET(napi_has_named_property(env, arg, "selections", &hasFetchOpt),
189 "Failed to get property selections");
190 return napi_ok;
191 }
192
GetMediaTypeFromUri(const string & uri)193 MediaType SendableMediaLibraryNapiUtils::GetMediaTypeFromUri(const string &uri)
194 {
195 if (uri.find(MEDIALIBRARY_IMAGE_URI) != string::npos) {
196 return MediaType::MEDIA_TYPE_IMAGE;
197 } else if (uri.find(MEDIALIBRARY_VIDEO_URI) != string::npos) {
198 return MediaType::MEDIA_TYPE_VIDEO;
199 } else if (uri.find(MEDIALIBRARY_AUDIO_URI) != string::npos) {
200 return MediaType::MEDIA_TYPE_AUDIO;
201 } else if (uri.find(MEDIALIBRARY_FILE_URI) != string::npos) {
202 return MediaType::MEDIA_TYPE_FILE;
203 }
204 return MediaType::MEDIA_TYPE_ALL;
205 }
206
HandleSpecialDateTypePredicate(const OperationItem & item,vector<OperationItem> & operations,const FetchOptionType & fetchOptType)207 static bool HandleSpecialDateTypePredicate(const OperationItem &item,
208 vector<OperationItem> &operations, const FetchOptionType &fetchOptType)
209 {
210 constexpr int32_t FIELD_IDX = 0;
211 constexpr int32_t VALUE_IDX = 1;
212 vector<string>dateTypes = { MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_DATE_TRASHED, MEDIA_DATA_DB_DATE_MODIFIED,
213 MEDIA_DATA_DB_DATE_TAKEN };
214 string dateType = item.GetSingle(FIELD_IDX);
215 auto it = find(dateTypes.begin(), dateTypes.end(), dateType);
216 if (it != dateTypes.end() && item.operation != DataShare::ORDER_BY_ASC &&
217 item.operation != DataShare::ORDER_BY_DESC) {
218 dateType += "_s";
219 operations.push_back({ item.operation, { dateType, static_cast<double>(item.GetSingle(VALUE_IDX)) } });
220 return true;
221 }
222 if (DATE_TRANSITION_MAP.count(dateType) != 0) {
223 dateType = DATE_TRANSITION_MAP.at(dateType);
224 operations.push_back({ item.operation, { dateType, static_cast<double>(item.GetSingle(VALUE_IDX)) } });
225 return true;
226 }
227 return false;
228 }
229
230 template <class AsyncContext>
HandleSpecialPredicate(AsyncContext & context,shared_ptr<DataShareAbsPredicates> & predicate,const FetchOptionType & fetchOptType)231 bool SendableMediaLibraryNapiUtils::HandleSpecialPredicate(AsyncContext &context,
232 shared_ptr<DataShareAbsPredicates> &predicate, const FetchOptionType &fetchOptType)
233 {
234 constexpr int32_t FIELD_IDX = 0;
235 constexpr int32_t VALUE_IDX = 1;
236 vector<OperationItem> operations;
237 auto &items = predicate->GetOperationList();
238 for (auto &item : items) {
239 if (item.singleParams.empty()) {
240 operations.push_back(item);
241 continue;
242 }
243 if (HandleSpecialDateTypePredicate(item, operations, fetchOptType)) {
244 continue;
245 }
246 // change uri ->file id
247 // get networkid
248 // replace networkid with file id
249 if (static_cast<string>(item.GetSingle(FIELD_IDX)) == DEVICE_DB_NETWORK_ID) {
250 if (item.operation != DataShare::EQUAL_TO || static_cast<string>(item.GetSingle(VALUE_IDX)).empty()) {
251 NAPI_ERR_LOG("DEVICE_DB_NETWORK_ID predicates not support %{public}d", item.operation);
252 return false;
253 }
254 context->networkId = static_cast<string>(item.GetSingle(VALUE_IDX));
255 continue;
256 }
257 if (static_cast<string>(item.GetSingle(FIELD_IDX)) == MEDIA_DATA_DB_URI) {
258 if (item.operation != DataShare::EQUAL_TO) {
259 NAPI_ERR_LOG("MEDIA_DATA_DB_URI predicates not support %{public}d", item.operation);
260 return false;
261 }
262 string uri = static_cast<string>(item.GetSingle(VALUE_IDX));
263 MediaFileUri::RemoveAllFragment(uri);
264 MediaFileUri fileUri(uri);
265 context->uri = uri;
266 if ((fetchOptType != ALBUM_FETCH_OPT) && (!fileUri.IsApi10())) {
267 fileUri = MediaFileUri(MediaFileUtils::GetRealUriFromVirtualUri(uri));
268 }
269 context->networkId = fileUri.GetNetworkId();
270 string field = (fetchOptType == ALBUM_FETCH_OPT) ? PhotoAlbumColumns::ALBUM_ID : MEDIA_DATA_DB_ID;
271 operations.push_back({ item.operation, { field, fileUri.GetFileId() } });
272 continue;
273 }
274 if (static_cast<string>(item.GetSingle(FIELD_IDX)) == PENDING_STATUS) {
275 // do not query pending files below API11
276 continue;
277 }
278 if (LOCATION_PARAM_MAP.find(static_cast<string>(item.GetSingle(FIELD_IDX))) != LOCATION_PARAM_MAP.end()) {
279 continue;
280 }
281 operations.push_back(item);
282 }
283 context->predicates = DataSharePredicates(move(operations));
284 return true;
285 }
286
287 template <class AsyncContext>
GetLocationPredicate(AsyncContext & context,shared_ptr<DataShareAbsPredicates> & predicate)288 bool SendableMediaLibraryNapiUtils::GetLocationPredicate(AsyncContext &context,
289 shared_ptr<DataShareAbsPredicates> &predicate)
290 {
291 constexpr int32_t FIELD_IDX = 0;
292 constexpr int32_t VALUE_IDX = 1;
293 map<string, string> locationMap;
294 auto &items = predicate->GetOperationList();
295 for (auto &item : items) {
296 if (item.singleParams.empty()) {
297 continue;
298 }
299 if (LOCATION_PARAM_MAP.find(static_cast<string>(item.GetSingle(FIELD_IDX))) != LOCATION_PARAM_MAP.end()) {
300 if (item.operation != DataShare::EQUAL_TO) {
301 NAPI_ERR_LOG("location predicates not support %{public}d", item.operation);
302 return false;
303 }
304 string param = static_cast<string>(item.GetSingle(FIELD_IDX));
305 string value = static_cast<string>(item.GetSingle(VALUE_IDX));
306 locationMap.insert(make_pair(param, value));
307 if (param == DIAMETER) {
308 continue;
309 }
310 if (LOCATION_PARAM_MAP.at(param).second == DataShare::GREATER_THAN_OR_EQUAL_TO) {
311 context->predicates.GreaterThanOrEqualTo(LOCATION_PARAM_MAP.at(param).first, value);
312 continue;
313 }
314 if (LOCATION_PARAM_MAP.at(param).second == DataShare::LESS_THAN) {
315 context->predicates.LessThan(LOCATION_PARAM_MAP.at(param).first, value);
316 continue;
317 }
318 if (LOCATION_PARAM_MAP.at(param).second == DataShare::EQUAL_TO) {
319 context->predicates.EqualTo(LOCATION_PARAM_MAP.at(param).first, value);
320 continue;
321 }
322 }
323 }
324
325 if (locationMap.count(DIAMETER) == 1 && locationMap.count(START_LATITUDE) == 1
326 && locationMap.count(START_LONGITUDE) == 1) {
327 // 0.5:Used for rounding down
328 string latitudeIndex = "round((latitude - " + locationMap.at(START_LATITUDE) + ") / " +
329 locationMap.at(DIAMETER) + " - 0.5)";
330 string longitudeIndex = "round((longitude - " + locationMap.at(START_LONGITUDE) + ") / " +
331 locationMap.at(DIAMETER) + " - 0.5)";
332 string albumName = LATITUDE + "||'_'||" + LONGITUDE + "||'_'||" + latitudeIndex + "||'_'||" +
333 longitudeIndex + " AS " + ALBUM_NAME;
334 context->fetchColumn.push_back(albumName);
335 string locationGroup = latitudeIndex + "," + longitudeIndex;
336 context->predicates.GroupBy({ locationGroup });
337 }
338 return true;
339 }
340
341 template <class AsyncContext>
GetFetchOption(napi_env env,napi_value arg,const FetchOptionType & fetchOptType,AsyncContext & context)342 napi_status SendableMediaLibraryNapiUtils::GetFetchOption(napi_env env, napi_value arg,
343 const FetchOptionType &fetchOptType, AsyncContext &context)
344 {
345 // Parse the argument into fetchOption if any
346 CHECK_STATUS_RET(GetPredicate(env, arg, "predicates", context, fetchOptType), "invalid predicate");
347 CHECK_STATUS_RET(GetArrayProperty(env, arg, "fetchColumns", context->fetchColumn),
348 "Failed to parse fetchColumn");
349 return napi_ok;
350 }
351
352 template <class AsyncContext>
GetAlbumFetchOption(napi_env env,napi_value arg,const FetchOptionType & fetchOptType,AsyncContext & context)353 napi_status SendableMediaLibraryNapiUtils::GetAlbumFetchOption(napi_env env, napi_value arg,
354 const FetchOptionType &fetchOptType, AsyncContext &context)
355 {
356 // Parse the argument into AlbumFetchOption if any
357 CHECK_STATUS_RET(GetPredicate(env, arg, "predicates", context, fetchOptType), "invalid predicate");
358 return napi_ok;
359 }
360
361 template <class AsyncContext>
GetPredicate(napi_env env,const napi_value arg,const string & propName,AsyncContext & context,const FetchOptionType & fetchOptType)362 napi_status SendableMediaLibraryNapiUtils::GetPredicate(napi_env env, const napi_value arg, const string &propName,
363 AsyncContext &context, const FetchOptionType &fetchOptType)
364 {
365 bool present = false;
366 napi_value property = nullptr;
367 CHECK_STATUS_RET(napi_has_named_property(env, arg, propName.c_str(), &present),
368 "Failed to check property name");
369 if (present) {
370 CHECK_STATUS_RET(napi_get_named_property(env, arg, propName.c_str(), &property), "Failed to get property");
371 JSProxy::JSProxy<DataShareAbsPredicates> *jsProxy = nullptr;
372 napi_unwrap(env, property, reinterpret_cast<void **>(&jsProxy));
373 if (jsProxy == nullptr) {
374 NAPI_ERR_LOG("jsProxy is invalid");
375 return napi_invalid_arg;
376 }
377 shared_ptr<DataShareAbsPredicates> predicate = jsProxy->GetInstance();
378 CHECK_COND_RET(HandleSpecialPredicate(context, predicate, fetchOptType) == TRUE, napi_invalid_arg,
379 "invalid predicate");
380 CHECK_COND_RET(GetLocationPredicate(context, predicate) == TRUE, napi_invalid_arg, "invalid predicate");
381 }
382 return napi_ok;
383 }
384
385 template <class AsyncContext>
ParseAssetFetchOptCallback(napi_env env,napi_callback_info info,AsyncContext & context)386 napi_status SendableMediaLibraryNapiUtils::ParseAssetFetchOptCallback(napi_env env, napi_callback_info info,
387 AsyncContext &context)
388 {
389 constexpr size_t minArgs = ARGS_ONE;
390 constexpr size_t maxArgs = ARGS_TWO;
391 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
392 "Failed to get object info");
393 CHECK_STATUS_RET(GetFetchOption(env, context->argv[PARAM0], ASSET_FETCH_OPT, context),
394 "Failed to get fetch option");
395 return napi_ok;
396 }
397
398 template <class AsyncContext>
ParseAlbumFetchOptCallback(napi_env env,napi_callback_info info,AsyncContext & context)399 napi_status SendableMediaLibraryNapiUtils::ParseAlbumFetchOptCallback(napi_env env, napi_callback_info info,
400 AsyncContext &context)
401 {
402 constexpr size_t minArgs = ARGS_ONE;
403 constexpr size_t maxArgs = ARGS_TWO;
404 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
405 "Failed to get object info");
406 // Parse the argument into fetchOption if any
407 CHECK_STATUS_RET(GetPredicate(env, context->argv[PARAM0], "predicates", context, ALBUM_FETCH_OPT),
408 "invalid predicate");
409 context->predicates.And()->NotEqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::HIDDEN));
410 return napi_ok;
411 }
412
413 template <class AsyncContext>
UpdateMediaTypeSelections(AsyncContext * context)414 void SendableMediaLibraryNapiUtils::UpdateMediaTypeSelections(AsyncContext *context)
415 {
416 constexpr int FIRST_MEDIA_TYPE = 0;
417 constexpr int SECOND_MEDIA_TYPE = 1;
418 if ((context->mediaTypes.size() != ARGS_ONE) && (context->mediaTypes.size() != ARGS_TWO)) {
419 return;
420 }
421 DataShare::DataSharePredicates &predicates = context->predicates;
422 predicates.BeginWrap();
423 predicates.EqualTo(MEDIA_DATA_DB_MEDIA_TYPE, (int)context->mediaTypes[FIRST_MEDIA_TYPE]);
424 if (context->mediaTypes.size() == ARGS_TWO) {
425 predicates.Or()->EqualTo(MEDIA_DATA_DB_MEDIA_TYPE, (int)context->mediaTypes[SECOND_MEDIA_TYPE]);
426 }
427 predicates.EndWrap();
428 }
429
430 template <class AsyncContext>
AsyncContextSetObjectInfo(napi_env env,napi_callback_info info,AsyncContext & asyncContext,const size_t minArgs,const size_t maxArgs)431 napi_status SendableMediaLibraryNapiUtils::AsyncContextSetObjectInfo(napi_env env, napi_callback_info info,
432 AsyncContext &asyncContext, const size_t minArgs, const size_t maxArgs)
433 {
434 napi_value thisVar = nullptr;
435 asyncContext->argc = maxArgs;
436 CHECK_STATUS_RET(napi_get_cb_info(env, info, &asyncContext->argc, &(asyncContext->argv[ARGS_ZERO]), &thisVar,
437 nullptr), "Failed to get cb info");
438 CHECK_COND_RET(((asyncContext->argc >= minArgs) && (asyncContext->argc <= maxArgs)), napi_invalid_arg,
439 "Number of args is invalid");
440 if (minArgs > 0) {
441 CHECK_COND_RET(asyncContext->argv[ARGS_ZERO] != nullptr, napi_invalid_arg, "Argument list is empty");
442 }
443 CHECK_STATUS_RET(napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo)),
444 "Failed to unwrap thisVar");
445 CHECK_COND_RET(asyncContext->objectInfo != nullptr, napi_invalid_arg, "Failed to get object info");
446 CHECK_STATUS_RET(GetParamCallback(env, asyncContext), "Failed to get callback param!");
447 return napi_ok;
448 }
449
450 template <class AsyncContext>
AsyncContextGetArgs(napi_env env,napi_callback_info info,AsyncContext & asyncContext,const size_t minArgs,const size_t maxArgs)451 napi_status SendableMediaLibraryNapiUtils::AsyncContextGetArgs(napi_env env, napi_callback_info info,
452 AsyncContext &asyncContext, const size_t minArgs, const size_t maxArgs)
453 {
454 asyncContext->argc = maxArgs;
455 CHECK_STATUS_RET(napi_get_cb_info(env, info, &asyncContext->argc, &(asyncContext->argv[ARGS_ZERO]), nullptr,
456 nullptr), "Failed to get cb info");
457 CHECK_COND_RET(asyncContext->argc >= minArgs && asyncContext->argc <= maxArgs, napi_invalid_arg,
458 "Number of args is invalid");
459 if (minArgs > 0) {
460 CHECK_COND_RET(asyncContext->argv[ARGS_ZERO] != nullptr, napi_invalid_arg, "Argument list is empty");
461 }
462 CHECK_STATUS_RET(GetParamCallback(env, asyncContext), "Failed to get callback param");
463 return napi_ok;
464 }
465
466 template <class AsyncContext>
GetParamCallback(napi_env env,AsyncContext & context)467 napi_status SendableMediaLibraryNapiUtils::GetParamCallback(napi_env env, AsyncContext &context)
468 {
469 /* Parse the last argument into callbackref if any */
470 bool isCallback = false;
471 CHECK_STATUS_RET(HasCallback(env, context->argc, context->argv, isCallback), "Failed to check callback");
472 if (isCallback) {
473 CHECK_STATUS_RET(GetParamFunction(env, context->argv[context->argc - 1], context->callbackRef),
474 "Failed to get callback");
475 }
476 return napi_ok;
477 }
478
479 template <class AsyncContext>
ParseArgsBoolCallBack(napi_env env,napi_callback_info info,AsyncContext & context,bool & param)480 napi_status SendableMediaLibraryNapiUtils::ParseArgsBoolCallBack(napi_env env, napi_callback_info info,
481 AsyncContext &context,
482 bool ¶m)
483 {
484 constexpr size_t minArgs = ARGS_ONE;
485 constexpr size_t maxArgs = ARGS_TWO;
486 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
487 "Failed to get object info");
488
489 /* Parse the first argument into param */
490 CHECK_STATUS_RET(GetParamBool(env, context->argv[ARGS_ZERO], param), "Failed to get parameter");
491 return napi_ok;
492 }
493
494 template <class AsyncContext>
ParseArgsStringCallback(napi_env env,napi_callback_info info,AsyncContext & context,string & param)495 napi_status SendableMediaLibraryNapiUtils::ParseArgsStringCallback(napi_env env, napi_callback_info info,
496 AsyncContext &context, string ¶m)
497 {
498 constexpr size_t minArgs = ARGS_ONE;
499 constexpr size_t maxArgs = ARGS_TWO;
500 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
501 "Failed to get object info");
502
503 CHECK_STATUS_RET(GetParamStringPathMax(env, context->argv[ARGS_ZERO], param), "Failed to get string argument");
504 return napi_ok;
505 }
506
507 template <class AsyncContext>
ParseArgsStringArrayCallback(napi_env env,napi_callback_info info,AsyncContext & context,vector<string> & array)508 napi_status SendableMediaLibraryNapiUtils::ParseArgsStringArrayCallback(napi_env env, napi_callback_info info,
509 AsyncContext &context, vector<string> &array)
510 {
511 constexpr size_t minArgs = ARGS_ONE;
512 constexpr size_t maxArgs = ARGS_TWO;
513 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
514 "Failed to get object info");
515
516 CHECK_STATUS_RET(GetStringArray(env, context->argv[ARGS_ZERO], array), "Failed to get string array");
517 CHECK_STATUS_RET(GetParamCallback(env, context), "Failed to get callback");
518 return napi_ok;
519 }
520
521 template <class AsyncContext>
ParseArgsNumberCallback(napi_env env,napi_callback_info info,AsyncContext & context,int32_t & value)522 napi_status SendableMediaLibraryNapiUtils::ParseArgsNumberCallback(napi_env env, napi_callback_info info,
523 AsyncContext &context, int32_t &value)
524 {
525 constexpr size_t minArgs = ARGS_ONE;
526 constexpr size_t maxArgs = ARGS_TWO;
527 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
528 "Failed to get object info");
529
530 CHECK_STATUS_RET(GetInt32(env, context->argv[ARGS_ZERO], value), "Failed to get number argument");
531 return napi_ok;
532 }
533
534 template <class AsyncContext>
ParseArgsOnlyCallBack(napi_env env,napi_callback_info info,AsyncContext & context)535 napi_status SendableMediaLibraryNapiUtils::ParseArgsOnlyCallBack(napi_env env, napi_callback_info info,
536 AsyncContext &context)
537 {
538 constexpr size_t minArgs = ARGS_ZERO;
539 constexpr size_t maxArgs = ARGS_ONE;
540 CHECK_STATUS_RET(AsyncContextSetObjectInfo(env, info, context, minArgs, maxArgs),
541 "Failed to get object info");
542 return napi_ok;
543 }
544
GetAssetType(MediaType type)545 AssetType SendableMediaLibraryNapiUtils::GetAssetType(MediaType type)
546 {
547 AssetType result;
548
549 switch (type) {
550 case MEDIA_TYPE_AUDIO:
551 result = ASSET_AUDIO;
552 break;
553 case MEDIA_TYPE_VIDEO:
554 result = ASSET_VIDEO;
555 break;
556 case MEDIA_TYPE_IMAGE:
557 result = ASSET_IMAGE;
558 break;
559 case MEDIA_TYPE_MEDIA:
560 result = ASSET_MEDIA;
561 break;
562 default:
563 result = ASSET_NONE;
564 break;
565 }
566
567 return result;
568 }
569
AppendFetchOptionSelection(string & selection,const string & newCondition)570 void SendableMediaLibraryNapiUtils::AppendFetchOptionSelection(string &selection, const string &newCondition)
571 {
572 if (!newCondition.empty()) {
573 if (!selection.empty()) {
574 selection = "(" + selection + ") AND " + newCondition;
575 } else {
576 selection = newCondition;
577 }
578 }
579 }
580
TransErrorCode(const string & Name,shared_ptr<DataShare::DataShareResultSet> resultSet)581 int SendableMediaLibraryNapiUtils::TransErrorCode(const string &Name,
582 shared_ptr<DataShare::DataShareResultSet> resultSet)
583 {
584 NAPI_ERR_LOG("interface: %{public}s, server return nullptr", Name.c_str());
585 // Query can't return errorcode, so assume nullptr as permission deny
586 if (resultSet == nullptr) {
587 return JS_ERR_PERMISSION_DENIED;
588 }
589 return ERR_DEFAULT;
590 }
591
TransErrorCode(const string & Name,int error)592 int SendableMediaLibraryNapiUtils::TransErrorCode(const string &Name, int error)
593 {
594 NAPI_ERR_LOG("interface: %{public}s, server errcode:%{public}d ", Name.c_str(), error);
595 // Transfer Server error to napi error code
596 if (error <= E_COMMON_START && error >= E_COMMON_END) {
597 error = JS_INNER_FAIL;
598 } else if (trans2JsError.count(error)) {
599 error = trans2JsError.at(error);
600 }
601 return error;
602 }
603
HandleError(napi_env env,int error,napi_value & errorObj,const string & Name)604 void SendableMediaLibraryNapiUtils::HandleError(napi_env env, int error, napi_value &errorObj, const string &Name)
605 {
606 if (error == ERR_DEFAULT) {
607 return;
608 }
609
610 string errMsg = "System inner fail";
611 int originalError = error;
612 if (jsErrMap.count(error) > 0) {
613 errMsg = jsErrMap.at(error);
614 } else {
615 error = JS_INNER_FAIL;
616 }
617 CreateNapiErrorObject(env, errorObj, error, errMsg);
618 errMsg = Name + " " + errMsg;
619 NAPI_ERR_LOG("Error: %{public}s, js errcode:%{public}d ", errMsg.c_str(), originalError);
620 }
621
CreateNapiErrorObject(napi_env env,napi_value & errorObj,const int32_t errCode,const string errMsg)622 void SendableMediaLibraryNapiUtils::CreateNapiErrorObject(napi_env env, napi_value &errorObj, const int32_t errCode,
623 const string errMsg)
624 {
625 napi_status statusError;
626 napi_value napiErrorCode = nullptr;
627 napi_value napiErrorMsg = nullptr;
628 statusError = napi_create_string_utf8(env, to_string(errCode).c_str(), NAPI_AUTO_LENGTH, &napiErrorCode);
629 if (statusError == napi_ok) {
630 statusError = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &napiErrorMsg);
631 if (statusError == napi_ok) {
632 statusError = napi_create_error(env, napiErrorCode, napiErrorMsg, &errorObj);
633 if (statusError == napi_ok) {
634 NAPI_DEBUG_LOG("napi_create_error success");
635 }
636 }
637 }
638 }
639
InvokeJSAsyncMethod(napi_env env,napi_deferred deferred,napi_ref callbackRef,napi_async_work work,const SendableJSAsyncContextOutput & asyncContext)640 void SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(napi_env env, napi_deferred deferred, napi_ref callbackRef,
641 napi_async_work work, const SendableJSAsyncContextOutput &asyncContext)
642 {
643 MediaLibraryTracer tracer;
644 tracer.Start("InvokeJSAsyncMethod");
645
646 napi_value retVal;
647 napi_value callback = nullptr;
648
649 /* Deferred is used when JS Callback method expects a promise value */
650 if (deferred) {
651 if (asyncContext.status) {
652 napi_resolve_deferred(env, deferred, asyncContext.data);
653 } else {
654 napi_reject_deferred(env, deferred, asyncContext.error);
655 }
656 } else {
657 napi_value result[ARGS_TWO];
658 result[PARAM0] = asyncContext.error;
659 result[PARAM1] = asyncContext.data;
660 napi_get_reference_value(env, callbackRef, &callback);
661 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
662 napi_delete_reference(env, callbackRef);
663 }
664 napi_delete_async_work(env, work);
665 }
666
667 template <class AsyncContext>
NapiCreateAsyncWork(napi_env env,unique_ptr<AsyncContext> & asyncContext,const string & resourceName,void (* execute)(napi_env,void *),void (* complete)(napi_env,napi_status,void *))668 napi_value SendableMediaLibraryNapiUtils::NapiCreateAsyncWork(napi_env env, unique_ptr<AsyncContext> &asyncContext,
669 const string &resourceName, void (*execute)(napi_env, void *), void (*complete)(napi_env, napi_status, void *))
670 {
671 napi_value result = nullptr;
672 napi_value resource = nullptr;
673 NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
674 NAPI_CREATE_RESOURCE_NAME(env, resource, resourceName.c_str(), asyncContext);
675
676 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, execute, complete,
677 static_cast<void *>(asyncContext.get()), &asyncContext->work));
678 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
679 asyncContext.release();
680
681 return result;
682 }
683
ToUTF8String(napi_env env,napi_value value)684 tuple<bool, unique_ptr<char[]>, size_t> SendableMediaLibraryNapiUtils::ToUTF8String(napi_env env, napi_value value)
685 {
686 size_t strLen = 0;
687 napi_status status = napi_get_value_string_utf8(env, value, nullptr, -1, &strLen);
688 if (status != napi_ok) {
689 NAPI_ERR_LOG("ToUTF8String get fail, %{public}d", status);
690 return { false, nullptr, 0 };
691 }
692
693 size_t bufLen = strLen + 1;
694 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
695 if (str == nullptr) {
696 NAPI_ERR_LOG("ToUTF8String get memory fail");
697 return { false, nullptr, 0 };
698 }
699 status = napi_get_value_string_utf8(env, value, str.get(), bufLen, &strLen);
700 return make_tuple(status == napi_ok, move(str), strLen);
701 }
702
IsExistsByPropertyName(napi_env env,napi_value jsObject,const char * propertyName)703 bool SendableMediaLibraryNapiUtils::IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName)
704 {
705 bool result = false;
706 if (napi_has_named_property(env, jsObject, propertyName, &result) == napi_ok) {
707 return result;
708 } else {
709 NAPI_ERR_LOG("IsExistsByPropertyName not exist %{public}s", propertyName);
710 return false;
711 }
712 }
713
GetPropertyValueByName(napi_env env,napi_value jsObject,const char * propertyName)714 napi_value SendableMediaLibraryNapiUtils::GetPropertyValueByName(napi_env env, napi_value jsObject,
715 const char *propertyName)
716 {
717 napi_value value = nullptr;
718 if (IsExistsByPropertyName(env, jsObject, propertyName) == false) {
719 NAPI_ERR_LOG("GetPropertyValueByName not exist %{public}s", propertyName);
720 return nullptr;
721 }
722 if (napi_get_named_property(env, jsObject, propertyName, &value) != napi_ok) {
723 NAPI_ERR_LOG("GetPropertyValueByName get fail %{public}s", propertyName);
724 return nullptr;
725 }
726 return value;
727 }
728
CheckJSArgsTypeAsFunc(napi_env env,napi_value arg)729 bool SendableMediaLibraryNapiUtils::CheckJSArgsTypeAsFunc(napi_env env, napi_value arg)
730 {
731 napi_valuetype valueType = napi_undefined;
732 napi_typeof(env, arg, &valueType);
733 return (valueType == napi_function);
734 }
735
IsArrayForNapiValue(napi_env env,napi_value param,uint32_t & arraySize)736 bool SendableMediaLibraryNapiUtils::IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize)
737 {
738 bool isArray = false;
739 arraySize = 0;
740 if ((napi_is_array(env, param, &isArray) != napi_ok) || (isArray == false)) {
741 return false;
742 }
743 if (napi_get_array_length(env, param, &arraySize) != napi_ok) {
744 return false;
745 }
746 return true;
747 }
748
GetInt32Arg(napi_env env,napi_value arg,int32_t & value)749 napi_value SendableMediaLibraryNapiUtils::GetInt32Arg(napi_env env, napi_value arg, int32_t &value)
750 {
751 napi_valuetype valueType = napi_undefined;
752 CHECK_ARGS(env, napi_typeof(env, arg, &valueType), JS_INNER_FAIL);
753 if (valueType != napi_number) {
754 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
755 return nullptr;
756 }
757 CHECK_ARGS(env, napi_get_value_int32(env, arg, &value), JS_INNER_FAIL);
758
759 napi_value result = nullptr;
760 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
761 return result;
762 }
763
UriAppendKeyValue(string & uri,const string & key,const string & value)764 void SendableMediaLibraryNapiUtils::UriAppendKeyValue(string &uri, const string &key, const string &value)
765 {
766 string uriKey = key + '=';
767 if (uri.find(uriKey) != string::npos) {
768 return;
769 }
770
771 char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
772 string append = queryMark + key + '=' + value;
773
774 size_t posJ = uri.find('#');
775 if (posJ == string::npos) {
776 uri += append;
777 } else {
778 uri.insert(posJ, append);
779 }
780 }
781
AddDefaultAssetColumns(napi_env env,vector<string> & fetchColumn,function<bool (const string & columnName)> isValidColumn,NapiAssetType assetType,const PhotoAlbumSubType subType)782 napi_value SendableMediaLibraryNapiUtils::AddDefaultAssetColumns(napi_env env, vector<string> &fetchColumn,
783 function<bool(const string &columnName)> isValidColumn, NapiAssetType assetType,
784 const PhotoAlbumSubType subType)
785 {
786 auto validFetchColumns = MediaColumn::DEFAULT_FETCH_COLUMNS;
787 if (assetType == TYPE_PHOTO) {
788 validFetchColumns.insert(
789 PhotoColumn::DEFAULT_FETCH_COLUMNS.begin(), PhotoColumn::DEFAULT_FETCH_COLUMNS.end());
790 }
791 switch (subType) {
792 case PhotoAlbumSubType::FAVORITE:
793 validFetchColumns.insert(MediaColumn::MEDIA_IS_FAV);
794 break;
795 case PhotoAlbumSubType::VIDEO:
796 validFetchColumns.insert(MediaColumn::MEDIA_TYPE);
797 break;
798 case PhotoAlbumSubType::HIDDEN:
799 validFetchColumns.insert(MediaColumn::MEDIA_HIDDEN);
800 break;
801 case PhotoAlbumSubType::TRASH:
802 validFetchColumns.insert(MediaColumn::MEDIA_DATE_TRASHED);
803 break;
804 case PhotoAlbumSubType::SCREENSHOT:
805 case PhotoAlbumSubType::CAMERA:
806 validFetchColumns.insert(PhotoColumn::PHOTO_SUBTYPE);
807 break;
808 default:
809 break;
810 }
811 for (const auto &column : fetchColumn) {
812 if (column == PENDING_STATUS) {
813 validFetchColumns.insert(MediaColumn::MEDIA_TIME_PENDING);
814 } else if (isValidColumn(column)) {
815 validFetchColumns.insert(column);
816 } else if (column == MEDIA_DATA_DB_URI) {
817 continue;
818 } else if (DATE_TRANSITION_MAP.count(column) != 0) {
819 validFetchColumns.insert(DATE_TRANSITION_MAP.at(column));
820 } else {
821 NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
822 return nullptr;
823 }
824 }
825 fetchColumn.assign(validFetchColumns.begin(), validFetchColumns.end());
826
827 napi_value result = nullptr;
828 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
829 return result;
830 }
831
SetDefaultPredicatesCondition(DataSharePredicates & predicates,const int32_t dateTrashed,const bool isHidden,const int32_t timePending,const bool isTemp)832 inline void SetDefaultPredicatesCondition(DataSharePredicates &predicates, const int32_t dateTrashed,
833 const bool isHidden, const int32_t timePending, const bool isTemp)
834 {
835 predicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, to_string(dateTrashed));
836 predicates.EqualTo(MediaColumn::MEDIA_HIDDEN, to_string(isHidden));
837 predicates.EqualTo(MediaColumn::MEDIA_TIME_PENDING, to_string(timePending));
838 predicates.EqualTo(PhotoColumn::PHOTO_IS_TEMP, to_string(isTemp));
839 predicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL,
840 to_string(static_cast<int32_t>(BurstCoverLevelType::COVER)));
841 }
842
GetUserAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates,const bool hiddenOnly)843 int32_t SendableMediaLibraryNapiUtils::GetUserAlbumPredicates(
844 const int32_t albumId, DataSharePredicates &predicates, const bool hiddenOnly)
845 {
846 predicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
847 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
848 return E_SUCCESS;
849 }
850
GetPortraitAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates)851 int32_t SendableMediaLibraryNapiUtils::GetPortraitAlbumPredicates(const int32_t albumId,
852 DataSharePredicates &predicates)
853 {
854 string onClause = MediaColumn::MEDIA_ID + " = " + PhotoMap::ASSET_ID;
855 vector<string> clauses = { onClause };
856 predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On(clauses);
857 onClause = ALBUM_ID + " = " + PhotoMap::ALBUM_ID;
858 clauses = { onClause };
859 predicates.InnerJoin(ANALYSIS_ALBUM_TABLE)->On(clauses);
860 string tempTable = "(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " +
861 to_string(albumId) + ") ag";
862 onClause = "ag." + GROUP_TAG + " = " + ANALYSIS_ALBUM_TABLE + "." + GROUP_TAG;
863 clauses = { onClause };
864 predicates.InnerJoin(tempTable)->On(clauses);
865 SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
866 predicates.Distinct();
867 return E_SUCCESS;
868 }
869
GetAnalysisAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates)870 int32_t SendableMediaLibraryNapiUtils::GetAnalysisAlbumPredicates(const int32_t albumId,
871 DataSharePredicates &predicates)
872 {
873 string onClause = MediaColumn::MEDIA_ID + " = " + PhotoMap::ASSET_ID;
874 predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ onClause });
875 predicates.EqualTo(PhotoMap::ALBUM_ID, to_string(albumId));
876 SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
877 return E_SUCCESS;
878 }
879
IsFeaturedSinglePortraitAlbum(std::string albumName,DataShare::DataSharePredicates & predicates)880 bool SendableMediaLibraryNapiUtils::IsFeaturedSinglePortraitAlbum(
881 std::string albumName, DataShare::DataSharePredicates &predicates)
882 {
883 bool isFeaturedSinglePortrait = false;
884 int portraitAlbumId = 0;
885 if (albumName.compare(to_string(portraitAlbumId)) != 0) {
886 return isFeaturedSinglePortrait;
887 }
888
889 DataSharePredicates featuredSinglePortraitPredicates;
890 std::vector<OperationItem> operationList = predicates.GetOperationList();
891 for (auto& operationItem : operationList) {
892 switch (operationItem.operation) {
893 case OHOS::DataShare::OperationType::LIKE : {
894 std::string field = std::get<string>(operationItem.singleParams[0]);
895 std::string value = std::get<string>(operationItem.singleParams[1]);
896 if (field.compare("FeaturedSinglePortrait") == 0 && value.compare("true") == 0) {
897 isFeaturedSinglePortrait = true;
898 } else {
899 featuredSinglePortraitPredicates.Like(field, value);
900 }
901 break;
902 }
903 case OHOS::DataShare::OperationType::ORDER_BY_DESC : {
904 featuredSinglePortraitPredicates.OrderByDesc(operationItem.GetSingle(0));
905 break;
906 }
907 case OHOS::DataShare::OperationType::LIMIT : {
908 featuredSinglePortraitPredicates.Limit(operationItem.GetSingle(0), operationItem.GetSingle(1));
909 break;
910 }
911 default: {
912 break;
913 }
914 }
915 }
916
917 if (isFeaturedSinglePortrait) {
918 predicates = featuredSinglePortraitPredicates;
919 }
920 return isFeaturedSinglePortrait;
921 }
922
GetFeaturedSinglePortraitAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates)923 int32_t SendableMediaLibraryNapiUtils::GetFeaturedSinglePortraitAlbumPredicates(
924 const int32_t albumId, DataSharePredicates &predicates)
925 {
926 string onClause = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " +
927 ANALYSIS_PHOTO_MAP_TABLE + "." + PhotoMap::ASSET_ID;
928 predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ onClause });
929
930 constexpr int32_t minSize = 224;
931 string imgHeightColumn = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_HEIGHT;
932 string imgWidthColumn = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_WIDTH;
933 string imgFaceHeightColumn = VISION_IMAGE_FACE_TABLE + "." + SCALE_HEIGHT;
934 string imgFaceWidthColumn = VISION_IMAGE_FACE_TABLE + "." + SCALE_WIDTH;
935 string imgFaceHeightClause = "( " + imgFaceHeightColumn + " > " + to_string(minSize) +
936 " OR ( " + imgFaceHeightColumn + " <= 1.0 " + " AND " + imgFaceHeightColumn + " * " + imgHeightColumn +
937 " > " + to_string(minSize) + " ) )";
938 string imgFaceWidthClause = "( " + imgFaceWidthColumn + " > " + to_string(minSize) +
939 " OR ( " + imgFaceWidthColumn + " <= 1.0 " + " AND " + imgFaceWidthColumn + " * " + imgWidthColumn +
940 " > " + to_string(minSize) + " ) )";
941 string imgFaceOcclusionClause = "( " + VISION_IMAGE_FACE_TABLE + "." + FACE_OCCLUSION + " != 1 OR " +
942 VISION_IMAGE_FACE_TABLE + "." + FACE_OCCLUSION + " IS NULL )";
943 string portraitRotationLimit = "BETWEEN -30 AND 30";
944 onClause = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " + VISION_IMAGE_FACE_TABLE + "." +
945 MediaColumn::MEDIA_ID + " AND " + VISION_IMAGE_FACE_TABLE + "." + TOTAL_FACES + " = 1 AND " +
946 imgFaceHeightClause + " AND " + imgFaceWidthClause + " AND " + imgFaceOcclusionClause + " AND " +
947 VISION_IMAGE_FACE_TABLE + "." + PITCH + " " + portraitRotationLimit + " AND " +
948 VISION_IMAGE_FACE_TABLE + "." + YAW + " " + portraitRotationLimit + " AND " +
949 VISION_IMAGE_FACE_TABLE + "." + ROLL + " " + portraitRotationLimit;
950 predicates.InnerJoin(VISION_IMAGE_FACE_TABLE)->On({ onClause });
951
952 string portraitType = "IN ( 1, 2 )";
953 onClause = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " + VISION_POSE_TABLE + "." +
954 MediaColumn::MEDIA_ID + " AND " + VISION_POSE_TABLE + "." + POSE_TYPE + " " + portraitType;
955 predicates.InnerJoin(VISION_POSE_TABLE)->On({ onClause });
956
957 predicates.EqualTo(PhotoMap::ALBUM_ID, to_string(albumId));
958 SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
959 return E_SUCCESS;
960 }
961
GetAllLocationPredicates(DataSharePredicates & predicates)962 int32_t SendableMediaLibraryNapiUtils::GetAllLocationPredicates(DataSharePredicates &predicates)
963 {
964 SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
965 predicates.And()->NotEqualTo(PhotoColumn::PHOTO_LATITUDE, to_string(0));
966 predicates.And()->NotEqualTo(PhotoColumn::PHOTO_LONGITUDE, to_string(0));
967 return E_SUCCESS;
968 }
969
GetFavoritePredicates(DataSharePredicates & predicates,const bool hiddenOnly)970 static int32_t GetFavoritePredicates(DataSharePredicates &predicates, const bool hiddenOnly)
971 {
972 predicates.BeginWrap();
973 constexpr int32_t IS_FAVORITE = 1;
974 predicates.EqualTo(MediaColumn::MEDIA_IS_FAV, to_string(IS_FAVORITE));
975 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
976 predicates.EndWrap();
977 return E_SUCCESS;
978 }
979
GetVideoPredicates(DataSharePredicates & predicates,const bool hiddenOnly)980 static int32_t GetVideoPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
981 {
982 predicates.BeginWrap();
983 predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_VIDEO));
984 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
985 predicates.EndWrap();
986 return E_SUCCESS;
987 }
988
GetHiddenPredicates(DataSharePredicates & predicates)989 static int32_t GetHiddenPredicates(DataSharePredicates &predicates)
990 {
991 predicates.BeginWrap();
992 SetDefaultPredicatesCondition(predicates, 0, 1, 0, false);
993 predicates.EndWrap();
994 return E_SUCCESS;
995 }
996
GetTrashPredicates(DataSharePredicates & predicates)997 static int32_t GetTrashPredicates(DataSharePredicates &predicates)
998 {
999 predicates.BeginWrap();
1000 predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
1001 predicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL,
1002 to_string(static_cast<int32_t>(BurstCoverLevelType::COVER)));
1003 predicates.EndWrap();
1004 return E_SUCCESS;
1005 }
1006
GetScreenshotPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1007 static int32_t GetScreenshotPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1008 {
1009 predicates.BeginWrap();
1010 predicates.EqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::SCREENSHOT)));
1011 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1012 predicates.EndWrap();
1013 return E_SUCCESS;
1014 }
1015
GetCameraPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1016 static int32_t GetCameraPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1017 {
1018 predicates.BeginWrap();
1019 predicates.EqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::CAMERA)));
1020 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1021 predicates.EndWrap();
1022 return E_SUCCESS;
1023 }
1024
GetAllImagesPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1025 static int32_t GetAllImagesPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1026 {
1027 predicates.BeginWrap();
1028 predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_IMAGE));
1029 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1030 predicates.EndWrap();
1031 return E_SUCCESS;
1032 }
1033
GetSourceAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates,const bool hiddenOnly)1034 int32_t SendableMediaLibraryNapiUtils::GetSourceAlbumPredicates(const int32_t albumId, DataSharePredicates &predicates,
1035 const bool hiddenOnly)
1036 {
1037 predicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
1038 predicates.EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)));
1039 SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1040 return E_SUCCESS;
1041 }
1042
GetSystemAlbumPredicates(const PhotoAlbumSubType subType,DataSharePredicates & predicates,const bool hiddenOnly)1043 int32_t SendableMediaLibraryNapiUtils::GetSystemAlbumPredicates(const PhotoAlbumSubType subType,
1044 DataSharePredicates &predicates, const bool hiddenOnly)
1045 {
1046 switch (subType) {
1047 case PhotoAlbumSubType::FAVORITE: {
1048 return GetFavoritePredicates(predicates, hiddenOnly);
1049 }
1050 case PhotoAlbumSubType::VIDEO: {
1051 return GetVideoPredicates(predicates, hiddenOnly);
1052 }
1053 case PhotoAlbumSubType::HIDDEN: {
1054 return GetHiddenPredicates(predicates);
1055 }
1056 case PhotoAlbumSubType::TRASH: {
1057 return GetTrashPredicates(predicates);
1058 }
1059 case PhotoAlbumSubType::SCREENSHOT: {
1060 return GetScreenshotPredicates(predicates, hiddenOnly);
1061 }
1062 case PhotoAlbumSubType::CAMERA: {
1063 return GetCameraPredicates(predicates, hiddenOnly);
1064 }
1065 case PhotoAlbumSubType::IMAGE: {
1066 return GetAllImagesPredicates(predicates, hiddenOnly);
1067 }
1068 default: {
1069 NAPI_ERR_LOG("Unsupported photo album subtype: %{public}d", subType);
1070 return E_INVALID_ARGUMENTS;
1071 }
1072 }
1073 }
1074
CreateValueByIndex(napi_env env,int32_t index,string name,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,const shared_ptr<FileAsset> & asset)1075 napi_value SendableMediaLibraryNapiUtils::CreateValueByIndex(napi_env env, int32_t index, string name,
1076 shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet, const shared_ptr<FileAsset> &asset)
1077 {
1078 int status;
1079 int integerVal = 0;
1080 string stringVal = "";
1081 int64_t longVal = 0;
1082 double doubleVal = 0.0;
1083 napi_value value = nullptr;
1084 auto dataType = SendableMediaLibraryNapiUtils::GetTypeMap().at(name);
1085 switch (dataType.first) {
1086 case TYPE_STRING:
1087 status = resultSet->GetString(index, stringVal);
1088 napi_create_string_utf8(env, stringVal.c_str(), NAPI_AUTO_LENGTH, &value);
1089 asset->GetMemberMap().emplace(name, stringVal);
1090 break;
1091 case TYPE_INT32:
1092 status = resultSet->GetInt(index, integerVal);
1093 napi_create_int32(env, integerVal, &value);
1094 asset->GetMemberMap().emplace(name, integerVal);
1095 break;
1096 case TYPE_INT64:
1097 status = resultSet->GetLong(index, longVal);
1098 napi_create_int64(env, longVal, &value);
1099 asset->GetMemberMap().emplace(name, longVal);
1100 break;
1101 case TYPE_DOUBLE:
1102 status = resultSet->GetDouble(index, doubleVal);
1103 napi_create_double(env, doubleVal, &value);
1104 asset->GetMemberMap().emplace(name, doubleVal);
1105 break;
1106 default:
1107 NAPI_ERR_LOG("not match dataType %{public}d", dataType.first);
1108 break;
1109 }
1110
1111 return value;
1112 }
1113
handleTimeInfo(napi_env env,const std::string & name,napi_value result,int32_t index,const std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)1114 void SendableMediaLibraryNapiUtils::handleTimeInfo(napi_env env, const std::string& name, napi_value result,
1115 int32_t index, const std::shared_ptr<NativeRdb::AbsSharedResultSet>& resultSet)
1116 {
1117 if (TIME_COLUMN.count(name) == 0) {
1118 return;
1119 }
1120 int64_t longVal = 0;
1121 int status;
1122 napi_value value = nullptr;
1123 status = resultSet->GetLong(index, longVal);
1124 int64_t modifieldValue = longVal / 1000;
1125 napi_create_int64(env, modifieldValue, &value);
1126 auto dataType = SendableMediaLibraryNapiUtils::GetTimeTypeMap().at(name);
1127 napi_set_named_property(env, result, dataType.second.c_str(), value);
1128 }
1129
handleThumbnailReady(napi_env env,const std::string & name,napi_value result,int32_t index,const std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)1130 static void handleThumbnailReady(napi_env env, const std::string& name, napi_value result, int32_t index,
1131 const std::shared_ptr<NativeRdb::AbsSharedResultSet>& resultSet)
1132 {
1133 if (name != "thumbnail_ready") {
1134 return;
1135 }
1136 int64_t longVal = 0;
1137 int status;
1138 napi_value value = nullptr;
1139 status = resultSet->GetLong(index, longVal);
1140 bool resultVal = longVal > 0;
1141 napi_create_int32(env, resultVal, &value);
1142 napi_set_named_property(env, result, "thumbnailReady", value);
1143 }
1144
GetNextRowObject(napi_env env,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)1145 napi_value SendableMediaLibraryNapiUtils::GetNextRowObject(napi_env env,
1146 shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
1147 {
1148 if (resultSet == nullptr) {
1149 NAPI_ERR_LOG("GetNextRowObject fail, result is nullptr");
1150 return nullptr;
1151 }
1152 vector<string> columnNames;
1153 resultSet->GetAllColumnNames(columnNames);
1154
1155 napi_value result = nullptr;
1156 napi_create_object(env, &result);
1157
1158 napi_value value = nullptr;
1159 int32_t index = -1;
1160 auto fileAsset = make_shared<FileAsset>();
1161 for (const auto &name : columnNames) {
1162 index++;
1163
1164 // Check if the column name exists in the type map
1165 if (SendableMediaLibraryNapiUtils::GetTypeMap().count(name) == 0) {
1166 continue;
1167 }
1168 value = SendableMediaLibraryNapiUtils::CreateValueByIndex(env, index, name, resultSet, fileAsset);
1169 auto dataType = SendableMediaLibraryNapiUtils::GetTypeMap().at(name);
1170 napi_set_named_property(env, result, dataType.second.c_str(), value);
1171 handleTimeInfo(env, name, result, index, resultSet);
1172 handleThumbnailReady(env, name, result, index, resultSet);
1173 }
1174
1175 string extrUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath(), false);
1176 MediaFileUri fileUri(fileAsset->GetMediaType(), to_string(fileAsset->GetId()), "", MEDIA_API_VERSION_V10, extrUri);
1177 fileAsset->SetUri(move(fileUri.ToString()));
1178 napi_create_string_utf8(env, fileAsset->GetUri().c_str(), NAPI_AUTO_LENGTH, &value);
1179 napi_set_named_property(env, result, MEDIA_DATA_DB_URI.c_str(), value);
1180 return result;
1181 }
1182
IsSystemApp()1183 bool SendableMediaLibraryNapiUtils::IsSystemApp()
1184 {
1185 static bool isSys = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetSelfTokenID());
1186 return isSys;
1187 }
1188
SendableNapiScopeHandler(napi_env env)1189 SendableNapiScopeHandler::SendableNapiScopeHandler(napi_env env): env_(env)
1190 {
1191 napi_status status = napi_open_handle_scope(env_, &scope_);
1192 if (status != napi_ok) {
1193 NAPI_ERR_LOG("Open Handler scope failed, status %{public}d", status);
1194 isValid_ = false;
1195 } else {
1196 isValid_ = true;
1197 }
1198 }
1199
~SendableNapiScopeHandler()1200 SendableNapiScopeHandler::~SendableNapiScopeHandler()
1201 {
1202 if (isValid_) {
1203 napi_status status = napi_close_handle_scope(env_, scope_);
1204 if (status != napi_ok) {
1205 NAPI_ERR_LOG("Close Handler scope failed, status %{public}d", status);
1206 }
1207 }
1208 }
1209
IsValid()1210 bool SendableNapiScopeHandler::IsValid()
1211 {
1212 return isValid_;
1213 }
1214
GetNapiValueArray(napi_env env,napi_value arg,vector<napi_value> & values)1215 napi_value SendableMediaLibraryNapiUtils::GetNapiValueArray(napi_env env, napi_value arg, vector<napi_value> &values)
1216 {
1217 bool isArray = false;
1218 CHECK_ARGS(env, napi_is_array(env, arg, &isArray), OHOS_INVALID_PARAM_CODE);
1219 if (!isArray) {
1220 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Failed to check array type");
1221 return nullptr;
1222 }
1223
1224 uint32_t len = 0;
1225 CHECK_ARGS(env, napi_get_array_length(env, arg, &len), JS_INNER_FAIL);
1226 if (len == 0) {
1227 napi_value result = nullptr;
1228 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1229 return result;
1230 }
1231
1232 for (uint32_t i = 0; i < len; i++) {
1233 napi_value value = nullptr;
1234 CHECK_ARGS(env, napi_get_element(env, arg, i, &value), JS_INNER_FAIL);
1235 if (value == nullptr) {
1236 NapiError::ThrowError(env, OHOS_INVALID_PARAM_CODE, "Failed to get element");
1237 return nullptr;
1238 }
1239 values.push_back(value);
1240 }
1241
1242 napi_value result = nullptr;
1243 CHECK_ARGS(env, napi_get_boolean(env, true, &result), JS_INNER_FAIL);
1244 return result;
1245 }
1246
GetStringArray(napi_env env,vector<napi_value> & napiValues,vector<string> & values)1247 napi_value SendableMediaLibraryNapiUtils::GetStringArray(napi_env env, vector<napi_value> &napiValues,
1248 vector<string> &values)
1249 {
1250 napi_valuetype valueType = napi_undefined;
1251 unique_ptr<char[]> buffer = make_unique<char[]>(PATH_MAX);
1252 for (const auto &napiValue : napiValues) {
1253 CHECK_ARGS(env, napi_typeof(env, napiValue, &valueType), JS_ERR_PARAMETER_INVALID);
1254 CHECK_COND(env, valueType == napi_string, JS_ERR_PARAMETER_INVALID);
1255
1256 size_t res = 0;
1257 CHECK_ARGS(
1258 env, napi_get_value_string_utf8(env, napiValue, buffer.get(), PATH_MAX, &res), JS_ERR_PARAMETER_INVALID);
1259 values.emplace_back(buffer.get());
1260 }
1261 napi_value ret = nullptr;
1262 CHECK_ARGS(env, napi_get_boolean(env, true, &ret), JS_INNER_FAIL);
1263 return ret;
1264 }
1265
1266 template <class AsyncContext>
ParsePredicates(napi_env env,const napi_value arg,AsyncContext & context,const FetchOptionType & fetchOptType)1267 napi_status SendableMediaLibraryNapiUtils::ParsePredicates(napi_env env, const napi_value arg,
1268 AsyncContext &context, const FetchOptionType &fetchOptType)
1269 {
1270 JSProxy::JSProxy<DataShareAbsPredicates> *jsProxy = nullptr;
1271 napi_unwrap(env, arg, reinterpret_cast<void **>(&jsProxy));
1272 if (jsProxy == nullptr) {
1273 NAPI_ERR_LOG("jsProxy is invalid");
1274 return napi_invalid_arg;
1275 }
1276 shared_ptr<DataShareAbsPredicates> predicate = jsProxy->GetInstance();
1277 CHECK_COND_RET(HandleSpecialPredicate(context, predicate, fetchOptType) == TRUE,
1278 napi_invalid_arg, "invalid predicate");
1279 CHECK_COND_RET(GetLocationPredicate(context, predicate) == TRUE, napi_invalid_arg, "invalid predicate");
1280 return napi_ok;
1281 }
1282
1283 template bool SendableMediaLibraryNapiUtils::HandleSpecialPredicate<unique_ptr<SendablePAHAsyncContext>>(
1284 unique_ptr<SendablePAHAsyncContext> &context, shared_ptr<DataShareAbsPredicates> &predicate,
1285 const FetchOptionType &fetchOptType);
1286
1287 template napi_status SendableMediaLibraryNapiUtils::GetFetchOption<unique_ptr<SendablePAHAsyncContext>>(
1288 napi_env env, napi_value arg, const FetchOptionType &fetchOptType,
1289 unique_ptr<SendablePAHAsyncContext> &context);
1290
1291 template napi_status SendableMediaLibraryNapiUtils::GetFetchOption<unique_ptr<SendablePANAsyncContext>>(
1292 napi_env env, napi_value arg, const FetchOptionType &fetchOptType,
1293 unique_ptr<SendablePANAsyncContext> &context);
1294
1295 template napi_status SendableMediaLibraryNapiUtils::GetAlbumFetchOption<unique_ptr<SendablePANAsyncContext>>(
1296 napi_env env, napi_value arg, const FetchOptionType &fetchOptType,
1297 unique_ptr<SendablePANAsyncContext> &context);
1298
1299 template napi_status SendableMediaLibraryNapiUtils::GetPredicate<unique_ptr<SendablePAHAsyncContext>>(
1300 napi_env env, const napi_value arg, const string &propName,
1301 unique_ptr<SendablePAHAsyncContext> &context, const FetchOptionType &fetchOptType);
1302
1303 template napi_status SendableMediaLibraryNapiUtils::ParseArgsStringArrayCallback<unique_ptr<SendablePAHAsyncContext>>(
1304 napi_env env, napi_callback_info info,
1305 unique_ptr<SendablePAHAsyncContext> &context, vector<string> &array);
1306
1307 template napi_status SendableMediaLibraryNapiUtils::GetParamCallback<unique_ptr<SendablePANAsyncContext>>(
1308 napi_env env, unique_ptr<SendablePANAsyncContext> &context);
1309
1310 template napi_status SendableMediaLibraryNapiUtils::GetParamCallback<unique_ptr<SendablePAHAsyncContext>>(
1311 napi_env env, unique_ptr<SendablePAHAsyncContext> &context);
1312
1313 template napi_status SendableMediaLibraryNapiUtils::GetParamCallback<unique_ptr<SendablePhotoAccessHelperInitContext>>(
1314 napi_env env, unique_ptr<SendablePhotoAccessHelperInitContext> &context);
1315
1316 template napi_status SendableMediaLibraryNapiUtils::ParseArgsStringCallback<unique_ptr<SendableFAAsyncContext>>(
1317 napi_env env, napi_callback_info info, unique_ptr<SendableFAAsyncContext> &context, string ¶m);
1318
1319 template napi_status SendableMediaLibraryNapiUtils::ParseArgsStringCallback<unique_ptr<SendablePANAsyncContext>>(
1320 napi_env env, napi_callback_info info,
1321 unique_ptr<SendablePANAsyncContext> &context, string ¶m);
1322
1323 template napi_status SendableMediaLibraryNapiUtils::ParseArgsBoolCallBack<unique_ptr<SendableFAAsyncContext>>(
1324 napi_env env, napi_callback_info info, unique_ptr<SendableFAAsyncContext> &context, bool ¶m);
1325
1326 template napi_status SendableMediaLibraryNapiUtils::AsyncContextSetObjectInfo<unique_ptr<SendablePAHAsyncContext>>(
1327 napi_env env, napi_callback_info info, unique_ptr<SendablePAHAsyncContext> &asyncContext,
1328 const size_t minArgs, const size_t maxArgs);
1329
1330 template napi_status SendableMediaLibraryNapiUtils::AsyncContextSetObjectInfo<unique_ptr<SendableFAAsyncContext>>(
1331 napi_env env, napi_callback_info info, unique_ptr<SendableFAAsyncContext> &asyncContext,
1332 const size_t minArgs, const size_t maxArgs);
1333
1334 template napi_status SendableMediaLibraryNapiUtils::AsyncContextSetObjectInfo<unique_ptr<SendablePANAsyncContext>>(
1335 napi_env env, napi_callback_info info, unique_ptr<SendablePANAsyncContext> &asyncContext,
1336 const size_t minArgs, const size_t maxArgs);
1337
1338 template napi_value SendableMediaLibraryNapiUtils::NapiCreateAsyncWork<SendablePAHAsyncContext>(
1339 napi_env env, unique_ptr<SendablePAHAsyncContext> &asyncContext, const string &resourceName,
1340 void (*execute)(napi_env, void *), void (*complete)(napi_env, napi_status, void *));
1341
1342 template napi_value SendableMediaLibraryNapiUtils::NapiCreateAsyncWork<SendablePhotoAccessHelperInitContext>(
1343 napi_env env, unique_ptr<SendablePhotoAccessHelperInitContext> &asyncContext, const string &resourceName,
1344 void (*execute)(napi_env, void *), void (*complete)(napi_env, napi_status, void *));
1345
1346 template napi_value SendableMediaLibraryNapiUtils::NapiCreateAsyncWork<SendableFAAsyncContext>(napi_env env,
1347 unique_ptr<SendableFAAsyncContext> &asyncContext, const string &resourceName,
1348 void (*execute)(napi_env, void *), void (*complete)(napi_env, napi_status, void *));
1349
1350 template napi_value SendableMediaLibraryNapiUtils::NapiCreateAsyncWork<SendablePANAsyncContext>(
1351 napi_env env, unique_ptr<SendablePANAsyncContext> &asyncContext, const string &resourceName,
1352 void (*execute)(napi_env, void *), void (*complete)(napi_env, napi_status, void *));
1353
1354 template napi_status SendableMediaLibraryNapiUtils::ParseArgsNumberCallback<unique_ptr<SendableFAAsyncContext>>(
1355 napi_env env, napi_callback_info info, unique_ptr<SendableFAAsyncContext> &context, int32_t &value);
1356
1357 template napi_status SendableMediaLibraryNapiUtils::ParseArgsOnlyCallBack<unique_ptr<SendableFAAsyncContext>>(
1358 napi_env env, napi_callback_info info, unique_ptr<SendableFAAsyncContext> &context);
1359
1360 template napi_status SendableMediaLibraryNapiUtils::ParsePredicates<unique_ptr<SendablePAHAsyncContext>>(
1361 napi_env env, const napi_value arg, unique_ptr<SendablePAHAsyncContext> &context,
1362 const FetchOptionType &fetchOptType);
1363
1364 } // namespace Media
1365 } // namespace OHOS
1366