• 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 
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