• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2023 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 #include "image_type.h"
16 #define MLOG_TAG "MediaLibraryManager"
17 
18 #include "media_library_manager.h"
19 
20 #include <fcntl.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 #include "accesstoken_kit.h"
25 #include "album_asset.h"
26 #include "datashare_abs_result_set.h"
27 #include "datashare_predicates.h"
28 #include "fetch_result.h"
29 #include "file_asset.h"
30 #include "image_source.h"
31 #include "media_file_uri.h"
32 #include "media_file_utils.h"
33 #include "media_log.h"
34 #include "medialibrary_db_const.h"
35 #include "medialibrary_errno.h"
36 #include "medialibrary_kvstore_manager.h"
37 #include "medialibrary_tracer.h"
38 #include "medialibrary_type_const.h"
39 #include "post_proc.h"
40 #include "permission_utils.h"
41 #include "result_set_utils.h"
42 #include "string_ex.h"
43 #include "thumbnail_const.h"
44 #include "unique_fd.h"
45 
46 #ifdef IMAGE_PURGEABLE_PIXELMAP
47 #include "purgeable_pixelmap_builder.h"
48 #endif
49 
50 using namespace std;
51 using namespace OHOS::NativeRdb;
52 
53 namespace OHOS {
54 namespace Media {
55 shared_ptr<DataShare::DataShareHelper> MediaLibraryManager::sDataShareHelper_ = nullptr;
56 constexpr int32_t DEFAULT_THUMBNAIL_SIZE = 256;
57 constexpr int32_t MAX_DEFAULT_THUMBNAIL_SIZE = 768;
58 constexpr int32_t DEFAULT_MONTH_THUMBNAIL_SIZE = 128;
59 constexpr int32_t DEFAULT_YEAR_THUMBNAIL_SIZE = 64;
60 
61 struct UriParams {
62     string path;
63     string fileUri;
64     Size size;
65     bool isAstc;
66 };
67 
GetMediaLibraryManager()68 MediaLibraryManager *MediaLibraryManager::GetMediaLibraryManager()
69 {
70     static MediaLibraryManager mediaLibMgr;
71     return &mediaLibMgr;
72 }
73 
InitMediaLibraryManager(const sptr<IRemoteObject> & token)74 void MediaLibraryManager::InitMediaLibraryManager(const sptr<IRemoteObject> &token)
75 {
76     token_ = token;
77     if (sDataShareHelper_ == nullptr) {
78         sDataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
79     }
80 }
81 
UriAppendKeyValue(string & uri,const string & key,const string & value)82 static void UriAppendKeyValue(string &uri, const string &key, const string &value)
83 {
84     string uriKey = key + '=';
85     if (uri.find(uriKey) != string::npos) {
86         return;
87     }
88     char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
89     string append = queryMark + key + '=' + value;
90     size_t posJ = uri.find('#');
91     if (posJ == string::npos) {
92         uri += append;
93     } else {
94         uri.insert(posJ, append);
95     }
96 }
97 
GetCreateUri(string & uri)98 static void GetCreateUri(string &uri)
99 {
100     uri = PAH_CREATE_PHOTO;
101     const std::string API_VERSION = "api_version";
102     UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
103 }
104 
parseCreateArguments(const string & displayName,DataShareValuesBucket & valuesBucket)105 static int32_t parseCreateArguments(const string &displayName, DataShareValuesBucket &valuesBucket)
106 {
107     MediaType mediaType = MediaFileUtils::GetMediaType(displayName);
108     if (mediaType != MEDIA_TYPE_IMAGE && mediaType != MEDIA_TYPE_VIDEO) {
109         MEDIA_ERR_LOG("Failed to create Asset, invalid file type");
110         return E_ERR;
111     }
112     valuesBucket.Put(MEDIA_DATA_DB_NAME, displayName);
113     valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, static_cast<int32_t>(mediaType));
114     return E_OK;
115 }
116 
CreateAsset(const string & displayName)117 string MediaLibraryManager::CreateAsset(const string &displayName)
118 {
119     if (sDataShareHelper_ == nullptr || displayName.empty()) {
120         MEDIA_ERR_LOG("Failed to create Asset, datashareHelper is nullptr");
121         sDataShareHelper_ = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
122     }
123     DataShareValuesBucket valuesBucket;
124     auto ret = parseCreateArguments(displayName, valuesBucket);
125     if (ret != NativeRdb::E_OK) {
126         MEDIA_ERR_LOG("Failed to create Asset, parse create argument fails");
127         return "";
128     }
129     string createFileUri;
130     GetCreateUri(createFileUri);
131     Uri createUri(createFileUri);
132     string outUri;
133     int index = sDataShareHelper_->InsertExt(createUri, valuesBucket, outUri);
134     if (index < 0) {
135         MEDIA_ERR_LOG("Failed to create Asset, insert database error!");
136         return "";
137     }
138     return outUri;
139 }
140 
CheckUri(string & uri)141 static bool CheckUri(string &uri)
142 {
143     if (uri.find("..") != string::npos) {
144         return false;
145     }
146     string uriprex = "file://media";
147     return uri.substr(0, uriprex.size()) == uriprex;
148 }
149 
OpenAsset(string & uri,const string openMode)150 int32_t MediaLibraryManager::OpenAsset(string &uri, const string openMode)
151 {
152     if (openMode.empty()) {
153         return E_ERR;
154     }
155     if (!CheckUri(uri)) {
156         MEDIA_ERR_LOG("invalid uri");
157         return E_ERR;
158     }
159     string originOpenMode = openMode;
160     std::transform(originOpenMode.begin(), originOpenMode.end(),
161         originOpenMode.begin(), [](unsigned char c) {return std::tolower(c);});
162     if (!MEDIA_OPEN_MODES.count(originOpenMode)) {
163         return E_ERR;
164     }
165     if (sDataShareHelper_ == nullptr) {
166         MEDIA_ERR_LOG("Failed to open Asset, datashareHelper is nullptr");
167         return E_ERR;
168     }
169     Uri openUri(uri);
170     return sDataShareHelper_->OpenFile(openUri, openMode);
171 }
172 
CloseAsset(const string & uri,const int32_t fd)173 int32_t MediaLibraryManager::CloseAsset(const string &uri, const int32_t fd)
174 {
175     int32_t retVal = E_FAIL;
176     DataShareValuesBucket valuesBucket;
177     valuesBucket.Put(MEDIA_DATA_DB_URI, uri);
178 
179     if (sDataShareHelper_ != nullptr) {
180         string abilityUri = MEDIALIBRARY_DATA_URI;
181         Uri closeAssetUri(abilityUri + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET);
182 
183         if (close(fd) == E_SUCCESS) {
184             retVal = sDataShareHelper_->Insert(closeAssetUri, valuesBucket);
185         }
186 
187         if (retVal == E_FAIL) {
188             MEDIA_ERR_LOG("Failed to close the file");
189         }
190     }
191 
192     return retVal;
193 }
194 
QueryTotalSize(MediaVolume & outMediaVolume)195 int32_t MediaLibraryManager::QueryTotalSize(MediaVolume &outMediaVolume)
196 {
197     auto dataShareHelper = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
198     if (dataShareHelper == nullptr) {
199         MEDIA_ERR_LOG("dataShareHelper is null");
200         return E_FAIL;
201     }
202     vector<string> columns;
203     Uri uri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_QUERYOPRN_QUERYVOLUME + "/" + MEDIA_QUERYOPRN_QUERYVOLUME);
204     DataSharePredicates predicates;
205     auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
206     if (queryResultSet == nullptr) {
207         MEDIA_ERR_LOG("queryResultSet is null!");
208         return E_FAIL;
209     }
210     auto count = 0;
211     auto ret = queryResultSet->GetRowCount(count);
212     if (ret != NativeRdb::E_OK) {
213         MEDIA_ERR_LOG("get rdbstore failed");
214         return E_HAS_DB_ERROR;
215     }
216     MEDIA_INFO_LOG("count = %{public}d", (int)count);
217     if (count >= 0) {
218         while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
219             int mediatype = get<int32_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_MEDIA_TYPE,
220                 queryResultSet, TYPE_INT32));
221             int64_t size = get<int64_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_SIZE,
222                 queryResultSet, TYPE_INT64));
223             outMediaVolume.SetSize(mediatype, size);
224         }
225     }
226     MEDIA_INFO_LOG("Size:Files:%{public}" PRId64 " Videos:%{public}" PRId64 " Images:%{public} " PRId64
227         " Audio:%{public}" PRId64,
228         outMediaVolume.GetFilesSize(), outMediaVolume.GetVideosSize(),
229         outMediaVolume.GetImagesSize(), outMediaVolume.GetAudiosSize());
230     return E_SUCCESS;
231 }
232 
GetResultSetFromDb(string columnName,const string & value,vector<string> & columns)233 std::shared_ptr<DataShareResultSet> MediaLibraryManager::GetResultSetFromDb(string columnName, const string &value,
234     vector<string> &columns)
235 {
236     Uri uri(MEDIALIBRARY_MEDIA_PREFIX);
237     DataSharePredicates predicates;
238     predicates.EqualTo(columnName, value);
239     predicates.And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
240     DatashareBusinessError businessError;
241 
242     if (sDataShareHelper_ == nullptr) {
243         MEDIA_ERR_LOG("sDataShareHelper_ is null");
244         return nullptr;
245     }
246     return sDataShareHelper_->Query(uri, predicates, columns, &businessError);
247 }
248 
SolvePath(const string & filePath,string & tempPath,string & userId)249 static int32_t SolvePath(const string &filePath, string &tempPath, string &userId)
250 {
251     if (filePath.empty()) {
252         return E_INVALID_PATH;
253     }
254 
255     string prePath = PRE_PATH_VALUES;
256     if (filePath.find(prePath) != 0) {
257         return E_CHECK_ROOT_DIR_FAIL;
258     }
259     string postpath = filePath.substr(prePath.length());
260     auto pos = postpath.find('/');
261     if (pos == string::npos) {
262         return E_INVALID_ARGUMENTS;
263     }
264     userId = postpath.substr(0, pos);
265     postpath = postpath.substr(pos + 1);
266     tempPath = prePath + postpath;
267 
268     return E_SUCCESS;
269 }
270 
CheckResultSet(std::shared_ptr<DataShareResultSet> & resultSet)271 static int32_t CheckResultSet(std::shared_ptr<DataShareResultSet> &resultSet)
272 {
273     int count = 0;
274     auto ret = resultSet->GetRowCount(count);
275     if (ret != NativeRdb::E_OK) {
276         MEDIA_ERR_LOG("Failed to get resultset row count, ret: %{public}d", ret);
277         return ret;
278     }
279     if (count <= 0) {
280         MEDIA_ERR_LOG("Failed to get count, count: %{public}d", count);
281         return E_FAIL;
282     }
283     ret = resultSet->GoToFirstRow();
284     if (ret != NativeRdb::E_OK) {
285         MEDIA_ERR_LOG("Failed to go to first row, ret: %{public}d", ret);
286         return ret;
287     }
288     return E_SUCCESS;
289 }
290 
291 
GetFilePathFromUri(const Uri & fileUri,string & filePath,string userId)292 int32_t MediaLibraryManager::GetFilePathFromUri(const Uri &fileUri, string &filePath, string userId)
293 {
294     string uri = fileUri.ToString();
295     MediaFileUri virtualUri(uri);
296     if (!virtualUri.IsValid()) {
297         return E_URI_INVALID;
298     }
299     string virtualId = virtualUri.GetFileId();
300 #ifdef MEDIALIBRARY_COMPATIBILITY
301     if (MediaFileUtils::GetTableFromVirtualUri(uri) != MEDIALIBRARY_TABLE) {
302         MEDIA_INFO_LOG("uri:%{private}s does not match Files Table", uri.c_str());
303         return E_URI_INVALID;
304     }
305 #endif
306     vector<string> columns = { MEDIA_DATA_DB_FILE_PATH };
307     auto resultSet = MediaLibraryManager::GetResultSetFromDb(MEDIA_DATA_DB_ID, virtualId, columns);
308     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_INVALID_URI,
309         "GetFilePathFromUri::uri is not correct: %{private}s", uri.c_str());
310     if (CheckResultSet(resultSet) != E_SUCCESS) {
311         return E_FAIL;
312     }
313 
314     std::string tempPath = ResultSetUtils::GetStringValFromColumn(1, resultSet);
315     if (tempPath.find(ROOT_MEDIA_DIR) != 0) {
316         return E_CHECK_ROOT_DIR_FAIL;
317     }
318     string relativePath = tempPath.substr((ROOT_MEDIA_DIR + DOCS_PATH).length());
319     auto pos = relativePath.find('/');
320     if (pos == string::npos) {
321         return E_INVALID_ARGUMENTS;
322     }
323     relativePath = relativePath.substr(0, pos + 1);
324     if ((relativePath != DOC_DIR_VALUES) && (relativePath != DOWNLOAD_DIR_VALUES)) {
325         return E_DIR_CHECK_DIR_FAIL;
326     }
327 
328     string prePath = PRE_PATH_VALUES;
329     string postpath = tempPath.substr(prePath.length());
330     tempPath = prePath + userId + "/" + postpath;
331     filePath = tempPath;
332     return E_SUCCESS;
333 }
334 
GetUriFromFilePath(const string & filePath,Uri & fileUri,string & userId)335 int32_t MediaLibraryManager::GetUriFromFilePath(const string &filePath, Uri &fileUri, string &userId)
336 {
337     if (filePath.empty()) {
338         return E_INVALID_PATH;
339     }
340 
341     string tempPath;
342     SolvePath(filePath, tempPath, userId);
343     if (tempPath.find(ROOT_MEDIA_DIR) != 0) {
344         return E_CHECK_ROOT_DIR_FAIL;
345     }
346     string relativePath = tempPath.substr((ROOT_MEDIA_DIR + DOCS_PATH).length());
347     auto pos = relativePath.find('/');
348     if (pos == string::npos) {
349         return E_INVALID_ARGUMENTS;
350     }
351     relativePath = relativePath.substr(0, pos + 1);
352     if ((relativePath != DOC_DIR_VALUES) && (relativePath != DOWNLOAD_DIR_VALUES)) {
353         return E_DIR_CHECK_DIR_FAIL;
354     }
355 
356     vector<string> columns = { MEDIA_DATA_DB_ID};
357     auto resultSet = MediaLibraryManager::GetResultSetFromDb(MEDIA_DATA_DB_FILE_PATH, tempPath, columns);
358     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_INVALID_URI,
359         "GetUriFromFilePath::tempPath is not correct: %{private}s", tempPath.c_str());
360     if (CheckResultSet(resultSet) != E_SUCCESS) {
361         return E_FAIL;
362     }
363 
364     int32_t fileId = ResultSetUtils::GetIntValFromColumn(0, resultSet);
365 #ifdef MEDIALIBRARY_COMPATIBILITY
366     int64_t virtualId = MediaFileUtils::GetVirtualIdByType(fileId, MediaType::MEDIA_TYPE_FILE);
367     fileUri = MediaFileUri(MediaType::MEDIA_TYPE_FILE, to_string(virtualId), "", MEDIA_API_VERSION_V9);
368 #else
369     fileUri = MediaFileUri(MediaType::MEDIA_TYPE_FILE, to_string(fileId), "", MEDIA_API_VERSION_V9);
370 #endif
371     return E_SUCCESS;
372 }
373 
GetSandboxPath(const std::string & path,const Size & size,bool isAstc)374 static std::string GetSandboxPath(const std::string &path, const Size &size, bool isAstc)
375 {
376     if (path.length() < ROOT_MEDIA_DIR.length()) {
377         return "";
378     }
379     int min = std::min(size.width, size.height);
380     int max = std::max(size.width, size.height);
381     std::string suffixStr = path.substr(ROOT_MEDIA_DIR.length()) + "/";
382     if (min == DEFAULT_ORIGINAL && max == DEFAULT_ORIGINAL) {
383         suffixStr += "LCD.jpg";
384     } else if (min <= DEFAULT_THUMBNAIL_SIZE && max <= MAX_DEFAULT_THUMBNAIL_SIZE) {
385         suffixStr += isAstc ? "THM_ASTC.astc" : "THM.jpg";
386     } else {
387         suffixStr += "LCD.jpg";
388     }
389 
390     return ROOT_SANDBOX_DIR + ".thumbs/" + suffixStr;
391 }
392 
OpenThumbnail(string & uriStr,const string & path,const Size & size,bool isAstc)393 int MediaLibraryManager::OpenThumbnail(string &uriStr, const string &path, const Size &size, bool isAstc)
394 {
395     if (sDataShareHelper_ == nullptr) {
396         MEDIA_ERR_LOG("Failed to open thumbnail, datashareHelper is nullptr");
397         return E_ERR;
398     }
399     if (!path.empty()) {
400         string sandboxPath = GetSandboxPath(path, size, isAstc);
401         int fd = -1;
402         if (!sandboxPath.empty()) {
403             fd = open(sandboxPath.c_str(), O_RDONLY);
404             if (fd < 0 && isAstc) {
405                 string suffixStr = "THM_ASTC.astc";
406                 size_t thmIdx = sandboxPath.find(suffixStr);
407                 sandboxPath.replace(thmIdx, suffixStr.length(), "THM.jpg");
408                 fd = open(sandboxPath.c_str(), O_RDONLY);
409             }
410         }
411         if (fd > 0) {
412             return fd;
413         }
414         MEDIA_INFO_LOG("OpenThumbnail from andboxPath failed, path :%{public}s fd %{public}d errno %{public}d",
415             path.c_str(), fd, errno);
416         if (IsAsciiString(path)) {
417             uriStr += "&" + THUMBNAIL_PATH + "=" + path;
418         }
419     }
420     Uri openUri(uriStr);
421     return sDataShareHelper_->OpenFile(openUri, "R");
422 }
423 
424 /**
425  * Get the file uri prefix with id
426  * eg. Input: file://media/Photo/10/IMG_xxx/01.jpg
427  *     Output: file://media/Photo/10
428  */
GetUriIdPrefix(std::string & fileUri)429 static void GetUriIdPrefix(std::string &fileUri)
430 {
431     MediaFileUri mediaUri(fileUri);
432     if (!mediaUri.IsApi10()) {
433         return;
434     }
435     auto slashIdx = fileUri.rfind('/');
436     if (slashIdx == std::string::npos) {
437         return;
438     }
439     auto tmpUri = fileUri.substr(0, slashIdx);
440     slashIdx = tmpUri.rfind('/');
441     if (slashIdx == std::string::npos) {
442         return;
443     }
444     fileUri = tmpUri.substr(0, slashIdx);
445 }
446 
GetParamsFromUri(const string & uri,const bool isOldVer,UriParams & uriParams)447 static bool GetParamsFromUri(const string &uri, const bool isOldVer, UriParams &uriParams)
448 {
449     MediaFileUri mediaUri(uri);
450     if (!mediaUri.IsValid()) {
451         return false;
452     }
453     if (isOldVer) {
454         auto index = uri.find("thumbnail");
455         if (index == string::npos) {
456             return false;
457         }
458         uriParams.fileUri = uri.substr(0, index - 1);
459         GetUriIdPrefix(uriParams.fileUri);
460         index += strlen("thumbnail");
461         index = uri.find('/', index);
462         if (index == string::npos) {
463             return false;
464         }
465         index += 1;
466         auto tmpIdx = uri.find('/', index);
467         if (tmpIdx == string::npos) {
468             return false;
469         }
470 
471         int32_t width = 0;
472         StrToInt(uri.substr(index, tmpIdx - index), width);
473         int32_t height = 0;
474         StrToInt(uri.substr(tmpIdx + 1), height);
475         uriParams.size = { .width = width, .height = height };
476     } else {
477         auto qIdx = uri.find('?');
478         if (qIdx == string::npos) {
479             return false;
480         }
481         uriParams.fileUri = uri.substr(0, qIdx);
482         GetUriIdPrefix(uriParams.fileUri);
483         auto &queryKey = mediaUri.GetQueryKeys();
484         if (queryKey.count(THUMBNAIL_PATH) != 0) {
485             uriParams.path = queryKey[THUMBNAIL_PATH];
486         }
487         if (queryKey.count(THUMBNAIL_WIDTH) != 0) {
488             uriParams.size.width = stoi(queryKey[THUMBNAIL_WIDTH]);
489         }
490         if (queryKey.count(THUMBNAIL_HEIGHT) != 0) {
491             uriParams.size.height = stoi(queryKey[THUMBNAIL_HEIGHT]);
492         }
493         if (queryKey.count(THUMBNAIL_OPER) != 0) {
494             uriParams.isAstc = queryKey[THUMBNAIL_OPER] == MEDIA_DATA_DB_THUMB_ASTC;
495         }
496     }
497     return true;
498 }
499 
IfSizeEqualsRatio(const Size & imageSize,const Size & targetSize)500 static bool IfSizeEqualsRatio(const Size &imageSize, const Size &targetSize)
501 {
502     if (imageSize.height <= 0 || targetSize.height <= 0) {
503         return false;
504     }
505 
506     float imageSizeScale = static_cast<float>(imageSize.width) / static_cast<float>(imageSize.height);
507     float targetSizeScale = static_cast<float>(targetSize.width) / static_cast<float>(targetSize.height);
508     if (imageSizeScale - targetSizeScale > FLOAT_EPSILON || targetSizeScale - imageSizeScale > FLOAT_EPSILON) {
509         return false;
510     } else {
511         return true;
512     }
513 }
514 
DecodeThumbnail(UniqueFd & uniqueFd,const Size & size)515 unique_ptr<PixelMap> MediaLibraryManager::DecodeThumbnail(UniqueFd& uniqueFd, const Size& size)
516 {
517     MediaLibraryTracer tracer;
518     tracer.Start("ImageSource::CreateImageSource");
519     SourceOptions opts;
520     uint32_t err = 0;
521     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
522     if (imageSource  == nullptr) {
523         MEDIA_ERR_LOG("CreateImageSource err %{public}d", err);
524         return nullptr;
525     }
526 
527     ImageInfo imageInfo;
528     err = imageSource->GetImageInfo(0, imageInfo);
529     if (err != E_OK) {
530         MEDIA_ERR_LOG("GetImageInfo err %{public}d", err);
531         return nullptr;
532     }
533 
534     bool isEqualsRatio = IfSizeEqualsRatio(imageInfo.size, size);
535     DecodeOptions decodeOpts;
536     decodeOpts.desiredSize = isEqualsRatio ? size : imageInfo.size;
537     decodeOpts.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
538     unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
539     if (pixelMap == nullptr) {
540         MEDIA_ERR_LOG("CreatePixelMap err %{public}d", err);
541         return nullptr;
542     }
543 
544     PostProc postProc;
545     if (size.width != 0 && size.width != DEFAULT_ORIGINAL && !isEqualsRatio && !postProc.CenterScale(size, *pixelMap)) {
546         return nullptr;
547     }
548 
549     // Make the ashmem of pixelmap to be purgeable after the operation on ashmem.
550     // And then make the pixelmap subject to PurgeableManager's control.
551 #ifdef IMAGE_PURGEABLE_PIXELMAP
552     PurgeableBuilder::MakePixelMapToBePurgeable(pixelMap, imageSource, decodeOpts, size);
553 #endif
554     return pixelMap;
555 }
556 
QueryThumbnail(const std::string & uri,Size & size,const string & path,bool isAstc)557 unique_ptr<PixelMap> MediaLibraryManager::QueryThumbnail(const std::string &uri, Size &size,
558                                                          const string &path, bool isAstc)
559 {
560     MediaLibraryTracer tracer;
561     tracer.Start("QueryThumbnail uri:" + uri);
562 
563     string oper = isAstc ? MEDIA_DATA_DB_THUMB_ASTC : MEDIA_DATA_DB_THUMBNAIL;
564     string openUriStr = uri + "?" + MEDIA_OPERN_KEYWORD + "=" + oper + "&" + MEDIA_DATA_DB_WIDTH +
565         "=" + to_string(size.width) + "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(size.height);
566     tracer.Start("DataShare::OpenThumbnail");
567     UniqueFd uniqueFd(MediaLibraryManager::OpenThumbnail(openUriStr, path, size, isAstc));
568     if (uniqueFd.Get() < 0) {
569         MEDIA_ERR_LOG("queryThumb is null, errCode is %{public}d", uniqueFd.Get());
570         return nullptr;
571     }
572     tracer.Finish();
573     return DecodeThumbnail(uniqueFd, size);
574 }
575 
GetThumbnail(const Uri & uri)576 std::unique_ptr<PixelMap> MediaLibraryManager::GetThumbnail(const Uri &uri)
577 {
578     // uri is dataability:///media/image/<id>/thumbnail/<width>/<height>
579     string uriStr = uri.ToString();
580     auto thumbLatIdx = uriStr.find("thumbnail");
581     bool isAstc = false;
582     if (thumbLatIdx == string::npos || thumbLatIdx > uriStr.length()) {
583         thumbLatIdx = uriStr.find("astc");
584         if (thumbLatIdx == string::npos || thumbLatIdx > uriStr.length()) {
585             MEDIA_ERR_LOG("GetThumbnail failed, oper is invalid");
586             return nullptr;
587         }
588         isAstc = true;
589     }
590     thumbLatIdx += isAstc ? strlen("astc") : strlen("thumbnail");
591     bool isOldVersion = uriStr[thumbLatIdx] == '/';
592     UriParams uriParams;
593     if (!GetParamsFromUri(uriStr, isOldVersion, uriParams)) {
594         return nullptr;
595     }
596     auto pixelmap = QueryThumbnail(uriParams.fileUri, uriParams.size, uriParams.path, uriParams.isAstc);
597     return pixelmap;
598 }
599 
GetBatchAstcs(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)600 int32_t MediaLibraryManager::GetBatchAstcs(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
601 {
602     if (uriBatch.empty()) {
603         MEDIA_INFO_LOG("GetBatchAstcs uriBatch is empty");
604         return E_INVALID_URI;
605     }
606 
607     UriParams uriParams;
608     if (!GetParamsFromUri(uriBatch.at(0), false, uriParams)) {
609         MEDIA_ERR_LOG("GetParamsFromUri failed in GetBatchAstcs");
610         return E_INVALID_URI;
611     }
612     vector<string> timeIdBatch;
613     MediaFileUri::GetTimeIdFromUri(uriBatch, timeIdBatch);
614     MEDIA_INFO_LOG("GetBatchAstcs image batch size: %{public}zu, begin: %{public}s, end: %{public}s",
615         uriBatch.size(), timeIdBatch.back().c_str(), timeIdBatch.front().c_str());
616 
617     KvStoreValueType valueType;
618     if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
619         valueType = KvStoreValueType::MONTH_ASTC;
620     } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
621         uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
622         valueType = KvStoreValueType::YEAR_ASTC;
623     } else {
624         MEDIA_ERR_LOG("GetBatchAstcs invalid image size");
625         return E_INVALID_URI;
626     }
627 
628     auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
629     if (kvStore == nullptr) {
630         MEDIA_ERR_LOG("GetBatchAstcs kvStore is nullptr");
631         return E_DB_FAIL;
632     }
633     int32_t status = kvStore->BatchQuery(timeIdBatch, astcBatch);
634     if (status != E_OK) {
635         MEDIA_ERR_LOG("GetBatchAstcs failed, status %{public}d", status);
636         return status;
637     }
638     return E_OK;
639 }
640 } // namespace Media
641 } // namespace OHOS
642