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
16 #include "fetch_result_ani.h"
17
18 #include <iostream>
19
20 #include "ani_class_name.h"
21 #include "medialibrary_ani_log.h"
22 #include "medialibrary_ani_utils.h"
23 #include "medialibrary_tracer.h"
24
25 namespace OHOS::Media {
FetchFileResultInit(ani_env * env)26 ani_status FetchFileResultAni::FetchFileResultInit(ani_env *env)
27 {
28 static const char *className = ANI_CLASS_FETCH_RESULT.c_str();
29 ani_class cls;
30 auto status = env->FindClass(className, &cls);
31 if (status != ANI_OK) {
32 ANI_ERR_LOG("Failed to find class: %{public}s", className);
33 return status;
34 }
35
36 std::array methods = {
37 ani_native_function {"getAllObjectsSync", nullptr, reinterpret_cast<void *>(GetAllObjects)},
38 ani_native_function {"getFirstObjectSync", nullptr, reinterpret_cast<void *>(GetFirstObject)},
39 ani_native_function {"getNextObjectSync", nullptr, reinterpret_cast<void *>(GetNextObject)},
40 ani_native_function {"getCount", nullptr, reinterpret_cast<void *>(GetCount)},
41 ani_native_function {"close", nullptr, reinterpret_cast<void *>(Close)},
42 };
43 status = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
44 if (status != ANI_OK) {
45 ANI_ERR_LOG("Failed to bind native methods to: %{public}s", className);
46 return status;
47 };
48
49 ANI_INFO_LOG("FetchFileResultInit ok");
50 return ANI_OK;
51 }
52
CheckIfPropertyPtrNull()53 bool FetchFileResultAni::CheckIfPropertyPtrNull()
54 {
55 return propertyPtr == nullptr;
56 }
57
GetFetchResType()58 FetchResType FetchFileResultAni::GetFetchResType()
59 {
60 return propertyPtr->fetchResType_;
61 }
62
GetFetchFileResultObject()63 std::shared_ptr<FetchResult<FileAsset>> FetchFileResultAni::GetFetchFileResultObject()
64 {
65 return propertyPtr->fetchFileResult_;
66 }
67
GetFetchAlbumResultObject()68 std::shared_ptr<FetchResult<AlbumAsset>> FetchFileResultAni::GetFetchAlbumResultObject()
69 {
70 return propertyPtr->fetchAlbumResult_;
71 }
72
GetFetchPhotoAlbumResultObject()73 std::shared_ptr<FetchResult<PhotoAlbum>> FetchFileResultAni::GetFetchPhotoAlbumResultObject()
74 {
75 return propertyPtr->fetchPhotoAlbumResult_;
76 }
77
GetFetchSmartAlbumResultObject()78 std::shared_ptr<FetchResult<SmartAlbumAsset>> FetchFileResultAni::GetFetchSmartAlbumResultObject()
79 {
80 return propertyPtr->fetchSmartAlbumResult_;
81 }
82
GetFetchResult(unique_ptr<FetchFileResultAni> & obj)83 void FetchFileResultAni::GetFetchResult(unique_ptr<FetchFileResultAni> &obj)
84 {
85 ANI_INFO_LOG("GetFetchResult type: %{public}d", sFetchResType_);
86 switch (sFetchResType_) {
87 case FetchResType::TYPE_FILE: {
88 auto fileResult = make_shared<FetchResult<FileAsset>>(move(sFetchFileResult_->GetDataShareResultSet()));
89 obj->propertyPtr->fetchFileResult_ = fileResult;
90 obj->propertyPtr->fetchFileResult_->SetInfo(sFetchFileResult_);
91 break;
92 }
93 case FetchResType::TYPE_ALBUM: {
94 auto albumResult = make_shared<FetchResult<AlbumAsset>>(move(sFetchAlbumResult_->GetDataShareResultSet()));
95 obj->propertyPtr->fetchAlbumResult_ = albumResult;
96 obj->propertyPtr->fetchAlbumResult_->SetInfo(sFetchAlbumResult_);
97 break;
98 }
99 case FetchResType::TYPE_PHOTOALBUM: {
100 auto photoAlbumResult =
101 make_shared<FetchResult<PhotoAlbum>>(move(sFetchPhotoAlbumResult_->GetDataShareResultSet()));
102 obj->propertyPtr->fetchPhotoAlbumResult_ = photoAlbumResult;
103 obj->propertyPtr->fetchPhotoAlbumResult_->SetInfo(sFetchPhotoAlbumResult_);
104 break;
105 }
106 case FetchResType::TYPE_SMARTALBUM: {
107 auto smartResult =
108 make_shared<FetchResult<SmartAlbumAsset>>(move(sFetchSmartAlbumResult_->GetDataShareResultSet()));
109 obj->propertyPtr->fetchSmartAlbumResult_ = smartResult;
110 obj->propertyPtr->fetchSmartAlbumResult_->SetInfo(sFetchSmartAlbumResult_);
111 break;
112 }
113 default:
114 ANI_ERR_LOG("unsupported FetchResType");
115 break;
116 }
117 }
118
FetchFileResultAniConstructor(ani_env * env,ani_class clazz)119 ani_object FetchFileResultAni::FetchFileResultAniConstructor(ani_env *env, [[maybe_unused]] ani_class clazz)
120 {
121 unique_ptr<FetchFileResultAni> obj = make_unique<FetchFileResultAni>();
122 obj->propertyPtr = make_shared<FetchResultProperty>();
123 GetFetchResult(obj);
124 obj->propertyPtr->fetchResType_ = sFetchResType_;
125
126 ani_class cls;
127 if (ANI_OK != env->FindClass(ANI_CLASS_FETCH_RESULT.c_str(), &cls)) {
128 ANI_ERR_LOG("Failed to find class: %{public}s", ANI_CLASS_FETCH_RESULT.c_str());
129 ani_object nullobj = nullptr;
130 return nullobj;
131 }
132
133 ani_method ctor;
134 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
135 ANI_ERR_LOG("Failed to find method: %{public}s", "ctor");
136 ani_object nullobj = nullptr;
137 return nullobj;
138 }
139
140 ani_object fetchResult;
141 if (ANI_OK !=env->Object_New(cls, ctor, &fetchResult, reinterpret_cast<ani_long>(obj.release()))) {
142 ANI_ERR_LOG("New fetchResult Fail");
143 }
144 return fetchResult;
145 }
146
Unwrap(ani_env * env,ani_object fetchFileResultHandle)147 FetchFileResultAni* FetchFileResultAni::Unwrap(ani_env *env, ani_object fetchFileResultHandle)
148 {
149 ani_long fetchFileResultHandleLong;
150 auto status = env->Object_GetFieldByName_Long(fetchFileResultHandle,
151 "nativeValue", &fetchFileResultHandleLong);
152 if (ANI_OK != status || fetchFileResultHandleLong == 0) {
153 ANI_ERR_LOG("GetAllPhotoAssetHandleObjects nullptr");
154 return nullptr;
155 }
156 return reinterpret_cast<FetchFileResultAni *>(fetchFileResultHandleLong);
157 }
158
GetAllObjectFromFetchResult(std::unique_ptr<FetchFileResultAniContext> & aniContest)159 static void GetAllObjectFromFetchResult(std::unique_ptr<FetchFileResultAniContext>& aniContest)
160 {
161 MediaLibraryTracer tracer;
162 tracer.Start("GetAllObjectsExcute");
163
164 auto propertyPtr = aniContest->objectInfo->GetPropertyPtrInstance();
165 if (propertyPtr == nullptr) {
166 ANI_ERR_LOG("propertyPtr is nullptr");
167 return;
168 }
169
170 ANI_DEBUG_LOG("GetAllObject type: %{public}d", propertyPtr->fetchResType_);
171 switch (propertyPtr->fetchResType_) {
172 case FetchResType::TYPE_FILE: {
173 auto fetchResult = propertyPtr->fetchFileResult_;
174 auto file = fetchResult->GetFirstObject();
175 while (file != nullptr) {
176 aniContest->fileAssetArray.emplace_back(move(file));
177 file = fetchResult->GetNextObject();
178 }
179 break;
180 }
181 case FetchResType::TYPE_ALBUM: {
182 auto fetchResult = propertyPtr->fetchAlbumResult_;
183 auto album = fetchResult->GetFirstObject();
184 while (album != nullptr) {
185 aniContest->fileAlbumArray.emplace_back(move(album));
186 album = fetchResult->GetNextObject();
187 }
188 break;
189 }
190 case FetchResType::TYPE_PHOTOALBUM: {
191 auto fetchResult = propertyPtr->fetchPhotoAlbumResult_;
192 auto photoAlbum = fetchResult->GetFirstObject();
193 while (photoAlbum != nullptr) {
194 aniContest->filePhotoAlbumArray.emplace_back(move(photoAlbum));
195 photoAlbum = fetchResult->GetNextObject();
196 }
197 break;
198 }
199 case FetchResType::TYPE_SMARTALBUM: {
200 auto fetchResult = propertyPtr->fetchSmartAlbumResult_;
201 auto smartAlbum = fetchResult->GetFirstObject();
202 while (smartAlbum != nullptr) {
203 aniContest->fileSmartAlbumArray.emplace_back(move(smartAlbum));
204 smartAlbum = fetchResult->GetNextObject();
205 }
206 break;
207 }
208 default:
209 break;
210 }
211 }
212
CheckIfFFRAniNotEmpty(FetchFileResultAni * obj)213 static bool CheckIfFFRAniNotEmpty(FetchFileResultAni* obj)
214 {
215 if (obj == nullptr) {
216 ANI_ERR_LOG("FetchFileResultNapi is nullptr");
217 return false;
218 }
219 if (obj->CheckIfPropertyPtrNull()) {
220 ANI_ERR_LOG("PropertyPtr in FetchFileResultNapi is nullptr");
221 return false;
222 }
223 return true;
224 }
225
GetAllObjectComplete(ani_env * env,std::unique_ptr<FetchFileResultAniContext> & context)226 static ani_object GetAllObjectComplete(ani_env *env, std::unique_ptr<FetchFileResultAniContext> &context)
227 {
228 MediaLibraryTracer tracer;
229 tracer.Start("GetAllObjectsComplete");
230
231 ani_object result = nullptr;
232 ani_status status;
233 FetchResType fetchResType = context->objectPtr->fetchResType_;
234 ANI_DEBUG_LOG("fetchResType: %{public}d", fetchResType);
235 switch (fetchResType) {
236 case FetchResType::TYPE_FILE:
237 status = MediaLibraryAniUtils::ToFileAssetAniArray(env, context->fileAssetArray, result);
238 break;
239 case FetchResType::TYPE_PHOTOALBUM:
240 status = MediaLibraryAniUtils::ToPhotoAlbumAniArray(env, context->filePhotoAlbumArray, result);
241 break;
242 default:
243 ANI_ERR_LOG("unsupported FetchResType");
244 }
245 return result;
246 }
247
GetAllObjects(ani_env * env,ani_object fetchFileResultHandle)248 ani_object FetchFileResultAni::GetAllObjects(ani_env *env, [[maybe_unused]] ani_object fetchFileResultHandle)
249 {
250 MediaLibraryTracer tracer;
251 tracer.Start("GetAllObjects");
252
253 ani_object nullobj = nullptr;
254 auto aniContext = make_unique<FetchFileResultAniContext>();
255 aniContext->objectInfo = Unwrap(env, fetchFileResultHandle);
256 if (CheckIfFFRAniNotEmpty(aniContext->objectInfo)) {
257 aniContext->objectPtr = aniContext->objectInfo->propertyPtr;
258 CHECK_COND_RET(aniContext->objectPtr, nullobj, "propertyPtr is nullptr");
259 GetAllObjectFromFetchResult(aniContext);
260 return GetAllObjectComplete(env, aniContext);
261 } else {
262 AniError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "GetAllObject obj == nullptr");
263 }
264 return nullobj;
265 }
266
267
Close(ani_env * env,ani_object fetchFileResultHandle)268 ani_status FetchFileResultAni::Close(ani_env *env, [[maybe_unused]] ani_object fetchFileResultHandle)
269 {
270 ANI_INFO_LOG("fetch result close");
271 FetchFileResultAni* fetchFileResultAni = Unwrap(env, fetchFileResultHandle);
272 if (fetchFileResultAni) {
273 delete fetchFileResultAni;
274 if (ANI_OK != env->Object_SetFieldByName_Long(fetchFileResultHandle, "nativeValue", 0)) {
275 ANI_WARN_LOG("Set nativeValue failed");
276 }
277 }
278 return ANI_OK;
279 }
280
CreateFetchFileResult(ani_env * env,std::unique_ptr<FetchResult<FileAsset>> fileResult)281 ani_object FetchFileResultAni::CreateFetchFileResult(ani_env *env, std::unique_ptr<FetchResult<FileAsset>> fileResult)
282 {
283 if (fileResult == nullptr) {
284 ANI_ERR_LOG("fetchResult FileAsset is nullptr");
285 return nullptr;
286 }
287
288 sFetchResType_ = fileResult->GetFetchResType();
289 sFetchFileResult_ = move(fileResult);
290 ani_object result = nullptr;
291 ANI_INFO_LOG("get FileAsset result type: %{public}d", sFetchFileResult_->GetResultNapiType());
292 switch (sFetchFileResult_->GetResultNapiType()) {
293 case ResultNapiType::TYPE_USERFILE_MGR: {
294 result = FetchFileResultAniConstructor(env, nullptr);
295 break;
296 }
297 case ResultNapiType::TYPE_PHOTOACCESS_HELPER: {
298 result = FetchFileResultAniConstructor(env, nullptr);
299 break;
300 }
301 default:
302 result = FetchFileResultAniConstructor(env, nullptr);
303 break;
304 }
305 sFetchFileResult_ = nullptr;
306 return result;
307 }
308
CreateFetchFileResult(ani_env * env,std::unique_ptr<FetchResult<PhotoAlbum>> fileResult)309 ani_object FetchFileResultAni::CreateFetchFileResult(ani_env *env, std::unique_ptr<FetchResult<PhotoAlbum>> fileResult)
310 {
311 if (fileResult == nullptr) {
312 ANI_ERR_LOG("fetchResult PhotoAlbum is nullptr");
313 return nullptr;
314 }
315
316 sFetchResType_ = fileResult->GetFetchResType();
317 sFetchPhotoAlbumResult_ = move(fileResult);
318 ani_object result = nullptr;
319 ANI_INFO_LOG("get PhotoAlbum result type: %{public}d", sFetchPhotoAlbumResult_->GetResultNapiType());
320 switch (sFetchPhotoAlbumResult_->GetResultNapiType()) {
321 case ResultNapiType::TYPE_USERFILE_MGR: {
322 result = FetchFileResultAniConstructor(env, nullptr);
323 break;
324 }
325 case ResultNapiType::TYPE_PHOTOACCESS_HELPER: {
326 result = FetchFileResultAniConstructor(env, nullptr);
327 break;
328 }
329 default:
330 result = FetchFileResultAniConstructor(env, nullptr);
331 break;
332 }
333 sFetchPhotoAlbumResult_ = nullptr;
334 return result;
335 }
336
GetFirstAsset(std::unique_ptr<FetchFileResultAniContext> & aniContest)337 static void GetFirstAsset(std::unique_ptr<FetchFileResultAniContext>& aniContest)
338 {
339 auto propertyPtr = aniContest->objectInfo->GetPropertyPtrInstance();
340 if (propertyPtr == nullptr) {
341 ANI_ERR_LOG("propertyPtr is nullptr");
342 return;
343 }
344
345 ANI_INFO_LOG("getFirstAsset type: %{public}d", propertyPtr->fetchResType_);
346 switch (propertyPtr->fetchResType_) {
347 case FetchResType::TYPE_FILE: {
348 aniContest->fileAsset = propertyPtr->fetchFileResult_->GetFirstObject();
349 break;
350 }
351 case FetchResType::TYPE_ALBUM: {
352 aniContest->albumAsset = propertyPtr->fetchAlbumResult_->GetFirstObject();
353 break;
354 }
355 case FetchResType::TYPE_PHOTOALBUM: {
356 aniContest->photoAlbum = propertyPtr->fetchPhotoAlbumResult_->GetFirstObject();
357 break;
358 }
359 case FetchResType::TYPE_SMARTALBUM: {
360 aniContest->smartAlbumAsset = propertyPtr->fetchSmartAlbumResult_->GetFirstObject();
361 break;
362 }
363 default:
364 ANI_ERR_LOG("unsupported FetchResType");
365 break;
366 }
367 }
368
GetPositionObjectComplete(ani_env * env,std::unique_ptr<FetchFileResultAniContext> & aniContest)369 static ani_object GetPositionObjectComplete(ani_env *env, std::unique_ptr<FetchFileResultAniContext>& aniContest)
370 {
371 if (aniContest->objectPtr == nullptr) {
372 ANI_ERR_LOG("aniContest->objectPtr is nullptr");
373 return nullptr;
374 }
375
376 ANI_INFO_LOG("fetch result type: %{public}d", aniContest->objectPtr->fetchResType_);
377 ani_object etsAsset = nullptr;
378 switch (aniContest->objectPtr->fetchResType_) {
379 case FetchResType::TYPE_FILE: {
380 auto fileAssetAni = FileAssetAni::CreateFileAsset(env, aniContest->fileAsset);
381 etsAsset = FileAssetAni::Wrap(env, fileAssetAni);
382 break;
383 }
384 case FetchResType::TYPE_PHOTOALBUM: {
385 etsAsset = PhotoAlbumAni::CreatePhotoAlbumAni(env, aniContest->photoAlbum);
386 break;
387 }
388 default:
389 ANI_ERR_LOG("unsupported FetchResType");
390 break;
391 }
392
393 if (etsAsset == nullptr) {
394 ANI_ERR_LOG("Failed to get file asset napi object");
395 }
396 return etsAsset;
397 }
398
GetFirstObject(ani_env * env,ani_object fetchFileResultHandle)399 ani_object FetchFileResultAni::GetFirstObject(ani_env *env, [[maybe_unused]] ani_object fetchFileResultHandle)
400 {
401 ani_object nullobj = nullptr;
402 auto aniContext = make_unique<FetchFileResultAniContext>();
403 aniContext->objectInfo = Unwrap(env, fetchFileResultHandle);
404 if (CheckIfFFRAniNotEmpty(aniContext->objectInfo)) {
405 aniContext->objectPtr = aniContext->objectInfo->propertyPtr;
406 CHECK_COND_RET(aniContext->objectPtr, nullobj, "propertyPtr is nullptr");
407 GetFirstAsset(aniContext);
408 return GetPositionObjectComplete(env, aniContext);
409 } else {
410 AniError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "GetFirstObject obj == nullptr");
411 }
412 return nullptr;
413 }
414
GetNextAsset(std::unique_ptr<FetchFileResultAniContext> & aniContest)415 static void GetNextAsset(std::unique_ptr<FetchFileResultAniContext>& aniContest)
416 {
417 std::shared_ptr<FetchResultProperty> propertyPtr = aniContest->objectInfo->GetPropertyPtrInstance();
418 if (propertyPtr == nullptr) {
419 ANI_ERR_LOG("propertyPtr is nullptr");
420 return;
421 }
422
423 ANI_INFO_LOG("fetch result type: %{public}d", propertyPtr->fetchResType_);
424 switch (propertyPtr->fetchResType_) {
425 case FetchResType::TYPE_FILE: {
426 aniContest->fileAsset = propertyPtr->fetchFileResult_->GetNextObject();
427 break;
428 }
429 case FetchResType::TYPE_ALBUM: {
430 aniContest->albumAsset = propertyPtr->fetchAlbumResult_->GetNextObject();
431 break;
432 }
433 case FetchResType::TYPE_PHOTOALBUM: {
434 aniContest->photoAlbum = propertyPtr->fetchPhotoAlbumResult_->GetNextObject();
435 break;
436 }
437 case FetchResType::TYPE_SMARTALBUM: {
438 aniContest->smartAlbumAsset = propertyPtr->fetchSmartAlbumResult_->GetNextObject();
439 break;
440 }
441 default:
442 ANI_ERR_LOG("unsupported FetchResType");
443 break;
444 }
445 }
446
GetNextObject(ani_env * env,ani_object fetchFileResultHandle)447 ani_object FetchFileResultAni::GetNextObject(ani_env *env, [[maybe_unused]] ani_object fetchFileResultHandle)
448 {
449 ani_object nullobj = nullptr;
450 auto aniContext = make_unique<FetchFileResultAniContext>();
451 aniContext->objectInfo = Unwrap(env, fetchFileResultHandle);
452 if (CheckIfFFRAniNotEmpty(aniContext->objectInfo)) {
453 aniContext->objectPtr = aniContext->objectInfo->propertyPtr;
454 CHECK_COND_RET(aniContext->objectPtr, nullobj, "propertyPtr is nullptr");
455 GetNextAsset(aniContext);
456 return GetPositionObjectComplete(env, aniContext);
457 } else {
458 AniError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "GetNextObject obj == nullptr");
459 }
460 return nullptr;
461 }
462
GetCount(ani_env * env,ani_object fetchFileResultHandle)463 ani_double FetchFileResultAni::GetCount([[maybe_unused]] ani_env *env,
464 [[maybe_unused]] ani_object fetchFileResultHandle) // number Double
465 {
466 ani_double count = 0.0;
467 auto aniContext = make_unique<FetchFileResultAniContext>();
468 aniContext->objectInfo = Unwrap(env, fetchFileResultHandle);
469 if (CheckIfFFRAniNotEmpty(aniContext->objectInfo)) {
470 ANI_INFO_LOG("fetch result type: %{public}d", aniContext->objectInfo->GetFetchResType());
471 switch (aniContext->objectInfo->GetFetchResType()) {
472 case FetchResType::TYPE_FILE:
473 count = aniContext->objectInfo->GetFetchFileResultObject()->GetCount();
474 break;
475 case FetchResType::TYPE_ALBUM:
476 count = aniContext->objectInfo->GetFetchAlbumResultObject()->GetCount();
477 break;
478 case FetchResType::TYPE_PHOTOALBUM:
479 count = aniContext->objectInfo->GetFetchPhotoAlbumResultObject()->GetCount();
480 break;
481 case FetchResType::TYPE_SMARTALBUM:
482 count = aniContext->objectInfo->GetFetchSmartAlbumResultObject()->GetCount();
483 break;
484 default:
485 ANI_ERR_LOG("unsupported FetchResType");
486 break;
487 }
488 if (count < 0) {
489 AniError::ThrowError(env, JS_INNER_FAIL, "Failed to get count");
490 }
491 } else {
492 AniError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get native obj");
493 }
494 return count;
495 }
496 } // namespace OHOS::Media