• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param)
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 &param)
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 &param);
1318 
1319 template napi_status SendableMediaLibraryNapiUtils::ParseArgsStringCallback<unique_ptr<SendablePANAsyncContext>>(
1320     napi_env env, napi_callback_info info,
1321     unique_ptr<SendablePANAsyncContext> &context, string &param);
1322 
1323 template napi_status SendableMediaLibraryNapiUtils::ParseArgsBoolCallBack<unique_ptr<SendableFAAsyncContext>>(
1324     napi_env env, napi_callback_info info, unique_ptr<SendableFAAsyncContext> &context, bool &param);
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