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