• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "MediaLibraryAniUtils"
16 
17 #include "medialibrary_ani_utils.h"
18 
19 #include <cctype>
20 #include "accesstoken_kit.h"
21 #include "basic/result_set.h"
22 #include "datashare_predicates.h"
23 #include "file_asset_info_ani.h"
24 #include "location_column.h"
25 #include "ipc_skeleton.h"
26 #include "media_device_column.h"
27 #include "media_file_uri.h"
28 #include "media_file_utils.h"
29 #include "media_library_ani.h"
30 #include "medialibrary_client_errno.h"
31 #include "medialibrary_db_const.h"
32 #include "medialibrary_errno.h"
33 #include "medialibrary_ani_enum_comm.h"
34 #include "medialibrary_tracer.h"
35 #include "medialibrary_type_const.h"
36 #include "photo_album_ani.h"
37 #include "photo_map_column.h"
38 #include "tokenid_kit.h"
39 #include "userfile_client.h"
40 #include "vision_album_column.h"
41 #include "vision_column.h"
42 #include "vision_face_tag_column.h"
43 #include "vision_pose_column.h"
44 #include "vision_image_face_column.h"
45 #include "userfilemgr_uri.h"
46 #include <nlohmann/json.hpp>
47 
48 using namespace std;
49 using namespace OHOS::DataShare;
50 using namespace OHOS::Security;
51 
52 namespace OHOS {
53 namespace Media {
54 static constexpr int32_t FIELD_IDX = 0;
55 static constexpr int32_t VALUE_IDX = 1;
56 static const string EMPTY_STRING = "";
57 using json = nlohmann::json;
58 
isArray(ani_env * env,ani_object object)59 ani_boolean MediaLibraryAniUtils::isArray(ani_env *env, ani_object object)
60 {
61     ani_boolean isArray = ANI_FALSE;
62     ani_class cls {};
63     static const std::string className = "Lescompat/Array;";
64     CHECK_COND_RET(ANI_OK == env->FindClass(className.c_str(), &cls), isArray, "Can't find Lescompat/Array.");
65 
66     ani_static_method static_method {};
67     CHECK_COND_RET(ANI_OK == env->Class_FindStaticMethod(cls, "isArray", nullptr, &static_method), isArray,
68         "Can't find method isArray in Lescompat/Array.");
69 
70     CHECK_COND_RET(ANI_OK == env->Class_CallStaticMethod_Boolean(cls, static_method, &isArray, object),
71         isArray, "Call method isArray failed.");
72 
73     return isArray;
74 }
75 
isUndefined(ani_env * env,ani_object object)76 ani_boolean MediaLibraryAniUtils::isUndefined(ani_env *env, ani_object object)
77 {
78     ani_boolean isUndefined = ANI_TRUE;
79     CHECK_COND_RET(ANI_OK == env->Reference_IsUndefined(object, &isUndefined), ANI_TRUE,
80         "Call Reference_IsUndefined failed.");
81     return isUndefined;
82 }
83 
GetBool(ani_env * env,ani_boolean arg,bool & value)84 ani_status MediaLibraryAniUtils::GetBool(ani_env *env, ani_boolean arg, bool &value)
85 {
86     value = (arg == ANI_TRUE);
87     return ANI_OK;
88 }
89 
GetBool(ani_env * env,ani_object arg,bool & value)90 ani_status MediaLibraryAniUtils::GetBool(ani_env *env, ani_object arg, bool &value)
91 {
92     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
93 
94     ani_class cls {};
95     static const std::string className = "Lstd/core/Boolean;";
96     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Boolean.");
97 
98     ani_method method {};
99     CHECK_STATUS_RET(env->Class_FindMethod(cls, "valueOf", nullptr, &method),
100         "Can't find method valueOf in Lstd/core/Boolean.");
101 
102     ani_boolean result = 0;
103     CHECK_STATUS_RET(env->Object_CallMethod_Boolean(arg, method, &result), "Call method valueOf failed.");
104 
105     return GetBool(env, result, value);
106 }
107 
GetByte(ani_env * env,ani_byte arg,uint8_t & value)108 ani_status MediaLibraryAniUtils::GetByte(ani_env *env, ani_byte arg, uint8_t &value)
109 {
110     value = static_cast<uint8_t>(arg);
111     return ANI_OK;
112 }
113 
GetByte(ani_env * env,ani_object arg,uint8_t & value)114 ani_status MediaLibraryAniUtils::GetByte(ani_env *env, ani_object arg, uint8_t &value)
115 {
116     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
117 
118     ani_class cls {};
119     static const std::string className = "Lstd/core/Byte;";
120     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Byte.");
121 
122     ani_method method {};
123     CHECK_STATUS_RET(env->Class_FindMethod(cls, "byteValue", nullptr, &method),
124         "Can't find method byteValue in Lstd/core/Byte.");
125 
126     ani_byte result;
127     CHECK_STATUS_RET(env->Object_CallMethod_Byte(arg, method, &result), "Call method byteValue failed.");
128 
129     return GetByte(env, result, value);
130 }
131 
GetShort(ani_env * env,ani_short arg,int16_t & value)132 ani_status MediaLibraryAniUtils::GetShort(ani_env *env, ani_short arg, int16_t &value)
133 {
134     value = static_cast<int16_t>(arg);
135     return ANI_OK;
136 }
137 
GetShort(ani_env * env,ani_object arg,int16_t & value)138 ani_status MediaLibraryAniUtils::GetShort(ani_env *env, ani_object arg, int16_t &value)
139 {
140     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
141 
142     ani_class cls {};
143     static const std::string className = "Lstd/core/Short;";
144     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Short.");
145 
146     ani_method method {};
147     CHECK_STATUS_RET(env->Class_FindMethod(cls, "shortValue", nullptr, &method),
148         "Can't find method shortValue in Lstd/core/Short.");
149 
150     ani_short result;
151     CHECK_STATUS_RET(env->Object_CallMethod_Short(arg, method, &result), "Call method shortValue failed.");
152 
153     return GetShort(env, result, value);
154 }
155 
GetInt32(ani_env * env,ani_int arg,int32_t & value)156 ani_status MediaLibraryAniUtils::GetInt32(ani_env *env, ani_int arg, int32_t &value)
157 {
158     value = static_cast<int32_t>(arg);
159     return ANI_OK;
160 }
161 
GetInt32(ani_env * env,ani_object arg,int32_t & value)162 ani_status MediaLibraryAniUtils::GetInt32(ani_env *env, ani_object arg, int32_t &value)
163 {
164     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
165 
166     ani_class cls {};
167     static const std::string className = "Lstd/core/Int;";
168     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Int.");
169 
170     ani_method method {};
171     CHECK_STATUS_RET(env->Class_FindMethod(cls, "intValue", nullptr, &method),
172         "Can't find method intValue in Lstd/core/Int.");
173 
174     ani_int result;
175     CHECK_STATUS_RET(env->Object_CallMethod_Int(arg, method, &result), "Call method intValue failed.");
176 
177     return GetInt32(env, result, value);
178 }
179 
GetUint32(ani_env * env,ani_int arg,uint32_t & value)180 ani_status MediaLibraryAniUtils::GetUint32(ani_env *env, ani_int arg, uint32_t &value)
181 {
182     value = static_cast<uint32_t>(arg);
183     return ANI_OK;
184 }
185 
GetUint32(ani_env * env,ani_object arg,uint32_t & value)186 ani_status MediaLibraryAniUtils::GetUint32(ani_env *env, ani_object arg, uint32_t &value)
187 {
188     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
189 
190     ani_class cls {};
191     static const std::string className = "Lstd/core/Int;";
192     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Int.");
193 
194     ani_method method {};
195     CHECK_STATUS_RET(env->Class_FindMethod(cls, "intValue", nullptr, &method),
196         "Can't find method intValue in Lstd/core/Int.");
197 
198     ani_int result;
199     CHECK_STATUS_RET(env->Object_CallMethod_Int(arg, method, &result), "Call method intValue failed.");
200     return GetUint32(env, result, value);
201 }
202 
GetInt64(ani_env * env,ani_long arg,int64_t & value)203 ani_status MediaLibraryAniUtils::GetInt64(ani_env *env, ani_long arg, int64_t &value)
204 {
205     value = static_cast<int64_t>(arg);
206     return ANI_OK;
207 }
208 
GetInt64(ani_env * env,ani_object arg,int64_t & value)209 ani_status MediaLibraryAniUtils::GetInt64(ani_env *env, ani_object arg, int64_t &value)
210 {
211     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
212 
213     ani_class cls {};
214     static const std::string className = "Lstd/core/Int;";
215     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Int.");
216 
217     ani_method method {};
218     CHECK_STATUS_RET(env->Class_FindMethod(cls, "longValue", nullptr, &method),
219         "Can't find method longValue in Lstd/core/Int.");
220 
221     ani_long result;
222     CHECK_STATUS_RET(env->Object_CallMethod_Long(arg, method, &result), "Call method longValue failed.");
223     return GetInt64(env, result, value);
224 }
225 
GetFloat(ani_env * env,ani_float arg,float & value)226 ani_status MediaLibraryAniUtils::GetFloat(ani_env *env, ani_float arg, float &value)
227 {
228     value = static_cast<float>(arg);
229     return ANI_OK;
230 }
231 
GetFloat(ani_env * env,ani_object arg,float & value)232 ani_status MediaLibraryAniUtils::GetFloat(ani_env *env, ani_object arg, float &value)
233 {
234     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
235 
236     ani_class cls {};
237     static const std::string className = "Lstd/core/Float;";
238     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Float.");
239 
240     ani_method method {};
241     CHECK_STATUS_RET(env->Class_FindMethod(cls, "floatValue", nullptr, &method),
242         "Can't find method floatValue in Lstd/core/Float.");
243 
244     ani_float result;
245     CHECK_STATUS_RET(env->Object_CallMethod_Float(arg, method, &result), "Call method floatValue failed.");
246     return GetFloat(env, result, value);
247 }
248 
GetDouble(ani_env * env,ani_double arg,double & value)249 ani_status MediaLibraryAniUtils::GetDouble(ani_env *env, ani_double arg, double &value)
250 {
251     value = static_cast<double>(arg);
252     return ANI_OK;
253 }
254 
GetDouble(ani_env * env,ani_object arg,double & value)255 ani_status MediaLibraryAniUtils::GetDouble(ani_env *env, ani_object arg, double &value)
256 {
257     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
258 
259     ani_class cls {};
260     static const std::string className = "Lstd/core/Double;";
261     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lstd/core/Double.");
262 
263     ani_method method {};
264     CHECK_STATUS_RET(env->Class_FindMethod(cls, "doubleValue", nullptr, &method),
265         "Can't find method doubleValue in Lstd/core/Double.");
266 
267     ani_double result;
268     CHECK_STATUS_RET(env->Object_CallMethod_Double(arg, method, &result), "Call method doubleValue failed.");
269     return GetDouble(env, result, value);
270 }
271 
GetString(ani_env * env,ani_string arg,std::string & str)272 ani_status MediaLibraryAniUtils::GetString(ani_env *env, ani_string arg, std::string &str)
273 {
274     CHECK_COND_RET(arg != nullptr, ANI_INVALID_ARGS, "GetString invalid arg");
275 
276     ani_size srcSize = 0;
277     CHECK_STATUS_RET(env->String_GetUTF8Size(arg, &srcSize), "String_GetUTF8Size failed");
278 
279     std::vector<char> buffer(srcSize + 1);
280     ani_size dstSize = 0;
281     CHECK_STATUS_RET(env->String_GetUTF8SubString(arg, 0, srcSize, buffer.data(), buffer.size(), &dstSize),
282         "String_GetUTF8SubString failed");
283 
284     str.assign(buffer.data(), dstSize);
285     return ANI_OK;
286 }
287 
GetString(ani_env * env,ani_object arg,std::string & str)288 ani_status MediaLibraryAniUtils::GetString(ani_env *env, ani_object arg, std::string &str)
289 {
290     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
291 
292     return GetString(env, static_cast<ani_string>(arg), str);
293 }
294 
ToAniString(ani_env * env,const std::string & str,ani_string & aniStr)295 ani_status MediaLibraryAniUtils::ToAniString(ani_env *env, const std::string &str, ani_string &aniStr)
296 {
297     CHECK_STATUS_RET(env->String_NewUTF8(str.c_str(), str.size(), &aniStr), "String_NewUTF8 failed");
298     return ANI_OK;
299 }
300 
ToAniInt(ani_env * env,const std::int32_t & int32,ani_int & aniInt)301 ani_status MediaLibraryAniUtils::ToAniInt(ani_env *env, const std::int32_t &int32, ani_int &aniInt)
302 {
303     aniInt = static_cast<ani_int>(int32);
304     return ANI_OK;
305 }
306 
ToAniLong(ani_env * env,const std::int64_t & int64,ani_long & aniLong)307 ani_status MediaLibraryAniUtils::ToAniLong(ani_env *env, const std::int64_t &int64, ani_long &aniLong)
308 {
309     aniLong = static_cast<ani_long>(int64);
310     return ANI_OK;
311 }
312 
ToAniDouble(ani_env * env,const double & arg,ani_double & aniDouble)313 ani_status MediaLibraryAniUtils::ToAniDouble(ani_env *env, const double &arg, ani_double &aniDouble)
314 {
315     aniDouble = static_cast<ani_double>(arg);
316     return ANI_OK;
317 }
318 
GetParamStringWithLength(ani_env * env,ani_string arg,int32_t maxLen,std::string & str)319 ani_status MediaLibraryAniUtils::GetParamStringWithLength(ani_env *env, ani_string arg, int32_t maxLen,
320     std::string &str)
321 {
322     ani_size srcSize = 0;
323     CHECK_STATUS_RET(env->String_GetUTF8Size(arg, &srcSize), "String_GetUTF8Size failed");
324     if (static_cast<int32_t>(srcSize) > maxLen) {
325         ANI_ERR_LOG("Invalid string length: %{public}zu, maxLen: %{public}d", srcSize, maxLen);
326         return ANI_INVALID_ARGS;
327     }
328     return GetString(env, arg, str);
329 }
330 
GetParamStringPathMax(ani_env * env,ani_string arg,std::string & str)331 ani_status MediaLibraryAniUtils::GetParamStringPathMax(ani_env *env, ani_string arg, std::string &str)
332 {
333     return GetParamStringWithLength(env, arg, PATH_MAX, str);
334 }
335 
GetParamStringPathMax(ani_env * env,ani_object arg,std::string & str)336 ani_status MediaLibraryAniUtils::GetParamStringPathMax(ani_env *env, ani_object arg, std::string &str)
337 {
338     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
339     return GetParamStringWithLength(env, static_cast<ani_string>(arg), PATH_MAX, str);
340 }
341 
ToAniBooleanObject(ani_env * env,bool src,ani_object & aniObj)342 ani_status MediaLibraryAniUtils::ToAniBooleanObject(ani_env *env, bool src, ani_object &aniObj)
343 {
344     static const char *className = "Lstd/core/Boolean;";
345     ani_class cls {};
346     CHECK_STATUS_RET(env->FindClass(className, &cls), "Failed to find class: %{public}s", className);
347 
348     ani_method ctor {};
349     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "Z:V", &ctor), "Failed to find method: ctor");
350 
351     ani_boolean aniBool = src ? ANI_TRUE : ANI_FALSE;
352     CHECK_STATUS_RET(env->Object_New(cls, ctor, &aniObj, aniBool), "New bool Object Fail");
353     return ANI_OK;
354 }
355 
ToAniIntObject(ani_env * env,int32_t src,ani_object & aniObj)356 ani_status MediaLibraryAniUtils::ToAniIntObject(ani_env *env, int32_t src, ani_object &aniObj)
357 {
358     static const char *className = "Lstd/core/Int;";
359     ani_class cls {};
360     CHECK_STATUS_RET(env->FindClass(className, &cls), "Failed to find class: %{public}s", className);
361 
362     ani_method ctor {};
363     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "I:V", &ctor), "Failed to find method: ctor");
364 
365     CHECK_STATUS_RET(env->Object_New(cls, ctor, &aniObj, static_cast<ani_int>(src)), "New int32 Object Fail");
366     return ANI_OK;
367 }
368 
ToAniDoubleObject(ani_env * env,double src,ani_object & aniObj)369 ani_status MediaLibraryAniUtils::ToAniDoubleObject(ani_env *env, double src, ani_object &aniObj)
370 {
371     static const char *className = "Lstd/core/Double;";
372     ani_class cls {};
373     CHECK_STATUS_RET(env->FindClass(className, &cls), "Failed to find class: %{public}s", className);
374 
375     ani_method ctor {};
376     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "D:V", &ctor), "Failed to find method: ctor");
377 
378     CHECK_STATUS_RET(env->Object_New(cls, ctor, &aniObj, static_cast<ani_double>(src)), "New double Object Fail");
379     return ANI_OK;
380 }
381 
ToAniLongObject(ani_env * env,int64_t src,ani_object & aniObj)382 ani_status MediaLibraryAniUtils::ToAniLongObject(ani_env *env, int64_t src, ani_object &aniObj)
383 {
384     static const char *className = "Lescompat/BigInt;";
385     ani_class cls {};
386     CHECK_STATUS_RET(env->FindClass(className, &cls), "Failed to find class: %{public}s", className);
387 
388     ani_method ctor {};
389     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor), "Failed to find method: ctor");
390 
391     CHECK_STATUS_RET(env->Object_New(cls, ctor, &aniObj, static_cast<ani_long>(src)), "New int64_t Object Fail");
392     return ANI_OK;
393 }
394 
GetUint32Array(ani_env * env,ani_object arg,std::vector<uint32_t> & array)395 ani_status MediaLibraryAniUtils::GetUint32Array(ani_env *env, ani_object arg, std::vector<uint32_t> &array)
396 {
397     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
398     CHECK_COND_RET(isArray(env, arg) == ANI_TRUE, ANI_ERROR, "invalid parameter.");
399 
400     ani_double length;
401     CHECK_STATUS_RET(env->Object_GetPropertyByName_Double(arg, "length", &length),
402         "Call method <get>length failed.");
403 
404     for (int i = 0; i < static_cast<ani_int>(length); i++) {
405         ani_ref value;
406         CHECK_STATUS_RET(env->Object_CallMethodByName_Ref(arg, "$_get", "I:Lstd/core/Object;", &value, (ani_int)i),
407             "Call method $_get failed.");
408 
409         uint32_t uValue = 0;
410         CHECK_STATUS_RET(GetUint32(env, (ani_object)value, uValue), "Call method GetUint32 failed.");
411 
412         array.emplace_back(uValue);
413     }
414     return ANI_OK;
415 }
416 
ToAniInt32Array(ani_env * env,const std::vector<uint32_t> & array,ani_object & aniArray)417 ani_status MediaLibraryAniUtils::ToAniInt32Array(ani_env *env, const std::vector<uint32_t> &array,
418     ani_object &aniArray)
419 {
420     ani_class cls {};
421     static const std::string className = "Lescompat/Array;";
422     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lescompat/Array.");
423 
424     ani_method arrayConstructor {};
425     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "I:V;", &arrayConstructor),
426         "Can't find method <ctor> in Lescompat/Array.");
427 
428     CHECK_STATUS_RET(env->Object_New(cls, arrayConstructor, &aniArray, array.size()), "Call method <ctor> failed.");
429 
430     ani_method setMethod {};
431     CHECK_STATUS_RET(env->Class_FindMethod(cls, "$_set", "ILstd/core/Object;:V", &setMethod),
432         "Can't find method $_set in Lescompat/Array.");
433 
434     for (size_t i = 0; i < array.size(); i++) {
435         ani_int aniInt = static_cast<ani_int>(array[i]);
436         CHECK_STATUS_RET(env->Object_CallMethod_Void(aniArray, setMethod, (ani_int)i, aniInt),
437             "Call method $_set failed.");
438     }
439     return ANI_OK;
440 }
441 
GetStringArray(ani_env * env,ani_object arg,std::vector<std::string> & array)442 ani_status MediaLibraryAniUtils::GetStringArray(ani_env *env, ani_object arg, std::vector<std::string> &array)
443 {
444     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
445     CHECK_COND_RET(isArray(env, arg) == ANI_TRUE, ANI_ERROR, "invalid parameter.");
446 
447     ani_double length;
448     CHECK_STATUS_RET(env->Object_GetPropertyByName_Double(arg, "length", &length),
449         "Call method <get>length failed.");
450 
451     for (int i = 0; i < static_cast<ani_int>(length); i++) {
452         ani_ref value {};
453         CHECK_STATUS_RET(env->Object_CallMethodByName_Ref(arg, "$_get", "I:Lstd/core/Object;", &value, (ani_int)i),
454             "Call method $_get failed.");
455 
456         std::string sValue;
457         CHECK_STATUS_RET(GetString(env, (ani_object)value, sValue), "Call GetString failed.");
458         array.emplace_back(sValue);
459     }
460     return ANI_OK;
461 }
462 
ToAniStringArray(ani_env * env,const std::vector<std::string> & array,ani_object & aniArray)463 ani_status MediaLibraryAniUtils::ToAniStringArray(ani_env *env, const std::vector<std::string> &array,
464     ani_object &aniArray)
465 {
466     ani_class cls {};
467     static const std::string className = "Lescompat/Array;";
468     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lescompat/Array.");
469 
470     ani_method arrayConstructor {};
471     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "I:V", &arrayConstructor),
472         "Can't find method <ctor> in Lescompat/Array.");
473 
474     CHECK_STATUS_RET(env->Object_New(cls, arrayConstructor, &aniArray, array.size()), "Call method <ctor> failed.");
475 
476     ani_method setMethod {};
477     CHECK_STATUS_RET(env->Class_FindMethod(cls, "$_set", "ILstd/core/Object;:V", &setMethod),
478         "Can't find method $_set in Lescompat/Array.");
479 
480     for (size_t i = 0; i < array.size(); i++) {
481         ani_string aniString {};
482         CHECK_STATUS_RET(ToAniString(env, array[i], aniString), "ToAniString failed");
483         CHECK_STATUS_RET(env->Object_CallMethod_Void(aniArray, setMethod, (ani_int)i, aniString),
484             "Call method $_set failed.");
485     }
486     return ANI_OK;
487 }
488 
GetProperty(ani_env * env,ani_object arg,const std::string & propName,std::string & propValue)489 ani_status MediaLibraryAniUtils::GetProperty(ani_env *env, ani_object arg, const std::string &propName,
490     std::string &propValue)
491 {
492     ani_object propObj;
493     CHECK_STATUS_RET(GetProperty(env, arg, propName, propObj), "GetProperty failed.");
494     CHECK_STATUS_RET(GetString(env, propObj, propValue), "GetString failed.");
495     return ANI_OK;
496 }
497 
GetProperty(ani_env * env,ani_object arg,const std::string & propName,ani_object & propObj)498 ani_status MediaLibraryAniUtils::GetProperty(ani_env *env, ani_object arg, const std::string &propName,
499     ani_object &propObj)
500 {
501     ani_ref propRef;
502     CHECK_STATUS_RET(env->Object_GetPropertyByName_Ref(arg, propName.c_str(), &propRef),
503         "Object_GetPropertyByName_Ref failed.");
504     propObj = static_cast<ani_object>(propRef);
505     return ANI_OK;
506 }
507 
GetArrayProperty(ani_env * env,ani_object arg,const std::string & propName,std::vector<std::string> & array)508 ani_status MediaLibraryAniUtils::GetArrayProperty(ani_env *env, ani_object arg, const std::string &propName,
509     std::vector<std::string> &array)
510 {
511     ani_object property;
512     CHECK_STATUS_RET(GetProperty(env, arg, propName, property), "GetProperty failed.");
513     CHECK_STATUS_RET(GetStringArray(env, property, array), "GetStringArray failed.");
514     return ANI_OK;
515 }
516 
GetArrayBuffer(ani_env * env,ani_object arg,std::unique_ptr<uint8_t[]> & buffer,size_t & size)517 ani_status MediaLibraryAniUtils::GetArrayBuffer(ani_env *env, ani_object arg, std::unique_ptr<uint8_t[]> &buffer,
518     size_t &size)
519 {
520     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
521     ani_int length;
522     CHECK_STATUS_RET(env->Object_CallMethodByName_Int(arg, "getByteLength", nullptr, &length),
523         "GetArrayBuffer Object_CallMethodByName_Int failed.");
524     size = static_cast<size_t>(length);
525     buffer = std::make_unique<uint8_t[]>(size);
526     CHECK_COND_RET(buffer != nullptr, ANI_ERROR, "GetArrayBuffer make buffer failed");
527     for (int i = 0; i < static_cast<int>(size); ++i) {
528         ani_byte value {};
529         CHECK_STATUS_RET(env->Object_CallMethodByName_Byte(arg, "at", nullptr, &value, static_cast<ani_int>(i)),
530             "GetArrayBuffer Call method at failed.");
531         CHECK_STATUS_RET(GetByte(env, value, buffer[i]), "GetArrayBuffer GetByte failed.");
532     }
533     return ANI_OK;
534 }
535 
GetOptionalStringPathMaxField(ani_env * env,ani_object src,const std::string & fieldName,std::string & value)536 ani_status MediaLibraryAniUtils::GetOptionalStringPathMaxField(ani_env *env, ani_object src,
537     const std::string &fieldName, std::string &value)
538 {
539     ani_ref field_ref;
540     if (ANI_OK != env->Object_GetPropertyByName_Ref(src, fieldName.c_str(), &field_ref)) {
541         ANI_ERR_LOG("Object_GetPropertyByName_Ref %{public}s Failed", fieldName.c_str());
542         return ANI_INVALID_ARGS;
543     }
544 
545     ani_boolean isUndefined;
546     env->Reference_IsUndefined(field_ref, &isUndefined);
547     if (isUndefined) {
548         ANI_INFO_LOG("%{public}s is undefined", fieldName.c_str());
549         return ANI_NOT_FOUND;
550     }
551 
552     MediaLibraryAniUtils::GetParamStringPathMax(env, static_cast<ani_string>(field_ref), value);
553     ANI_INFO_LOG("%{public}s Get %{public}s: %{public}s", __func__, fieldName.c_str(), value.c_str());
554     return ANI_OK;
555 }
556 
GetOptionalEnumInt32Field(ani_env * env,ani_object src,const std::string & fieldName,int32_t & value)557 ani_status MediaLibraryAniUtils::GetOptionalEnumInt32Field(ani_env *env, ani_object src, const std::string &fieldName,
558     int32_t &value)
559 {
560     ani_ref field_ref;
561     if (ANI_OK != env->Object_GetPropertyByName_Ref(src, fieldName.c_str(), &field_ref)) {
562         ANI_ERR_LOG("Object_GetPropertyByName_Ref %{public}s Failed", fieldName.c_str());
563         return ANI_INVALID_ARGS;
564     }
565 
566     ani_boolean isUndefined;
567     env->Reference_IsUndefined(field_ref, &isUndefined);
568     if (isUndefined) {
569         ANI_INFO_LOG("%{public}s is undefined", fieldName.c_str());
570         return ANI_NOT_FOUND;
571     }
572 
573     ani_int enum_value {};
574     CHECK_STATUS_RET(env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(field_ref), &enum_value),
575         "EnumItem_GetValue_Int failed");
576     CHECK_STATUS_RET(GetInt32(env, enum_value, value), "GetInt32 failed");
577     ANI_INFO_LOG("%{public}s Get %{public}s: %{public}d", __func__, fieldName.c_str(), value);
578     return ANI_OK;
579 }
580 
GetOptionalEnumStringField(ani_env * env,ani_object src,const std::string & fieldName,std::string & value)581 ani_status MediaLibraryAniUtils::GetOptionalEnumStringField(ani_env *env, ani_object src, const std::string &fieldName,
582     std::string &value)
583 {
584     ani_ref field_ref;
585     if (ANI_OK != env->Object_GetPropertyByName_Ref(src, fieldName.c_str(), &field_ref)) {
586         ANI_ERR_LOG("Object_GetPropertyByName_Ref %{public}s Failed", fieldName.c_str());
587         return ANI_INVALID_ARGS;
588     }
589 
590     ani_boolean isUndefined;
591     env->Reference_IsUndefined(field_ref, &isUndefined);
592     if (isUndefined) {
593         ANI_INFO_LOG("%{public}s is undefined", fieldName.c_str());
594         return ANI_NOT_FOUND;
595     }
596 
597     ani_string aniString {};
598     CHECK_STATUS_RET(env->EnumItem_GetValue_String(static_cast<ani_enum_item>(field_ref), &aniString),
599         "EnumItem_GetValue_String failed");
600     CHECK_STATUS_RET(GetString(env, aniString, value), "GetString failed");
601     ANI_INFO_LOG("%{public}s Get %{public}s: %{public}s", __func__, fieldName.c_str(), value.c_str());
602     return ANI_OK;
603 }
604 
GetCreateOptions(ani_env * env,ani_object src)605 std::unordered_map<std::string, std::variant<int32_t, bool, std::string>> MediaLibraryAniUtils::GetCreateOptions(
606     ani_env *env, ani_object src)
607 {
608     std::unordered_map<std::string, std::variant<int32_t, bool, std::string>> result;
609     std::string title;
610     if (ANI_OK == GetOptionalStringPathMaxField(env, src, "title", title)) {
611         result[PhotoColumn::MEDIA_TITLE] = title;
612     }
613 
614     int32_t subtype;
615     if (ANI_OK == GetOptionalEnumInt32Field(env, src, "subtype", subtype)) {
616         result[PhotoColumn::PHOTO_SUBTYPE] = subtype;
617     }
618     return result;
619 }
620 
GetPhotoCreateOptions(ani_env * env,ani_object src)621 std::unordered_map<std::string, std::variant<int32_t, bool, std::string>> MediaLibraryAniUtils::GetPhotoCreateOptions(
622     ani_env *env, ani_object src)
623 {
624     std::unordered_map<std::string, std::variant<int32_t, bool, std::string>> result;
625     std::string cameraShotKey;
626     if (ANI_OK == GetOptionalStringPathMaxField(env, src, "cameraShotKey", cameraShotKey)) {
627         result[PhotoColumn::CAMERA_SHOT_KEY] = cameraShotKey;
628     }
629 
630     int32_t subtype;
631     if (ANI_OK == GetOptionalEnumInt32Field(env, src, "subtype", subtype)) {
632         result[PhotoColumn::PHOTO_SUBTYPE] = subtype;
633     }
634     return result;
635 }
636 
IsSystemApp()637 bool MediaLibraryAniUtils::IsSystemApp()
638 {
639     static bool isSys = AccessToken::TokenIdKit::IsSystemAppByFullTokenID(OHOS::IPCSkeleton::GetSelfTokenID());
640     return isSys;
641 }
642 
GetUriFromAsset(const std::shared_ptr<FileAsset> & fileAsset)643 static std::string GetUriFromAsset(const std::shared_ptr<FileAsset> &fileAsset)
644 {
645     std::string displayName = fileAsset->GetDisplayName();
646     std::string filePath = fileAsset->GetPath();
647     return MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()),
648         MediaFileUtils::GetExtraUri(displayName, filePath));
649 }
650 
GetUriArrayFromAssets(ani_env * env,ani_object arg,std::vector<std::string> & array)651 ani_status MediaLibraryAniUtils::GetUriArrayFromAssets(ani_env *env, ani_object arg, std::vector<std::string> &array)
652 {
653     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
654     CHECK_COND_RET(isArray(env, arg) == ANI_TRUE, ANI_ERROR, "invalid parameter.");
655 
656     ani_double length;
657     CHECK_STATUS_RET(env->Object_GetPropertyByName_Double(arg, "length", &length),
658         "Call method <get>length failed.");
659 
660     for (ani_int i = 0; i < static_cast<ani_int>(length); i++) {
661         ani_ref asset {};
662         CHECK_STATUS_RET(env->Object_CallMethodByName_Ref(arg, "$_get", "I:Lstd/core/Object;", &asset, i),
663             "Call method $_get failed.");
664 
665         FileAssetAni *obj = FileAssetAni::Unwrap(env, static_cast<ani_object>(asset));
666         if (obj == nullptr || obj->GetFileAssetInstance() == nullptr) {
667             AniError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get asset ani object");
668             return ANI_INVALID_ARGS;
669         }
670         MediaType mediaType = obj->GetFileAssetInstance()->GetMediaType();
671         if ((mediaType != MEDIA_TYPE_IMAGE && mediaType != MEDIA_TYPE_VIDEO)) {
672             ANI_INFO_LOG("Skip invalid asset, mediaType: %{public}d", mediaType);
673             continue;
674         }
675         array.push_back(GetUriFromAsset(obj->GetFileAssetInstance()));
676     }
677     return ANI_OK;
678 }
679 
ToFileAssetInfoAniArray(ani_env * env,std::vector<std::unique_ptr<FileAsset>> & array,ani_object & aniArray)680 ani_status MediaLibraryAniUtils::ToFileAssetInfoAniArray(ani_env *env, std::vector<std::unique_ptr<FileAsset>> &array,
681     ani_object &aniArray)
682 {
683     ani_class cls {};
684     static const std::string className = "Lescompat/Array;";
685     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lescompat/Array.");
686 
687     ani_method method {};
688     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "I:V", &method),
689         "Can't find method <ctor> in Lescompat/Array.");
690 
691     CHECK_STATUS_RET(env->Object_New(cls, method, &aniArray, array.size()), "Call method <ctor> failed.");
692 
693     ani_method setMethod {};
694     CHECK_STATUS_RET(env->Class_FindMethod(cls, "$_set", "ILstd/core/Object;:V", &setMethod),
695         "Can't find method set in Lescompat/Array.");
696 
697     for (size_t i = 0; i < array.size(); ++i) {
698         ani_object fileAssetObj = FileAssetInfo::ToFileAssetInfoObject(env, std::move(array[i]));
699         CHECK_COND_RET(fileAssetObj != nullptr, ANI_ERROR, "CreateFileAssetObj failed");
700         CHECK_STATUS_RET(env->Object_CallMethod_Void(aniArray, setMethod, (ani_int)i, fileAssetObj),
701             "Call method $_set failed.");
702     }
703     return ANI_OK;
704 }
705 
ToFileAssetAniArray(ani_env * env,std::vector<std::unique_ptr<FileAsset>> & array,ani_object & aniArray)706 ani_status MediaLibraryAniUtils::ToFileAssetAniArray(ani_env *env, std::vector<std::unique_ptr<FileAsset>> &array,
707     ani_object &aniArray)
708 {
709     ani_class cls {};
710     static const std::string className = "Lescompat/Array;";
711     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lescompat/Array.");
712 
713     ani_method method {};
714     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "I:V", &method),
715         "Can't find method <ctor> in Lescompat/Array.");
716 
717     CHECK_STATUS_RET(env->Object_New(cls, method, &aniArray, array.size()), "Call method <ctor> failed.");
718 
719     ani_method setMethod {};
720     CHECK_STATUS_RET(env->Class_FindMethod(cls, "$_set", "ILstd/core/Object;:V", &setMethod),
721         "Can't find method set in Lescompat/Array.");
722 
723     FileAssetAniMethod photoAccessAniMethod;
724     CHECK_STATUS_RET(FileAssetAni::InitFileAssetAniMethod(env, ResultNapiType::TYPE_PHOTOACCESS_HELPER,
725         photoAccessAniMethod), "Init photoAccessAniMethod failed");
726 
727     for (size_t i = 0; i < array.size(); ++i) {
728         FileAssetAni* fileAssetAni = FileAssetAni::CreateFileAsset(env, array[i]);
729         ani_object value = nullptr;
730         if (fileAssetAni->GetFileAssetInstance()->GetResultNapiType() ==
731             ResultNapiType::TYPE_PHOTOACCESS_HELPER) {
732             value = FileAssetAni::Wrap(env, fileAssetAni, photoAccessAniMethod);
733         }
734         CHECK_COND_RET(value != nullptr, ANI_ERROR, "CreatePhotoAsset failed");
735         CHECK_STATUS_RET(env->Object_CallMethod_Void(aniArray, setMethod, (ani_int)i, value),
736             "Call method $_set failed.");
737     }
738     return ANI_OK;
739 }
740 
ToFileAssetAniPtr(ani_env * env,std::unique_ptr<FetchResult<FileAsset>> fileAsset,ani_object & aniPtr)741 ani_status MediaLibraryAniUtils::ToFileAssetAniPtr(ani_env *env, std::unique_ptr<FetchResult<FileAsset>> fileAsset,
742     ani_object &aniPtr)
743 {
744     if (fileAsset == nullptr) {
745         ANI_ERR_LOG("fileAsset is nullptr");
746         return ANI_ERROR;
747     }
748     aniPtr = FetchFileResultAni::CreateFetchFileResult(env, move(fileAsset));
749     if (aniPtr == nullptr) {
750         ANI_ERR_LOG("FetchFileResultAni::CreateFetchFileResult failed");
751         return ANI_ERROR;
752     }
753     return ANI_OK;
754 }
755 
GetPhotoAlbumAniArray(ani_env * env,ani_object arg,std::vector<PhotoAlbumAni * > & array)756 ani_status MediaLibraryAniUtils::GetPhotoAlbumAniArray(ani_env *env, ani_object arg, std::vector<PhotoAlbumAni*> &array)
757 {
758     CHECK_COND_RET(isUndefined(env, arg) != ANI_TRUE, ANI_ERROR, "invalid property.");
759     CHECK_COND_RET(isArray(env, arg) == ANI_TRUE, ANI_ERROR, "invalid parameter.");
760 
761     ani_double length;
762     CHECK_STATUS_RET(env->Object_GetPropertyByName_Double(arg, "length", &length),
763         "Call method <get>length failed.");
764 
765     for (int i = 0; i < static_cast<ani_int>(length); i++) {
766         ani_ref value {};
767         CHECK_STATUS_RET(env->Object_CallMethodByName_Ref(arg, "$_get", "I:Lstd/core/Object;", &value, (ani_int)i),
768             "Call method $_get failed.");
769 
770         array.emplace_back(PhotoAlbumAni::UnwrapPhotoAlbumObject(env, (ani_object)value));
771     }
772     return ANI_OK;
773 }
774 
ToPhotoAlbumAniArray(ani_env * env,std::vector<unique_ptr<PhotoAlbum>> & array,ani_object & aniArray)775 ani_status MediaLibraryAniUtils::ToPhotoAlbumAniArray(ani_env *env, std::vector<unique_ptr<PhotoAlbum>> &array,
776     ani_object &aniArray)
777 {
778     ani_class cls {};
779     static const std::string className = "Lescompat/Array;";
780     CHECK_STATUS_RET(env->FindClass(className.c_str(), &cls), "Can't find Lescompat/Array.");
781 
782     ani_method method {};
783     CHECK_STATUS_RET(env->Class_FindMethod(cls, "<ctor>", "I:V", &method),
784         "Can't find method <ctor> in Lescompat/Array.");
785 
786     CHECK_STATUS_RET(env->Object_New(cls, method, &aniArray, array.size()), "Call method <ctor> failed.");
787 
788     ani_method setMethod {};
789     CHECK_STATUS_RET(env->Class_FindMethod(cls, "$_set", "ILstd/core/Object;:V", &setMethod),
790         "Can't find method set in Lescompat/Array.");
791 
792     for (size_t i = 0; i < array.size(); i++) {
793         ani_object value = PhotoAlbumAni::CreatePhotoAlbumAni(env, array[i]);
794         CHECK_COND_RET(value != nullptr, ANI_ERROR, "CreatePhotoAlbum failed");
795         CHECK_STATUS_RET(env->Object_CallMethod_Void(aniArray, setMethod, (ani_int)i, value),
796             "Call method $_set failed.");
797     }
798     return ANI_OK;
799 }
800 
801 template <class AniContext>
GetFetchOption(ani_env * env,ani_object fetchOptions,FetchOptionType fetchOptType,AniContext & context)802 ani_status MediaLibraryAniUtils::GetFetchOption(ani_env *env, ani_object fetchOptions, FetchOptionType fetchOptType,
803     AniContext &context)
804 {
805     // Parse the argument into fetchOption if any
806     CHECK_STATUS_RET(GetPredicate(env, fetchOptions, "predicates", context, fetchOptType), "invalid predicate");
807     CHECK_STATUS_RET(GetArrayProperty(env, fetchOptions, "fetchColumns", context->fetchColumn),
808         "Failed to parse fetchColumn");
809     return ANI_OK;
810 }
811 
UnwrapPredicate(ani_env * env,const ani_object predicates)812 DataSharePredicates* MediaLibraryAniUtils::UnwrapPredicate(ani_env *env, const ani_object predicates)
813 {
814     ani_class cls {};
815     static const std::string className = "L@ohos/data/dataSharePredicates/dataSharePredicates/DataSharePredicates;";
816     CHECK_COND_RET(env->FindClass(className.c_str(), &cls) == ANI_OK, nullptr, "Can't find class DataSharePredicates");
817 
818     ani_method getMethod {};
819     CHECK_COND_RET(env->Class_FindMethod(cls, "getNativePtr", nullptr, &getMethod) == ANI_OK, nullptr,
820         "Can't find method getNativePtr");
821 
822     ani_long nativePtr = 0;
823     CHECK_COND_RET(env->Object_CallMethod_Long(predicates, getMethod, &nativePtr) == ANI_OK, nullptr,
824         "Call getNativePtr fail");
825     CHECK_COND_RET(nativePtr != 0, nullptr, "Invalid nativePtr: 0");
826     return reinterpret_cast<DataSharePredicates*>(nativePtr);
827 }
828 
829 template <class AniContext>
GetPredicate(ani_env * env,const ani_object fetchOptions,const std::string & propName,AniContext & context,FetchOptionType fetchOptType)830 ani_status MediaLibraryAniUtils::GetPredicate(ani_env *env, const ani_object fetchOptions, const std::string &propName,
831     AniContext &context, FetchOptionType fetchOptType)
832 {
833     ani_object property {};
834     CHECK_STATUS_RET(GetProperty(env, fetchOptions, propName, property), "GetProperty predicates fail");
835 
836     DataSharePredicates* predicate = MediaLibraryAniUtils::UnwrapPredicate(env, property);
837     CHECK_COND_RET(predicate != nullptr, ANI_INVALID_ARGS, "UnwrapPredicate fail");
838     CHECK_COND_RET(HandleSpecialPredicate(context, predicate, fetchOptType), ANI_INVALID_ARGS, "invalid predicate");
839     CHECK_COND_RET(GetLocationPredicate(context, predicate), ANI_INVALID_ARGS, "invalid predicate");
840     return ANI_OK;
841 }
842 
HandleSpecialDateTypePredicate(const OperationItem & item,vector<OperationItem> & operations,const FetchOptionType & fetchOptType)843 static bool HandleSpecialDateTypePredicate(const OperationItem &item,
844     vector<OperationItem> &operations, const FetchOptionType &fetchOptType)
845 {
846     vector<string> dateTypes = { MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_DATE_TRASHED, MEDIA_DATA_DB_DATE_MODIFIED,
847         MEDIA_DATA_DB_DATE_TAKEN};
848     string dateType = item.GetSingle(FIELD_IDX);
849     auto it = find(dateTypes.begin(), dateTypes.end(), dateType);
850     if (it != dateTypes.end() && item.operation != DataShare::ORDER_BY_ASC &&
851         item.operation != DataShare::ORDER_BY_DESC) {
852         dateType += "_s";
853         operations.push_back({ item.operation, { dateType, static_cast<double>(item.GetSingle(VALUE_IDX)) } });
854         return true;
855     }
856     if (DATE_TRANSITION_MAP.count(dateType) != 0) {
857         dateType = DATE_TRANSITION_MAP.at(dateType);
858         operations.push_back({ item.operation, { dateType, static_cast<double>(item.GetSingle(VALUE_IDX)) } });
859         return true;
860     }
861     return false;
862 }
863 
864 template <class AniContext>
ParsePredicates(ani_env * env,const ani_object predicate,AniContext & context,FetchOptionType fetchOptType)865 ani_status MediaLibraryAniUtils::ParsePredicates(ani_env *env, const ani_object predicate, AniContext &context,
866     FetchOptionType fetchOptType)
867 {
868     DataSharePredicates* nativePredicate = MediaLibraryAniUtils::UnwrapPredicate(env, predicate);
869     CHECK_COND_RET(predicate != nullptr, ANI_INVALID_ARGS, "UnwrapPredicate fail");
870     CHECK_COND_RET(HandleSpecialPredicate(context, nativePredicate, fetchOptType), ANI_INVALID_ARGS,
871         "invalid predicate");
872     CHECK_COND_RET(GetLocationPredicate(context, nativePredicate), ANI_INVALID_ARGS, "invalid predicate");
873     return ANI_OK;
874 }
875 
876 template <class AniContext>
HandleSpecialPredicate(AniContext & context,DataSharePredicates * predicate,FetchOptionType fetchOptType)877 bool MediaLibraryAniUtils::HandleSpecialPredicate(AniContext &context,
878     DataSharePredicates *predicate, FetchOptionType fetchOptType)
879 {
880     if (predicate == nullptr) {
881         ANI_ERR_LOG("predicate is null");
882         return false;
883     }
884     vector<OperationItem> operations;
885     if (!ProcessPredicateItems(context, predicate->GetOperationList(), operations, fetchOptType)) {
886         return false;
887     }
888     context->predicates = DataSharePredicates(move(operations));
889     return true;
890 }
891 
892 template <class AniContext>
ProcessPredicateItems(AniContext & context,const vector<OperationItem> & items,vector<OperationItem> & operations,FetchOptionType fetchOptType)893 bool MediaLibraryAniUtils::ProcessPredicateItems(AniContext& context, const vector<OperationItem>& items,
894     vector<OperationItem>& operations, FetchOptionType fetchOptType)
895 {
896     for (auto& item : items) {
897         if (item.singleParams.empty()) {
898             operations.push_back(item);
899             continue;
900         }
901         if (HandleSpecialDateTypePredicate(item, operations, fetchOptType)) {
902             continue;
903         }
904         if (!HandleSpecialField(context, item, operations, fetchOptType)) {
905             return false;
906         }
907     }
908     return true;
909 }
910 
911 template <class AniContext>
HandleSpecialField(AniContext & context,const OperationItem & item,vector<OperationItem> & operations,FetchOptionType fetchOptType)912 bool MediaLibraryAniUtils::HandleSpecialField(AniContext& context, const OperationItem& item,
913     vector<OperationItem>& operations, FetchOptionType fetchOptType)
914 {
915     const string& field = static_cast<string>(item.GetSingle(FIELD_IDX));
916     const string& value = static_cast<string>(item.GetSingle(VALUE_IDX));
917     if (field == DEVICE_DB_NETWORK_ID) {
918         return HandleNetworkIdField(context, item, value);
919     }
920     if (field == MEDIA_DATA_DB_URI) {
921         return HandleUriField(context, item, value, operations, fetchOptType);
922     }
923     if (field == PENDING_STATUS || LOCATION_PARAM_MAP.count(field)) {
924         return true;
925     }
926     operations.push_back(item);
927     return true;
928 }
929 
930 template <class AniContext>
HandleNetworkIdField(AniContext & context,const OperationItem & item,const string & value)931 bool MediaLibraryAniUtils::HandleNetworkIdField(AniContext& context, const OperationItem& item, const string& value)
932 {
933     if (item.operation != DataShare::EQUAL_TO || value.empty()) {
934         ANI_ERR_LOG("DEVICE_DB_NETWORK_ID predicates not support %{public}d", item.operation);
935         return false;
936     }
937     context->networkId = value;
938     return true;
939 }
940 
941 template <class AniContext>
HandleUriField(AniContext & context,const OperationItem & item,const string & uriValue,vector<OperationItem> & operations,FetchOptionType fetchOptType)942 bool MediaLibraryAniUtils::HandleUriField(AniContext& context, const OperationItem& item,
943     const string& uriValue, vector<OperationItem>& operations, FetchOptionType fetchOptType)
944 {
945     if (item.operation != DataShare::EQUAL_TO) {
946         ANI_ERR_LOG("MEDIA_DATA_DB_URI predicates not support %{public}d", item.operation);
947         return false;
948     }
949     string uri = uriValue;
950     MediaFileUri::RemoveAllFragment(uri);
951     MediaFileUri fileUri(uri);
952     context->uri = uri;
953     if ((fetchOptType != ALBUM_FETCH_OPT) && (!fileUri.IsApi10())) {
954         fileUri = MediaFileUri(MediaFileUtils::GetRealUriFromVirtualUri(uri));
955     }
956     context->networkId = fileUri.GetNetworkId();
957     string field = (fetchOptType == ALBUM_FETCH_OPT) ? PhotoAlbumColumns::ALBUM_ID : MEDIA_DATA_DB_ID;
958     operations.push_back({ item.operation, { field, fileUri.GetFileId() } });
959     return true;
960 }
961 
962 template <class AniContext>
GetLocationPredicate(AniContext & context,DataSharePredicates * predicate)963 bool MediaLibraryAniUtils::GetLocationPredicate(AniContext &context, DataSharePredicates *predicate)
964 {
965     map<string, string> locationMap;
966     auto &items = predicate->GetOperationList();
967     for (auto &item : items) {
968         if (item.singleParams.empty()) {
969             continue;
970         }
971         if (LOCATION_PARAM_MAP.find(static_cast<string>(item.GetSingle(FIELD_IDX))) != LOCATION_PARAM_MAP.end()) {
972             if (item.operation != DataShare::EQUAL_TO) {
973                 ANI_ERR_LOG("location predicates not support %{public}d", item.operation);
974                 return false;
975             }
976             string param = static_cast<string>(item.GetSingle(FIELD_IDX));
977             string value = static_cast<string>(item.GetSingle(VALUE_IDX));
978             locationMap.insert(make_pair(param, value));
979             if (param == DIAMETER) {
980                 continue;
981             }
982             if (LOCATION_PARAM_MAP.at(param).second == DataShare::GREATER_THAN_OR_EQUAL_TO) {
983                 context->predicates.GreaterThanOrEqualTo(LOCATION_PARAM_MAP.at(param).first, value);
984                 continue;
985             }
986             if (LOCATION_PARAM_MAP.at(param).second == DataShare::LESS_THAN) {
987                 context->predicates.LessThan(LOCATION_PARAM_MAP.at(param).first, value);
988                 continue;
989             }
990             if (LOCATION_PARAM_MAP.at(param).second == DataShare::EQUAL_TO) {
991                 context->predicates.EqualTo(LOCATION_PARAM_MAP.at(param).first, value);
992                 continue;
993             }
994         }
995     }
996 
997     if (locationMap.count(DIAMETER) == 1 && locationMap.count(START_LATITUDE) == 1
998         && locationMap.count(START_LONGITUDE) == 1) {
999         // 0.5:Used for rounding down
1000         string latitudeIndex = "round((latitude - " + locationMap.at(START_LATITUDE) + ") / " +
1001             locationMap.at(DIAMETER) + " - 0.5)";
1002         string longitudeIndex = "round((longitude - " + locationMap.at(START_LONGITUDE) + ") / " +
1003             locationMap.at(DIAMETER) + " - 0.5)";
1004         string albumName = LATITUDE + "||'_'||" + LONGITUDE + "||'_'||" + latitudeIndex + "||'_'||" +
1005             longitudeIndex + " AS " + ALBUM_NAME;
1006         context->fetchColumn.push_back(albumName);
1007         string locationGroup = latitudeIndex + "," + longitudeIndex;
1008         context->predicates.GroupBy({ locationGroup });
1009     }
1010     return true;
1011 }
1012 
TransErrorCode(const string & Name,shared_ptr<DataShare::DataShareResultSet> resultSet)1013 int MediaLibraryAniUtils::TransErrorCode(const string &Name, shared_ptr<DataShare::DataShareResultSet> resultSet)
1014 {
1015     ANI_ERR_LOG("interface: %{public}s, server return nullptr", Name.c_str());
1016     // Query can't return errorcode, so assume nullptr as permission deny
1017     if (resultSet == nullptr) {
1018         return JS_ERR_PERMISSION_DENIED;
1019     }
1020     return ERR_DEFAULT;
1021 }
1022 
TransErrorCode(const string & Name,int error)1023 int MediaLibraryAniUtils::TransErrorCode(const string &Name, int error)
1024 {
1025     ANI_ERR_LOG("interface: %{public}s, server errcode:%{public}d ", Name.c_str(), error);
1026     // Transfer Server error to JS error code
1027     if (error <= E_COMMON_START && error >= E_COMMON_END) {
1028         error = JS_INNER_FAIL;
1029     } else if (error == E_PERMISSION_DENIED) {
1030         error = OHOS_PERMISSION_DENIED_CODE;
1031     } else if (trans2JsError.count(error)) {
1032         error = trans2JsError.at(error);
1033     }
1034     return error;
1035 }
1036 
HandleError(ani_env * env,int error,ani_object & errorObj,const std::string & Name)1037 void MediaLibraryAniUtils::HandleError(ani_env *env, int error, ani_object &errorObj, const std::string &Name)
1038 {
1039     if (error == ERR_DEFAULT) {
1040         return;
1041     }
1042 
1043     string errMsg = "System inner fail";
1044     int originalError = error;
1045     if (jsErrMap.count(error) > 0) {
1046         errMsg = jsErrMap.at(error);
1047     } else {
1048         error = JS_INNER_FAIL;
1049     }
1050     CreateAniErrorObject(env, errorObj, error, errMsg);
1051     errMsg = Name + " " + errMsg;
1052     ANI_ERR_LOG("Error: %{public}s, js errcode:%{public}d ", errMsg.c_str(), originalError);
1053 }
1054 
CreateAniErrorObject(ani_env * env,ani_object & errorObj,const int32_t errCode,const string & errMsg)1055 void MediaLibraryAniUtils::CreateAniErrorObject(ani_env *env, ani_object &errorObj, const int32_t errCode,
1056     const string &errMsg)
1057 {
1058     static const std::string className = "L@ohos/file/photoAccessHelper/MediaLibraryAniError;";
1059     ani_class cls {};
1060     ani_status status = env->FindClass(className.c_str(), &cls);
1061     if (status != ANI_OK) {
1062         ANI_ERR_LOG("Can't find class %{public}s", className.c_str());
1063         return;
1064     }
1065 
1066     ani_method ctor {};
1067     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "DLstd/core/String;:V", &ctor)) {
1068         ANI_ERR_LOG("Can't find <ctor> from class %{public}s", className.c_str());
1069         return;
1070     }
1071 
1072     ani_string error_msg {};
1073     if (ANI_OK != MediaLibraryAniUtils::ToAniString(env, errMsg, error_msg)) {
1074         ANI_ERR_LOG("Call ToAniString function failed.");
1075         return;
1076     }
1077 
1078     if (ANI_OK != env->Object_New(cls, ctor, &errorObj, (ani_double)errCode, error_msg)) {
1079         ANI_ERR_LOG("New MediaLibraryAniError object failed.");
1080         return;
1081     }
1082     return;
1083 }
1084 
GetStringValueByColumn(shared_ptr<DataShare::DataShareResultSet> resultSet,const std::string columnName)1085 string MediaLibraryAniUtils::GetStringValueByColumn(shared_ptr<DataShare::DataShareResultSet> resultSet,
1086     const std::string columnName)
1087 {
1088     int index;
1089     DataShare::DataType dataType;
1090     if (resultSet->GetColumnIndex(columnName, index) || resultSet->GetDataType(index, dataType)) {
1091         return EMPTY_STRING;
1092     }
1093     switch (dataType) {
1094         case DataShare::DataType::TYPE_INTEGER: {
1095             int64_t intValue = -1;
1096             if (resultSet->GetLong(index, intValue) == NativeRdb::E_OK) {
1097                 return to_string(intValue);
1098             }
1099             break;
1100         }
1101         case DataShare::DataType::TYPE_FLOAT: {
1102             double douValue = 0.0;
1103             if (resultSet->GetDouble(index, douValue) == NativeRdb::E_OK) {
1104                 return to_string(douValue);
1105             }
1106             break;
1107         }
1108         case DataShare::DataType::TYPE_STRING: {
1109             std::string strValue;
1110             if (resultSet->GetString(index, strValue) == NativeRdb::E_OK) {
1111                 return strValue;
1112             }
1113             break;
1114         }
1115         case DataShare::DataType::TYPE_BLOB: {
1116             std::vector<uint8_t> blobValue;
1117             if (resultSet->GetBlob(index, blobValue) == NativeRdb::E_OK) {
1118                 std::string tempValue(blobValue.begin(), blobValue.end());
1119                 return tempValue;
1120             }
1121             break;
1122         }
1123         default: {
1124             break;
1125         }
1126     }
1127     return EMPTY_STRING;
1128 }
1129 
ParseResultSet2JsonStr(shared_ptr<DataShare::DataShareResultSet> resultSet,const std::vector<std::string> & columns)1130 string MediaLibraryAniUtils::ParseResultSet2JsonStr(shared_ptr<DataShare::DataShareResultSet> resultSet,
1131     const std::vector<std::string> &columns)
1132 {
1133     json jsonArray = json::array();
1134     if (resultSet == nullptr) {
1135         return jsonArray.dump();
1136     }
1137     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1138         json jsonObject;
1139         for (uint32_t i = 0; i < columns.size(); i++) {
1140             string columnName = columns[i];
1141             jsonObject[columnName] = GetStringValueByColumn(resultSet, columnName);
1142         }
1143         jsonArray.push_back(jsonObject);
1144     }
1145     return jsonArray.dump();
1146 }
1147 
ParseAnalysisFace2JsonStr(shared_ptr<DataShare::DataShareResultSet> resultSet,const vector<string> & columns)1148 string MediaLibraryAniUtils::ParseAnalysisFace2JsonStr(shared_ptr<DataShare::DataShareResultSet> resultSet,
1149     const vector<string> &columns)
1150 {
1151     json jsonArray = json::array();
1152     if (resultSet == nullptr) {
1153         return jsonArray.dump();
1154     }
1155 
1156     Uri uri(PAH_QUERY_ANA_PHOTO_ALBUM);
1157     DataShare::DataSharePredicates predicates;
1158     predicates.EqualTo(ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::PORTRAIT))->And()->IsNotNull(TAG_ID);
1159     vector<string> albumColumns = { ALBUM_ID, TAG_ID };
1160     int errCode = 0;
1161     shared_ptr<DataShare::DataShareResultSet> albumSet = UserFileClient::Query(uri, predicates, albumColumns, errCode);
1162 
1163     unordered_map<string, string> tagIdToAlbumIdMap;
1164     if (albumSet != nullptr) {
1165         while (albumSet->GoToNextRow() == NativeRdb::E_OK) {
1166             tagIdToAlbumIdMap[GetStringValueByColumn(albumSet, TAG_ID)] = GetStringValueByColumn(albumSet, ALBUM_ID);
1167         }
1168     }
1169 
1170     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1171         json jsonObject;
1172         for (uint32_t i = 0; i < columns.size(); i++) {
1173             string columnName = columns[i];
1174             string columnValue = GetStringValueByColumn(resultSet, columnName);
1175             jsonObject[columnName] = columnValue;
1176             if (columnName == TAG_ID) {
1177                 jsonObject[ALBUM_URI] = PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX + tagIdToAlbumIdMap[columnValue];
1178             }
1179         }
1180         jsonArray.push_back(jsonObject);
1181     }
1182 
1183     return jsonArray.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
1184 }
1185 
UriAppendKeyValue(string & uri,const string & key,const string & value)1186 void MediaLibraryAniUtils::UriAppendKeyValue(string &uri, const string &key, const string &value)
1187 {
1188     string uriKey = key + '=';
1189     if (uri.find(uriKey) != string::npos) {
1190         return;
1191     }
1192 
1193     char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
1194     string append = queryMark + key + '=' + value;
1195 
1196     size_t posJ = uri.find('#');
1197     if (posJ == string::npos) {
1198         uri += append;
1199     } else {
1200         uri.insert(posJ, append);
1201     }
1202 }
1203 
AddDefaultAssetColumns(ani_env * env,vector<string> & fetchColumn,function<bool (const string & columnName)> isValidColumn,AniAssetType assetType,const PhotoAlbumSubType subType)1204 ani_status MediaLibraryAniUtils::AddDefaultAssetColumns(ani_env *env, vector<string> &fetchColumn,
1205     function<bool(const string &columnName)> isValidColumn, AniAssetType assetType,
1206     const PhotoAlbumSubType subType)
1207 {
1208     auto validFetchColumns = MediaColumn::DEFAULT_FETCH_COLUMNS;
1209     if (assetType == TYPE_PHOTO) {
1210         validFetchColumns.insert(
1211             PhotoColumn::DEFAULT_FETCH_COLUMNS.begin(), PhotoColumn::DEFAULT_FETCH_COLUMNS.end());
1212     }
1213     switch (subType) {
1214         case PhotoAlbumSubType::FAVORITE:
1215             validFetchColumns.insert(MediaColumn::MEDIA_IS_FAV);
1216             break;
1217         case PhotoAlbumSubType::VIDEO:
1218             validFetchColumns.insert(MediaColumn::MEDIA_TYPE);
1219             break;
1220         case PhotoAlbumSubType::HIDDEN:
1221             validFetchColumns.insert(MediaColumn::MEDIA_HIDDEN);
1222             break;
1223         case PhotoAlbumSubType::TRASH:
1224             validFetchColumns.insert(MediaColumn::MEDIA_DATE_TRASHED);
1225             break;
1226         case PhotoAlbumSubType::SCREENSHOT:
1227         case PhotoAlbumSubType::CAMERA:
1228             validFetchColumns.insert(PhotoColumn::PHOTO_SUBTYPE);
1229             break;
1230         default:
1231             break;
1232     }
1233     for (const auto &column : fetchColumn) {
1234         if (column == PENDING_STATUS) {
1235             validFetchColumns.insert(MediaColumn::MEDIA_TIME_PENDING);
1236         } else if (isValidColumn(column)) {
1237             validFetchColumns.insert(column);
1238         } else if (column == MEDIA_DATA_DB_URI) {
1239             continue;
1240         } else if (DATE_TRANSITION_MAP.count(column) != 0) {
1241             validFetchColumns.insert(DATE_TRANSITION_MAP.at(column));
1242         } else {
1243             AniError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
1244             return ANI_INVALID_ARGS;
1245         }
1246     }
1247     fetchColumn.assign(validFetchColumns.begin(), validFetchColumns.end());
1248     return ANI_OK;
1249 }
1250 
SetDefaultPredicatesCondition(DataSharePredicates & predicates,const int32_t dateTrashed,const bool isHidden,const int32_t timePending,const bool isTemp)1251 inline void SetDefaultPredicatesCondition(DataSharePredicates &predicates, const int32_t dateTrashed,
1252     const bool isHidden, const int32_t timePending, const bool isTemp)
1253 {
1254     predicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, to_string(dateTrashed));
1255     predicates.EqualTo(MediaColumn::MEDIA_HIDDEN, to_string(isHidden));
1256     predicates.EqualTo(MediaColumn::MEDIA_TIME_PENDING, to_string(timePending));
1257     predicates.EqualTo(PhotoColumn::PHOTO_IS_TEMP, to_string(isTemp));
1258     predicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL,
1259         to_string(static_cast<int32_t>(BurstCoverLevelType::COVER)));
1260 }
1261 
GetFavoritePredicates(DataSharePredicates & predicates,const bool hiddenOnly)1262 static int32_t GetFavoritePredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1263 {
1264     predicates.BeginWrap();
1265     constexpr int32_t IS_FAVORITE = 1;
1266     predicates.EqualTo(MediaColumn::MEDIA_IS_FAV, to_string(IS_FAVORITE));
1267     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1268     predicates.EndWrap();
1269     return E_SUCCESS;
1270 }
1271 
GetVideoPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1272 static int32_t GetVideoPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1273 {
1274     predicates.BeginWrap();
1275     predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_VIDEO));
1276     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1277     predicates.EndWrap();
1278     return E_SUCCESS;
1279 }
1280 
GetHiddenPredicates(DataSharePredicates & predicates)1281 static int32_t GetHiddenPredicates(DataSharePredicates &predicates)
1282 {
1283     predicates.BeginWrap();
1284     SetDefaultPredicatesCondition(predicates, 0, 1, 0, false);
1285     predicates.EndWrap();
1286     return E_SUCCESS;
1287 }
1288 
GetTrashPredicates(DataSharePredicates & predicates)1289 static int32_t GetTrashPredicates(DataSharePredicates &predicates)
1290 {
1291     predicates.BeginWrap();
1292     predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
1293     predicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL,
1294         to_string(static_cast<int32_t>(BurstCoverLevelType::COVER)));
1295     predicates.EndWrap();
1296     return E_SUCCESS;
1297 }
1298 
GetScreenshotPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1299 static int32_t GetScreenshotPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1300 {
1301     predicates.BeginWrap();
1302     predicates.EqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::SCREENSHOT)));
1303     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1304     predicates.EndWrap();
1305     return E_SUCCESS;
1306 }
1307 
GetCameraPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1308 static int32_t GetCameraPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1309 {
1310     predicates.BeginWrap();
1311     predicates.EqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::CAMERA)));
1312     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1313     predicates.EndWrap();
1314     return E_SUCCESS;
1315 }
1316 
GetAllImagesPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1317 static int32_t GetAllImagesPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1318 {
1319     predicates.BeginWrap();
1320     predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_IMAGE));
1321     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1322     predicates.EndWrap();
1323     return E_SUCCESS;
1324 }
1325 
GetCloudEnhancementPredicates(DataSharePredicates & predicates,const bool hiddenOnly)1326 static int32_t GetCloudEnhancementPredicates(DataSharePredicates &predicates, const bool hiddenOnly)
1327 {
1328     predicates.BeginWrap();
1329     predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_IMAGE));
1330     predicates.EqualTo(PhotoColumn::PHOTO_STRONG_ASSOCIATION,
1331         to_string(static_cast<int32_t>(StrongAssociationType::CLOUD_ENHANCEMENT)));
1332     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1333     predicates.EndWrap();
1334     return E_SUCCESS;
1335 }
1336 
GetSystemAlbumPredicates(const PhotoAlbumSubType subType,DataSharePredicates & predicates,const bool hiddenOnly)1337 int32_t MediaLibraryAniUtils::GetSystemAlbumPredicates(const PhotoAlbumSubType subType,
1338     DataSharePredicates &predicates, const bool hiddenOnly)
1339 {
1340     switch (subType) {
1341         case PhotoAlbumSubType::FAVORITE: {
1342             return GetFavoritePredicates(predicates, hiddenOnly);
1343         }
1344         case PhotoAlbumSubType::VIDEO: {
1345             return GetVideoPredicates(predicates, hiddenOnly);
1346         }
1347         case PhotoAlbumSubType::HIDDEN: {
1348             return GetHiddenPredicates(predicates);
1349         }
1350         case PhotoAlbumSubType::TRASH: {
1351             return GetTrashPredicates(predicates);
1352         }
1353         case PhotoAlbumSubType::SCREENSHOT: {
1354             return GetScreenshotPredicates(predicates, hiddenOnly);
1355         }
1356         case PhotoAlbumSubType::CAMERA: {
1357             return GetCameraPredicates(predicates, hiddenOnly);
1358         }
1359         case PhotoAlbumSubType::IMAGE: {
1360             return GetAllImagesPredicates(predicates, hiddenOnly);
1361         }
1362         case PhotoAlbumSubType::CLOUD_ENHANCEMENT: {
1363             return GetCloudEnhancementPredicates(predicates, hiddenOnly);
1364         }
1365         default: {
1366             ANI_ERR_LOG("Unsupported photo album subtype: %{public}d", subType);
1367             return E_INVALID_ARGUMENTS;
1368         }
1369     }
1370 }
1371 
GetUserAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates,const bool hiddenOnly)1372 int32_t MediaLibraryAniUtils::GetUserAlbumPredicates(
1373     const int32_t albumId, DataSharePredicates &predicates, const bool hiddenOnly)
1374 {
1375     predicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
1376     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1377     return E_SUCCESS;
1378 }
1379 
GetAnalysisPhotoMapPredicates(const int32_t albumId,DataSharePredicates & predicates)1380 int32_t MediaLibraryAniUtils::GetAnalysisPhotoMapPredicates(const int32_t albumId, DataSharePredicates &predicates)
1381 {
1382     string onClause = MediaColumn::MEDIA_ID + " = " + PhotoMap::ASSET_ID;
1383     predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ onClause });
1384     predicates.EqualTo(PhotoMap::ALBUM_ID, to_string(albumId));
1385     SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
1386     return E_SUCCESS;
1387 }
1388 
GetFeaturedSinglePortraitAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates)1389 int32_t MediaLibraryAniUtils::GetFeaturedSinglePortraitAlbumPredicates(
1390     const int32_t albumId, DataSharePredicates &predicates)
1391 {
1392     string onClause = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " +
1393         ANALYSIS_PHOTO_MAP_TABLE + "." + PhotoMap::ASSET_ID;
1394     predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ onClause });
1395 
1396     constexpr int32_t minSize = 224;
1397     string imgHeightColumn = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_HEIGHT;
1398     string imgWidthColumn = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_WIDTH;
1399     string imgFaceHeightColumn = VISION_IMAGE_FACE_TABLE + "." + SCALE_HEIGHT;
1400     string imgFaceWidthColumn = VISION_IMAGE_FACE_TABLE + "." + SCALE_WIDTH;
1401     string imgFaceHeightClause = "( " + imgFaceHeightColumn + " > " + to_string(minSize) +
1402         " OR ( " + imgFaceHeightColumn + " <= 1.0 " + " AND " + imgFaceHeightColumn + " * " + imgHeightColumn +
1403         " > " + to_string(minSize) + " ) )";
1404     string imgFaceWidthClause = "( " + imgFaceWidthColumn + " > " + to_string(minSize) +
1405         " OR ( " + imgFaceWidthColumn + " <= 1.0 " + " AND " + imgFaceWidthColumn + " * " + imgWidthColumn +
1406         " > " + to_string(minSize) + " ) )";
1407     string imgFaceOcclusionClause = "( " + VISION_IMAGE_FACE_TABLE + "." + FACE_OCCLUSION + " = 0 OR " +
1408         VISION_IMAGE_FACE_TABLE + "." + FACE_OCCLUSION + " IS NULL )";
1409     string portraitRotationLimit = "BETWEEN -30 AND 30";
1410     onClause = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " + VISION_IMAGE_FACE_TABLE + "." +
1411         MediaColumn::MEDIA_ID + " AND " + VISION_IMAGE_FACE_TABLE + "." + TOTAL_FACES + " = 1 AND " +
1412         imgFaceHeightClause + " AND " + imgFaceWidthClause + " AND " + imgFaceOcclusionClause + " AND " +
1413         VISION_IMAGE_FACE_TABLE + "." + PITCH + " " + portraitRotationLimit + " AND " +
1414         VISION_IMAGE_FACE_TABLE + "." + YAW + " " + portraitRotationLimit + " AND " +
1415         VISION_IMAGE_FACE_TABLE + "." + ROLL + " " + portraitRotationLimit;
1416     predicates.InnerJoin(VISION_IMAGE_FACE_TABLE)->On({ onClause });
1417 
1418     string portraitType = "IN ( 1, 2 )";
1419     onClause = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " + VISION_POSE_TABLE + "." +
1420         MediaColumn::MEDIA_ID + " AND " + VISION_POSE_TABLE + "." + POSE_TYPE + " " + portraitType;
1421     predicates.InnerJoin(VISION_POSE_TABLE)->On({ onClause });
1422 
1423     predicates.EqualTo(PhotoMap::ALBUM_ID, to_string(albumId));
1424     SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
1425     return E_SUCCESS;
1426 }
1427 
GetPortraitAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates)1428 int32_t MediaLibraryAniUtils::GetPortraitAlbumPredicates(const int32_t albumId, DataSharePredicates &predicates)
1429 {
1430     string onClause = MediaColumn::MEDIA_ID + " = " + PhotoMap::ASSET_ID;
1431     vector<string> clauses = { onClause };
1432     predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On(clauses);
1433     onClause = ALBUM_ID + " = " + PhotoMap::ALBUM_ID;
1434     clauses = { onClause };
1435     predicates.InnerJoin(ANALYSIS_ALBUM_TABLE)->On(clauses);
1436     string tempTable = "(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " +
1437         to_string(albumId) + ") ag";
1438     onClause = "ag." + GROUP_TAG + " = " + ANALYSIS_ALBUM_TABLE + "." + GROUP_TAG;
1439     clauses = { onClause };
1440     predicates.InnerJoin(tempTable)->On(clauses);
1441     SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
1442     predicates.Distinct();
1443     return E_SUCCESS;
1444 }
1445 
GetAllLocationPredicates(DataSharePredicates & predicates)1446 int32_t MediaLibraryAniUtils::GetAllLocationPredicates(DataSharePredicates &predicates)
1447 {
1448     SetDefaultPredicatesCondition(predicates, 0, 0, 0, false);
1449     predicates.And()->NotEqualTo(PhotoColumn::PHOTO_LATITUDE, to_string(0));
1450     predicates.And()->NotEqualTo(PhotoColumn::PHOTO_LONGITUDE, to_string(0));
1451     return E_SUCCESS;
1452 }
1453 
GetSourceAlbumPredicates(const int32_t albumId,DataSharePredicates & predicates,const bool hiddenOnly)1454 int32_t MediaLibraryAniUtils::GetSourceAlbumPredicates(const int32_t albumId, DataSharePredicates &predicates,
1455     const bool hiddenOnly)
1456 {
1457     predicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
1458     predicates.EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)));
1459     SetDefaultPredicatesCondition(predicates, 0, hiddenOnly, 0, false);
1460     return E_SUCCESS;
1461 }
1462 
IsFeaturedSinglePortraitAlbum(std::string albumName,DataShare::DataSharePredicates & predicates)1463 bool MediaLibraryAniUtils::IsFeaturedSinglePortraitAlbum(
1464     std::string albumName, DataShare::DataSharePredicates &predicates)
1465 {
1466     bool isFeaturedSinglePortrait = false;
1467     int portraitAlbumId = 0;
1468     if (albumName.compare(to_string(portraitAlbumId)) != 0) {
1469         return isFeaturedSinglePortrait;
1470     }
1471 
1472     DataSharePredicates featuredSinglePortraitPredicates;
1473     std::vector<OperationItem> operationList = predicates.GetOperationList();
1474     for (auto& operationItem : operationList) {
1475         switch (operationItem.operation) {
1476             case OHOS::DataShare::OperationType::LIKE : {
1477                 std::string field = std::get<string>(operationItem.singleParams[0]);
1478                 std::string value = std::get<string>(operationItem.singleParams[1]);
1479                 if (field.compare("FeaturedSinglePortrait") == 0 && value.compare("true") == 0) {
1480                     isFeaturedSinglePortrait = true;
1481                 } else {
1482                     featuredSinglePortraitPredicates.Like(field, value);
1483                 }
1484                 break;
1485             }
1486             case OHOS::DataShare::OperationType::ORDER_BY_DESC : {
1487                 featuredSinglePortraitPredicates.OrderByDesc(operationItem.GetSingle(0));
1488                 break;
1489             }
1490             case OHOS::DataShare::OperationType::LIMIT : {
1491                 featuredSinglePortraitPredicates.Limit(operationItem.GetSingle(0), operationItem.GetSingle(1));
1492                 break;
1493             }
1494             default: {
1495                 break;
1496             }
1497         }
1498     }
1499 
1500     if (isFeaturedSinglePortrait) {
1501         predicates = featuredSinglePortraitPredicates;
1502     }
1503     return isFeaturedSinglePortrait;
1504 }
1505 
FindClass(ani_env * env,const std::string & className,ani_class * cls)1506 ani_status MediaLibraryAniUtils::FindClass(ani_env *env, const std::string &className, ani_class *cls)
1507 {
1508     CHECK_STATUS_RET(env->FindClass(className.c_str(), cls), "Can't find class");
1509     return ANI_OK;
1510 }
1511 
FindClassMethod(ani_env * env,const std::string & className,const std::string & methodName,ani_method * method)1512 ani_status MediaLibraryAniUtils::FindClassMethod(ani_env *env, const std::string &className,
1513     const std::string &methodName, ani_method *method)
1514 {
1515     ani_class cls {};
1516     CHECK_STATUS_RET(MediaLibraryAniUtils::FindClass(env, className, &cls), "Can't find class");
1517     CHECK_STATUS_RET(env->Class_FindMethod(cls, methodName.c_str(), nullptr, method), "Can't find method");
1518 
1519     return ANI_OK;
1520 }
1521 
1522 template ani_status MediaLibraryAniUtils::GetFetchOption<unique_ptr<MediaLibraryAsyncContext>>(ani_env *env,
1523     ani_object fetchOptions, FetchOptionType fetchOptType, unique_ptr<MediaLibraryAsyncContext> &context);
1524 
1525 template ani_status MediaLibraryAniUtils::GetFetchOption<unique_ptr<PhotoAlbumAniContext>>(ani_env *env,
1526     ani_object fetchOptions, FetchOptionType fetchOptType, unique_ptr<PhotoAlbumAniContext> &context);
1527 
1528 template ani_status MediaLibraryAniUtils::GetPredicate<unique_ptr<PhotoAlbumAniContext>>(ani_env *env,
1529     const ani_object fetchOptions, const std::string &propName, unique_ptr<PhotoAlbumAniContext> &context,
1530     FetchOptionType fetchOptType);
1531 
1532 template ani_status MediaLibraryAniUtils::ParsePredicates<unique_ptr<MediaLibraryAsyncContext>>(ani_env *env,
1533     const ani_object predicate, unique_ptr<MediaLibraryAsyncContext> &context, FetchOptionType fetchOptType);
1534 
1535 template bool MediaLibraryAniUtils::HandleSpecialPredicate<unique_ptr<PhotoAlbumAniContext>>(
1536     unique_ptr<PhotoAlbumAniContext> &context, DataSharePredicates *predicate, FetchOptionType fetchOptType);
1537 
1538 template bool MediaLibraryAniUtils::ProcessPredicateItems<unique_ptr<PhotoAlbumAniContext>>(
1539     unique_ptr<PhotoAlbumAniContext> &context, const vector<OperationItem>& items, vector<OperationItem>& operations,
1540     FetchOptionType fetchOptType);
1541 
1542 template bool MediaLibraryAniUtils::HandleSpecialField<unique_ptr<PhotoAlbumAniContext>>(
1543     unique_ptr<PhotoAlbumAniContext> &context, const OperationItem& item, vector<OperationItem>& operations,
1544     FetchOptionType fetchOptType);
1545 
1546 template bool MediaLibraryAniUtils::HandleNetworkIdField<unique_ptr<PhotoAlbumAniContext>>(
1547     unique_ptr<PhotoAlbumAniContext> &context, const OperationItem& item, const string& value);
1548 
1549 template bool MediaLibraryAniUtils::HandleUriField<unique_ptr<PhotoAlbumAniContext>>(
1550     unique_ptr<PhotoAlbumAniContext> &context, const OperationItem& item, const string& uriValue,
1551     vector<OperationItem>& operations, FetchOptionType fetchOptType);
1552 
1553 template bool MediaLibraryAniUtils::GetLocationPredicate<unique_ptr<PhotoAlbumAniContext>>(
1554     unique_ptr<PhotoAlbumAniContext> &context, DataSharePredicates *predicate);
1555 } // namespace Media
1556 } // namespace OHOS