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