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