1 /*
2 * Copyright (C) 2021-2024 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
17 #define MLOG_TAG "MediaLibraryManager"
18
19 #include "media_library_manager.h"
20
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24
25 #include "accesstoken_kit.h"
26 #include "album_asset.h"
27 #include "datashare_abs_result_set.h"
28 #include "datashare_predicates.h"
29 #include "directory_ex.h"
30 #include "fetch_result.h"
31 #include "file_asset.h"
32 #include "file_uri.h"
33 #include "image_source.h"
34 #include "iservice_registry.h"
35 #include "media_asset_rdbstore.h"
36 #include "media_file_uri.h"
37 #include "media_file_utils.h"
38 #include "media_log.h"
39 #include "medialibrary_db_const.h"
40 #include "medialibrary_errno.h"
41 #include "medialibrary_kvstore_manager.h"
42 #include "medialibrary_tracer.h"
43 #include "medialibrary_type_const.h"
44 #include "media_app_uri_permission_column.h"
45 #include "media_app_uri_sensitive_column.h"
46 #include "media_library_tab_old_photos_client.h"
47 #include "post_proc.h"
48 #include "permission_utils.h"
49 #include "result_set_utils.h"
50 #include "string_ex.h"
51 #include "system_ability_definition.h"
52 #include "thumbnail_const.h"
53 #include "unique_fd.h"
54
55 #ifdef IMAGE_PURGEABLE_PIXELMAP
56 #include "purgeable_pixelmap_builder.h"
57 #endif
58
59 using namespace std;
60 using namespace OHOS::NativeRdb;
61 using namespace OHOS::Security::AccessToken;
62
63 namespace OHOS {
64 namespace Media {
65 shared_ptr<DataShare::DataShareHelper> MediaLibraryManager::sDataShareHelper_ = nullptr;
66 sptr<IRemoteObject> MediaLibraryManager::token_ = nullptr;
67 constexpr int32_t DEFAULT_THUMBNAIL_SIZE = 256;
68 constexpr int32_t MAX_DEFAULT_THUMBNAIL_SIZE = 768;
69 constexpr int32_t DEFAULT_MONTH_THUMBNAIL_SIZE = 128;
70 constexpr int32_t DEFAULT_YEAR_THUMBNAIL_SIZE = 64;
71 constexpr int32_t URI_MAX_SIZE = 1000;
72 constexpr uint32_t URI_PERMISSION_FLAG_READ = 1;
73 constexpr uint32_t URI_PERMISSION_FLAG_WRITE = 2;
74 constexpr uint32_t URI_PERMISSION_FLAG_READWRITE = 3;
75
76 struct UriParams {
77 string path;
78 string fileUri;
79 Size size;
80 bool isAstc;
81 DecodeDynamicRange dynamicRange;
82 };
83 static map<string, TableType> tableMap = {
84 { MEDIALIBRARY_TYPE_IMAGE_URI, TableType::TYPE_PHOTOS },
85 { MEDIALIBRARY_TYPE_VIDEO_URI, TableType::TYPE_PHOTOS },
86 { MEDIALIBRARY_TYPE_AUDIO_URI, TableType::TYPE_AUDIOS },
87 { PhotoColumn::PHOTO_TYPE_URI, TableType::TYPE_PHOTOS },
88 { AudioColumn::AUDIO_TYPE_URI, TableType::TYPE_AUDIOS }
89 };
90
GetMediaLibraryManager()91 MediaLibraryManager *MediaLibraryManager::GetMediaLibraryManager()
92 {
93 static MediaLibraryManager mediaLibMgr;
94 return &mediaLibMgr;
95 }
96
InitMediaLibraryManager(const sptr<IRemoteObject> & token)97 void MediaLibraryManager::InitMediaLibraryManager(const sptr<IRemoteObject> &token)
98 {
99 token_ = token;
100 if (sDataShareHelper_ == nullptr) {
101 sDataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
102 }
103 }
104
InitToken()105 sptr<IRemoteObject> MediaLibraryManager::InitToken()
106 {
107 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
108 if (saManager == nullptr) {
109 MEDIA_ERR_LOG("get system ability mgr failed.");
110 return nullptr;
111 }
112 auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
113 if (remoteObj == nullptr) {
114 MEDIA_ERR_LOG("GetSystemAbility Service failed.");
115 return nullptr;
116 }
117 return remoteObj;
118 }
119
InitMediaLibraryManager()120 void MediaLibraryManager::InitMediaLibraryManager()
121 {
122 token_ = InitToken();
123 if (sDataShareHelper_ == nullptr && token_ != nullptr) {
124 sDataShareHelper_ = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
125 }
126 }
127
UriAppendKeyValue(string & uri,const string & key,const string & value)128 static void UriAppendKeyValue(string &uri, const string &key, const string &value)
129 {
130 string uriKey = key + '=';
131 if (uri.find(uriKey) != string::npos) {
132 return;
133 }
134 char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
135 string append = queryMark + key + '=' + value;
136 size_t posJ = uri.find('#');
137 if (posJ == string::npos) {
138 uri += append;
139 } else {
140 uri.insert(posJ, append);
141 }
142 }
143
GetCreateUri(string & uri)144 static void GetCreateUri(string &uri)
145 {
146 uri = PAH_CREATE_PHOTO;
147 const std::string API_VERSION = "api_version";
148 UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
149 }
150
parseCreateArguments(const string & displayName,DataShareValuesBucket & valuesBucket)151 static int32_t parseCreateArguments(const string &displayName, DataShareValuesBucket &valuesBucket)
152 {
153 MediaType mediaType = MediaFileUtils::GetMediaType(displayName);
154 if (mediaType != MEDIA_TYPE_IMAGE && mediaType != MEDIA_TYPE_VIDEO) {
155 MEDIA_ERR_LOG("Failed to create Asset, invalid file type");
156 return E_ERR;
157 }
158 valuesBucket.Put(MEDIA_DATA_DB_NAME, displayName);
159 valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, static_cast<int32_t>(mediaType));
160 return E_OK;
161 }
162
CreateAsset(const string & displayName)163 string MediaLibraryManager::CreateAsset(const string &displayName)
164 {
165 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
166 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
167 if (dataShareHelper == nullptr || displayName.empty()) {
168 MEDIA_ERR_LOG("Failed to create Asset, datashareHelper is nullptr");
169 return "";
170 }
171 DataShareValuesBucket valuesBucket;
172 auto ret = parseCreateArguments(displayName, valuesBucket);
173 if (ret != NativeRdb::E_OK) {
174 MEDIA_ERR_LOG("Failed to create Asset, parse create argument fails");
175 return "";
176 }
177 string createFileUri;
178 GetCreateUri(createFileUri);
179 Uri createUri(createFileUri);
180 string outUri;
181 int index = dataShareHelper->InsertExt(createUri, valuesBucket, outUri);
182 if (index < 0) {
183 MEDIA_ERR_LOG("Failed to create Asset, insert database error!");
184 return "";
185 }
186 return outUri;
187 }
188
CheckUri(string & uri)189 static bool CheckUri(string &uri)
190 {
191 if (uri.find("../") != string::npos) {
192 return false;
193 }
194 string uriprex = "file://media";
195 return uri.substr(0, uriprex.size()) == uriprex;
196 }
197
CheckPhotoUri(const string & uri)198 static bool CheckPhotoUri(const string &uri)
199 {
200 if (uri.find("../") != string::npos) {
201 return false;
202 }
203 string photoUriPrefix = "file://media/Photo/";
204 return MediaFileUtils::StartsWith(uri, photoUriPrefix);
205 }
206
OpenAsset(string & uri,const string openMode)207 int32_t MediaLibraryManager::OpenAsset(string &uri, const string openMode)
208 {
209 if (openMode.empty()) {
210 return E_ERR;
211 }
212 if (!CheckUri(uri)) {
213 MEDIA_ERR_LOG("invalid uri");
214 return E_ERR;
215 }
216 string originOpenMode = openMode;
217 std::transform(originOpenMode.begin(), originOpenMode.end(),
218 originOpenMode.begin(), [](unsigned char c) {return std::tolower(c);});
219 if (!MEDIA_OPEN_MODES.count(originOpenMode)) {
220 return E_ERR;
221 }
222
223 if (sDataShareHelper_ == nullptr) {
224 MEDIA_ERR_LOG("Failed to open Asset, datashareHelper is nullptr");
225 return E_ERR;
226 }
227 Uri openUri(uri);
228 return sDataShareHelper_->OpenFile(openUri, openMode);
229 }
230
CloseAsset(const string & uri,const int32_t fd)231 int32_t MediaLibraryManager::CloseAsset(const string &uri, const int32_t fd)
232 {
233 int32_t retVal = E_FAIL;
234 DataShareValuesBucket valuesBucket;
235 valuesBucket.Put(MEDIA_DATA_DB_URI, uri);
236
237 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
238 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
239 if (dataShareHelper != nullptr) {
240 string abilityUri = MEDIALIBRARY_DATA_URI;
241 Uri closeAssetUri(abilityUri + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET);
242
243 if (close(fd) == E_SUCCESS) {
244 retVal = dataShareHelper->Insert(closeAssetUri, valuesBucket);
245 }
246
247 if (retVal == E_FAIL) {
248 MEDIA_ERR_LOG("Failed to close the file");
249 }
250 }
251
252 return retVal;
253 }
254
QueryTotalSize(MediaVolume & outMediaVolume)255 int32_t MediaLibraryManager::QueryTotalSize(MediaVolume &outMediaVolume)
256 {
257 auto dataShareHelper = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
258 if (dataShareHelper == nullptr) {
259 MEDIA_ERR_LOG("dataShareHelper is null");
260 return E_FAIL;
261 }
262 vector<string> columns;
263 Uri uri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_QUERYOPRN_QUERYVOLUME + "/" + MEDIA_QUERYOPRN_QUERYVOLUME);
264 DataSharePredicates predicates;
265 auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
266 if (queryResultSet == nullptr) {
267 MEDIA_ERR_LOG("queryResultSet is null!");
268 return E_FAIL;
269 }
270 auto count = 0;
271 auto ret = queryResultSet->GetRowCount(count);
272 if (ret != NativeRdb::E_OK) {
273 MEDIA_ERR_LOG("get rdbstore failed");
274 return E_HAS_DB_ERROR;
275 }
276 MEDIA_INFO_LOG("count = %{public}d", (int)count);
277 if (count >= 0) {
278 int thumbnailType = -1;
279 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
280 int mediatype = get<int32_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_MEDIA_TYPE,
281 queryResultSet, TYPE_INT32));
282 int64_t size = get<int64_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_SIZE,
283 queryResultSet, TYPE_INT64));
284 MEDIA_INFO_LOG("media_type: %{public}d, size: %{public}lld", mediatype, static_cast<long long>(size));
285 if (mediatype == MEDIA_TYPE_IMAGE || mediatype == thumbnailType) {
286 outMediaVolume.SetSize(MEDIA_TYPE_IMAGE, outMediaVolume.GetImagesSize() + size);
287 } else {
288 outMediaVolume.SetSize(mediatype, size);
289 }
290 }
291 }
292 MEDIA_INFO_LOG("Size: Files:%{public}lld, Videos:%{public}lld, Images:%{public}lld, Audio:%{public}lld",
293 static_cast<long long>(outMediaVolume.GetFilesSize()),
294 static_cast<long long>(outMediaVolume.GetVideosSize()),
295 static_cast<long long>(outMediaVolume.GetImagesSize()),
296 static_cast<long long>(outMediaVolume.GetAudiosSize())
297 );
298 return E_SUCCESS;
299 }
300
GetResultSetFromPhotos(const string & value,vector<string> & columns,sptr<IRemoteObject> & token,shared_ptr<DataShare::DataShareHelper> & dataShareHelper)301 std::shared_ptr<DataShareResultSet> GetResultSetFromPhotos(const string &value, vector<string> &columns,
302 sptr<IRemoteObject> &token, shared_ptr<DataShare::DataShareHelper> &dataShareHelper)
303 {
304 if (!CheckPhotoUri(value)) {
305 MEDIA_ERR_LOG("Failed to check invalid uri: %{public}s", value.c_str());
306 return nullptr;
307 }
308 Uri queryUri(PAH_QUERY_PHOTO);
309 DataSharePredicates predicates;
310 string fileId = MediaFileUtils::GetIdFromUri(value);
311 predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
312 DatashareBusinessError businessError;
313 if (dataShareHelper == nullptr) {
314 MEDIA_ERR_LOG("datashareHelper is nullptr");
315 return nullptr;
316 }
317 return dataShareHelper->Query(queryUri, predicates, columns, &businessError);
318 }
319
GetResultSetFromDb(string columnName,const string & value,vector<string> & columns)320 std::shared_ptr<DataShareResultSet> MediaLibraryManager::GetResultSetFromDb(string columnName, const string &value,
321 vector<string> &columns)
322 {
323 if (columnName == MEDIA_DATA_DB_URI) {
324 return GetResultSetFromPhotos(value, columns, token_, sDataShareHelper_);
325 }
326 Uri uri(MEDIALIBRARY_MEDIA_PREFIX);
327 DataSharePredicates predicates;
328 predicates.EqualTo(columnName, value);
329 predicates.And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
330 DatashareBusinessError businessError;
331
332 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
333 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
334 if (dataShareHelper == nullptr) {
335 MEDIA_ERR_LOG("dataShareHelper is null");
336 return nullptr;
337 }
338 return dataShareHelper->Query(uri, predicates, columns, &businessError);
339 }
340
SolvePath(const string & filePath,string & tempPath,string & userId)341 static int32_t SolvePath(const string &filePath, string &tempPath, string &userId)
342 {
343 if (filePath.empty()) {
344 return E_INVALID_PATH;
345 }
346
347 string prePath = PRE_PATH_VALUES;
348 if (filePath.find(prePath) != 0) {
349 return E_CHECK_ROOT_DIR_FAIL;
350 }
351 string postpath = filePath.substr(prePath.length());
352 auto pos = postpath.find('/');
353 if (pos == string::npos) {
354 return E_INVALID_ARGUMENTS;
355 }
356 userId = postpath.substr(0, pos);
357 postpath = postpath.substr(pos + 1);
358 tempPath = prePath + postpath;
359
360 return E_SUCCESS;
361 }
362
CheckResultSet(std::shared_ptr<DataShareResultSet> & resultSet)363 int32_t MediaLibraryManager::CheckResultSet(std::shared_ptr<DataShareResultSet> &resultSet)
364 {
365 int count = 0;
366 auto ret = resultSet->GetRowCount(count);
367 if (ret != NativeRdb::E_OK) {
368 MEDIA_ERR_LOG("Failed to get resultset row count, ret: %{public}d", ret);
369 return ret;
370 }
371 if (count <= 0) {
372 MEDIA_ERR_LOG("Failed to get count, count: %{public}d", count);
373 return E_FAIL;
374 }
375 ret = resultSet->GoToFirstRow();
376 if (ret != NativeRdb::E_OK) {
377 MEDIA_ERR_LOG("Failed to go to first row, ret: %{public}d", ret);
378 return ret;
379 }
380 return E_SUCCESS;
381 }
382
383
GetFilePathFromUri(const Uri & fileUri,string & filePath,string userId)384 int32_t MediaLibraryManager::GetFilePathFromUri(const Uri &fileUri, string &filePath, string userId)
385 {
386 string uri = fileUri.ToString();
387 MediaFileUri virtualUri(uri);
388 if (!virtualUri.IsValid()) {
389 return E_URI_INVALID;
390 }
391 string virtualId = virtualUri.GetFileId();
392 #ifdef MEDIALIBRARY_COMPATIBILITY
393 if (MediaFileUtils::GetTableFromVirtualUri(uri) != MEDIALIBRARY_TABLE) {
394 MEDIA_INFO_LOG("uri:%{private}s does not match Files Table", uri.c_str());
395 return E_URI_INVALID;
396 }
397 #endif
398 vector<string> columns = { MEDIA_DATA_DB_FILE_PATH };
399 auto resultSet = MediaLibraryManager::GetResultSetFromDb(MEDIA_DATA_DB_ID, virtualId, columns);
400 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_INVALID_URI,
401 "GetFilePathFromUri::uri is not correct: %{private}s", uri.c_str());
402 if (CheckResultSet(resultSet) != E_SUCCESS) {
403 return E_FAIL;
404 }
405
406 std::string tempPath = ResultSetUtils::GetStringValFromColumn(1, resultSet);
407 if (tempPath.find(ROOT_MEDIA_DIR) != 0) {
408 return E_CHECK_ROOT_DIR_FAIL;
409 }
410 string relativePath = tempPath.substr((ROOT_MEDIA_DIR + DOCS_PATH).length());
411 auto pos = relativePath.find('/');
412 if (pos == string::npos) {
413 return E_INVALID_ARGUMENTS;
414 }
415 relativePath = relativePath.substr(0, pos + 1);
416 if ((relativePath != DOC_DIR_VALUES) && (relativePath != DOWNLOAD_DIR_VALUES)) {
417 return E_DIR_CHECK_DIR_FAIL;
418 }
419
420 string prePath = PRE_PATH_VALUES;
421 string postpath = tempPath.substr(prePath.length());
422 tempPath = prePath + userId + "/" + postpath;
423 filePath = tempPath;
424 return E_SUCCESS;
425 }
426
GetUriFromFilePath(const string & filePath,Uri & fileUri,string & userId)427 int32_t MediaLibraryManager::GetUriFromFilePath(const string &filePath, Uri &fileUri, string &userId)
428 {
429 if (filePath.empty()) {
430 return E_INVALID_PATH;
431 }
432
433 string tempPath;
434 SolvePath(filePath, tempPath, userId);
435 if (tempPath.find(ROOT_MEDIA_DIR) != 0) {
436 return E_CHECK_ROOT_DIR_FAIL;
437 }
438 string relativePath = tempPath.substr((ROOT_MEDIA_DIR + DOCS_PATH).length());
439 auto pos = relativePath.find('/');
440 if (pos == string::npos) {
441 return E_INVALID_ARGUMENTS;
442 }
443 relativePath = relativePath.substr(0, pos + 1);
444 if ((relativePath != DOC_DIR_VALUES) && (relativePath != DOWNLOAD_DIR_VALUES)) {
445 return E_DIR_CHECK_DIR_FAIL;
446 }
447
448 vector<string> columns = { MEDIA_DATA_DB_ID};
449 auto resultSet = MediaLibraryManager::GetResultSetFromDb(MEDIA_DATA_DB_FILE_PATH, tempPath, columns);
450 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_INVALID_URI,
451 "GetUriFromFilePath::tempPath is not correct: %{private}s", tempPath.c_str());
452 if (CheckResultSet(resultSet) != E_SUCCESS) {
453 return E_FAIL;
454 }
455
456 int32_t fileId = ResultSetUtils::GetIntValFromColumn(0, resultSet);
457 #ifdef MEDIALIBRARY_COMPATIBILITY
458 int64_t virtualId = MediaFileUtils::GetVirtualIdByType(fileId, MediaType::MEDIA_TYPE_FILE);
459 fileUri = MediaFileUri(MediaType::MEDIA_TYPE_FILE, to_string(virtualId), "", MEDIA_API_VERSION_V9);
460 #else
461 fileUri = MediaFileUri(MediaType::MEDIA_TYPE_FILE, to_string(fileId), "", MEDIA_API_VERSION_V9);
462 #endif
463 return E_SUCCESS;
464 }
465
GetSandboxPath(const std::string & path,const Size & size,bool isAstc)466 static std::string GetSandboxPath(const std::string &path, const Size &size, bool isAstc)
467 {
468 if (path.length() < ROOT_MEDIA_DIR.length()) {
469 return "";
470 }
471 int min = std::min(size.width, size.height);
472 int max = std::max(size.width, size.height);
473 std::string suffixStr = path.substr(ROOT_MEDIA_DIR.length()) + "/";
474 if (min == DEFAULT_ORIGINAL && max == DEFAULT_ORIGINAL) {
475 suffixStr += "LCD.jpg";
476 } else if (min <= DEFAULT_THUMBNAIL_SIZE && max <= MAX_DEFAULT_THUMBNAIL_SIZE) {
477 suffixStr += isAstc ? "THM_ASTC.astc" : "THM.jpg";
478 } else {
479 suffixStr += "LCD.jpg";
480 }
481
482 return ROOT_SANDBOX_DIR + ".thumbs/" + suffixStr;
483 }
484
GetFdFromSandbox(const string & path,string & sandboxPath,bool isAstc)485 static int32_t GetFdFromSandbox(const string &path, string &sandboxPath, bool isAstc)
486 {
487 int32_t fd = -1;
488 if (sandboxPath.empty()) {
489 MEDIA_ERR_LOG("OpenThumbnail sandboxPath is empty, path :%{public}s",
490 MediaFileUtils::DesensitizePath(path).c_str());
491 return fd;
492 }
493 string absFilePath;
494 if (PathToRealPath(sandboxPath, absFilePath)) {
495 return open(absFilePath.c_str(), O_RDONLY);
496 }
497 if (!isAstc) {
498 return fd;
499 }
500 string suffixStr = "THM_ASTC.astc";
501 size_t thmIdx = sandboxPath.find(suffixStr);
502 if (thmIdx == std::string::npos) {
503 return fd;
504 }
505 sandboxPath.replace(thmIdx, suffixStr.length(), "THM.jpg");
506 if (!PathToRealPath(sandboxPath, absFilePath)) {
507 return fd;
508 }
509 return open(absFilePath.c_str(), O_RDONLY);
510 }
511
OpenThumbnail(string & uriStr,const string & path,const Size & size,bool isAstc)512 int MediaLibraryManager::OpenThumbnail(string &uriStr, const string &path, const Size &size, bool isAstc)
513 {
514 // To ensure performance.
515 if (sDataShareHelper_ == nullptr) {
516 MEDIA_ERR_LOG("Failed to open thumbnail, sDataShareHelper_ is nullptr");
517 return E_ERR;
518 }
519 if (path.empty()) {
520 MEDIA_ERR_LOG("OpenThumbnail path is empty");
521 Uri openUri(uriStr);
522 return sDataShareHelper_->OpenFile(openUri, "R");
523 }
524 string sandboxPath = GetSandboxPath(path, size, isAstc);
525 int32_t fd = GetFdFromSandbox(path, sandboxPath, isAstc);
526 if (fd > 0) {
527 return fd;
528 }
529 MEDIA_INFO_LOG("OpenThumbnail from andboxPath failed, errno %{public}d path :%{public}s fd %{public}d",
530 errno, MediaFileUtils::DesensitizePath(path).c_str(), fd);
531 if (IsAsciiString(path)) {
532 uriStr += "&" + THUMBNAIL_PATH + "=" + path;
533 }
534 Uri openUri(uriStr);
535 return sDataShareHelper_->OpenFile(openUri, "R");
536 }
537
538 /**
539 * Get the file uri prefix with id
540 * eg. Input: file://media/Photo/10/IMG_xxx/01.jpg
541 * Output: file://media/Photo/10
542 */
GetUriIdPrefix(std::string & fileUri)543 static void GetUriIdPrefix(std::string &fileUri)
544 {
545 MediaFileUri mediaUri(fileUri);
546 if (!mediaUri.IsApi10()) {
547 return;
548 }
549 auto slashIdx = fileUri.rfind('/');
550 if (slashIdx == std::string::npos) {
551 return;
552 }
553 auto tmpUri = fileUri.substr(0, slashIdx);
554 slashIdx = tmpUri.rfind('/');
555 if (slashIdx == std::string::npos) {
556 return;
557 }
558 fileUri = tmpUri.substr(0, slashIdx);
559 }
560
GetUriParamsFromQueryKey(UriParams & uriParams,std::unordered_map<std::string,std::string> & queryKey)561 static void GetUriParamsFromQueryKey(UriParams& uriParams,
562 std::unordered_map<std::string, std::string>& queryKey)
563 {
564 if (queryKey.count(THUMBNAIL_PATH) != 0) {
565 uriParams.path = queryKey[THUMBNAIL_PATH];
566 }
567 if (queryKey.count(THUMBNAIL_WIDTH) != 0) {
568 uriParams.size.width = stoi(queryKey[THUMBNAIL_WIDTH]);
569 }
570 if (queryKey.count(THUMBNAIL_HEIGHT) != 0) {
571 uriParams.size.height = stoi(queryKey[THUMBNAIL_HEIGHT]);
572 }
573 if (queryKey.count(THUMBNAIL_OPER) != 0) {
574 uriParams.isAstc = queryKey[THUMBNAIL_OPER] == MEDIA_DATA_DB_THUMB_ASTC;
575 }
576 uriParams.dynamicRange = DecodeDynamicRange::AUTO;
577 if (queryKey.count(DYNAMIC_RANGE) != 0) {
578 uriParams.dynamicRange = static_cast<DecodeDynamicRange>(stoi(queryKey[DYNAMIC_RANGE]));
579 }
580 }
581
GetParamsFromUri(const string & uri,const bool isOldVer,UriParams & uriParams)582 static bool GetParamsFromUri(const string &uri, const bool isOldVer, UriParams &uriParams)
583 {
584 MediaFileUri mediaUri(uri);
585 if (!mediaUri.IsValid()) {
586 return false;
587 }
588 if (isOldVer) {
589 auto index = uri.find("thumbnail");
590 if (index == string::npos) {
591 return false;
592 }
593 uriParams.fileUri = uri.substr(0, index - 1);
594 GetUriIdPrefix(uriParams.fileUri);
595 index += strlen("thumbnail");
596 index = uri.find('/', index);
597 if (index == string::npos) {
598 return false;
599 }
600 index += 1;
601 auto tmpIdx = uri.find('/', index);
602 if (tmpIdx == string::npos) {
603 return false;
604 }
605
606 int32_t width = 0;
607 StrToInt(uri.substr(index, tmpIdx - index), width);
608 int32_t height = 0;
609 StrToInt(uri.substr(tmpIdx + 1), height);
610 uriParams.size = { .width = width, .height = height };
611 } else {
612 auto qIdx = uri.find('?');
613 if (qIdx == string::npos) {
614 return false;
615 }
616 uriParams.fileUri = uri.substr(0, qIdx);
617 GetUriIdPrefix(uriParams.fileUri);
618 auto &queryKey = mediaUri.GetQueryKeys();
619 GetUriParamsFromQueryKey(uriParams, queryKey);
620 }
621 return true;
622 }
623
IfSizeEqualsRatio(const Size & imageSize,const Size & targetSize)624 static bool IfSizeEqualsRatio(const Size &imageSize, const Size &targetSize)
625 {
626 if (imageSize.height <= 0 || targetSize.height <= 0) {
627 return false;
628 }
629
630 float imageSizeScale = static_cast<float>(imageSize.width) / static_cast<float>(imageSize.height);
631 float targetSizeScale = static_cast<float>(targetSize.width) / static_cast<float>(targetSize.height);
632 if (imageSizeScale - targetSizeScale > FLOAT_EPSILON || targetSizeScale - imageSizeScale > FLOAT_EPSILON) {
633 return false;
634 } else {
635 return true;
636 }
637 }
638
DecodeThumbnail(UniqueFd & uniqueFd,const Size & size,DecodeDynamicRange dynamicRange)639 unique_ptr<PixelMap> MediaLibraryManager::DecodeThumbnail(UniqueFd& uniqueFd, const Size& size,
640 DecodeDynamicRange dynamicRange)
641 {
642 MediaLibraryTracer tracer;
643 tracer.Start("ImageSource::CreateImageSource");
644 SourceOptions opts;
645 uint32_t err = 0;
646 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
647 if (imageSource == nullptr) {
648 MEDIA_ERR_LOG("CreateImageSource err %{public}d", err);
649 return nullptr;
650 }
651
652 ImageInfo imageInfo;
653 err = imageSource->GetImageInfo(0, imageInfo);
654 if (err != E_OK) {
655 MEDIA_ERR_LOG("GetImageInfo err %{public}d", err);
656 return nullptr;
657 }
658
659 bool isEqualsRatio = IfSizeEqualsRatio(imageInfo.size, size);
660 DecodeOptions decodeOpts;
661 decodeOpts.desiredSize = isEqualsRatio ? size : imageInfo.size;
662 decodeOpts.desiredDynamicRange = dynamicRange;
663 unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
664 if (pixelMap == nullptr) {
665 MEDIA_ERR_LOG("CreatePixelMap err %{public}d", err);
666 return nullptr;
667 }
668
669 PostProc postProc;
670 if (size.width != 0 && size.width != DEFAULT_ORIGINAL && !isEqualsRatio && !postProc.CenterScale(size, *pixelMap)) {
671 MEDIA_ERR_LOG("CenterScale failed, size: %{public}d * %{public}d, imageInfo size: %{public}d * %{public}d",
672 size.width, size.height, imageInfo.size.width, imageInfo.size.height);
673 return nullptr;
674 }
675
676 // Make the ashmem of pixelmap to be purgeable after the operation on ashmem.
677 // And then make the pixelmap subject to PurgeableManager's control.
678 #ifdef IMAGE_PURGEABLE_PIXELMAP
679 PurgeableBuilder::MakePixelMapToBePurgeable(pixelMap, imageSource, decodeOpts, size);
680 #endif
681 return pixelMap;
682 }
683
QueryThumbnail(UriParams & params)684 unique_ptr<PixelMap> MediaLibraryManager::QueryThumbnail(UriParams& params)
685 {
686 MediaLibraryTracer tracer;
687 tracer.Start("QueryThumbnail uri:" + params.fileUri);
688
689 string oper = params.isAstc ? MEDIA_DATA_DB_THUMB_ASTC : MEDIA_DATA_DB_THUMBNAIL;
690 string openUriStr = params.fileUri + "?" + MEDIA_OPERN_KEYWORD + "=" + oper + "&" + MEDIA_DATA_DB_WIDTH +
691 "=" + to_string(params.size.width) + "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(params.size.height);
692 tracer.Start("DataShare::OpenThumbnail");
693 UniqueFd uniqueFd(MediaLibraryManager::OpenThumbnail(openUriStr, params.path, params.size, params.isAstc));
694 if (uniqueFd.Get() < 0) {
695 MEDIA_ERR_LOG("queryThumb is null, errCode is %{public}d", uniqueFd.Get());
696 return nullptr;
697 }
698 tracer.Finish();
699 return DecodeThumbnail(uniqueFd, params.size, params.dynamicRange);
700 }
701
GetThumbnail(const Uri & uri)702 std::unique_ptr<PixelMap> MediaLibraryManager::GetThumbnail(const Uri &uri)
703 {
704 // uri is dataability:///media/image/<id>/thumbnail/<width>/<height>
705 string uriStr = uri.ToString();
706 auto thumbLatIdx = uriStr.find("thumbnail");
707 bool isAstc = false;
708 if (thumbLatIdx == string::npos || thumbLatIdx > uriStr.length()) {
709 thumbLatIdx = uriStr.find("astc");
710 if (thumbLatIdx == string::npos || thumbLatIdx > uriStr.length()) {
711 MEDIA_ERR_LOG("GetThumbnail failed, oper is invalid");
712 return nullptr;
713 }
714 isAstc = true;
715 }
716 thumbLatIdx += isAstc ? strlen("astc") : strlen("thumbnail");
717 bool isOldVersion = uriStr[thumbLatIdx] == '/';
718 UriParams uriParams;
719 if (!GetParamsFromUri(uriStr, isOldVersion, uriParams)) {
720 MEDIA_ERR_LOG("GetThumbnail failed, get params from uri failed, uri :%{public}s", uriStr.c_str());
721 return nullptr;
722 }
723 auto pixelmap = QueryThumbnail(uriParams);
724 if (pixelmap == nullptr) {
725 MEDIA_ERR_LOG("pixelmap is null, uri :%{public}s, path :%{public}s",
726 uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
727 }
728 return pixelmap;
729 }
730
GetAstcsByOffset(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)731 static int32_t GetAstcsByOffset(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
732 {
733 UriParams uriParams;
734 if (!GetParamsFromUri(uriBatch.at(0), false, uriParams)) {
735 MEDIA_ERR_LOG("GetParamsFromUri failed in GetAstcsByOffset");
736 return E_INVALID_URI;
737 }
738 vector<string> timeIdBatch;
739 int32_t start = 0;
740 int32_t count = 0;
741 MediaFileUri::GetTimeIdFromUri(uriBatch, timeIdBatch, start, count);
742 CHECK_AND_RETURN_RET_LOG(!timeIdBatch.empty(), E_INVALID_URI, "GetTimeIdFromUri failed");
743 MEDIA_INFO_LOG("GetAstcsByOffset image batch size: %{public}zu, begin: %{public}s, end: %{public}s,"
744 "start: %{public}d, count: %{public}d", uriBatch.size(), timeIdBatch.back().c_str(),
745 timeIdBatch.front().c_str(), start, count);
746
747 KvStoreValueType valueType;
748 if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
749 valueType = KvStoreValueType::MONTH_ASTC;
750 } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
751 uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
752 valueType = KvStoreValueType::YEAR_ASTC;
753 } else {
754 MEDIA_ERR_LOG("GetAstcsByOffset invalid image size");
755 return E_INVALID_URI;
756 }
757
758 vector<string> newTimeIdBatch;
759 MediaAssetRdbStore::GetInstance()->QueryTimeIdBatch(start, count, newTimeIdBatch);
760 auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
761 if (kvStore == nullptr) {
762 MEDIA_ERR_LOG("GetAstcsByOffset kvStore is nullptr");
763 return E_DB_FAIL;
764 }
765 int32_t status = kvStore->BatchQuery(newTimeIdBatch, astcBatch);
766 if (status != E_OK) {
767 MEDIA_ERR_LOG("GetAstcsByOffset failed, status %{public}d", status);
768 return status;
769 }
770 return E_OK;
771 }
772
GetAstcsBatch(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)773 static int32_t GetAstcsBatch(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
774 {
775 UriParams uriParams;
776 if (!GetParamsFromUri(uriBatch.at(0), false, uriParams)) {
777 MEDIA_ERR_LOG("GetParamsFromUri failed in GetAstcsBatch");
778 return E_INVALID_URI;
779 }
780 vector<string> timeIdBatch;
781 MediaFileUri::GetTimeIdFromUri(uriBatch, timeIdBatch);
782 CHECK_AND_RETURN_RET_LOG(!timeIdBatch.empty(), E_INVALID_URI, "GetTimeIdFromUri failed");
783 MEDIA_INFO_LOG("GetAstcsBatch image batch size: %{public}zu, begin: %{public}s, end: %{public}s",
784 uriBatch.size(), timeIdBatch.back().c_str(), timeIdBatch.front().c_str());
785
786 KvStoreValueType valueType;
787 if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
788 valueType = KvStoreValueType::MONTH_ASTC;
789 } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
790 uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
791 valueType = KvStoreValueType::YEAR_ASTC;
792 } else {
793 MEDIA_ERR_LOG("GetAstcsBatch invalid image size");
794 return E_INVALID_URI;
795 }
796
797 auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
798 if (kvStore == nullptr) {
799 MEDIA_ERR_LOG("GetAstcsBatch kvStore is nullptr");
800 return E_DB_FAIL;
801 }
802 int32_t status = kvStore->BatchQuery(timeIdBatch, astcBatch);
803 if (status != E_OK) {
804 MEDIA_ERR_LOG("GetAstcsBatch failed, status %{public}d", status);
805 return status;
806 }
807 return E_OK;
808 }
809
GetBatchAstcs(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)810 int32_t MediaLibraryManager::GetBatchAstcs(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
811 {
812 if (uriBatch.empty()) {
813 MEDIA_INFO_LOG("GetBatchAstcs uriBatch is empty");
814 return E_INVALID_URI;
815 }
816 if (uriBatch.at(0).find(ML_URI_OFFSET) != std::string::npos) {
817 return GetAstcsByOffset(uriBatch, astcBatch);
818 } else {
819 return GetAstcsBatch(uriBatch, astcBatch);
820 }
821 }
822
DecodeAstc(UniqueFd & uniqueFd)823 unique_ptr<PixelMap> MediaLibraryManager::DecodeAstc(UniqueFd &uniqueFd)
824 {
825 if (uniqueFd.Get() < 0) {
826 MEDIA_ERR_LOG("Fd is invalid, errCode is %{public}d", uniqueFd.Get());
827 return nullptr;
828 }
829 MediaLibraryTracer tracer;
830 tracer.Start("MediaLibraryManager::DecodeAstc");
831 SourceOptions opts;
832 uint32_t err = 0;
833 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
834 if (imageSource == nullptr) {
835 MEDIA_ERR_LOG("CreateImageSource err %{public}d", err);
836 return nullptr;
837 }
838
839 DecodeOptions decodeOpts;
840 decodeOpts.fastAstc = true;
841 decodeOpts.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
842 unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
843 if (pixelMap == nullptr) {
844 MEDIA_ERR_LOG("CreatePixelMap err %{public}d", err);
845 return nullptr;
846 }
847 return pixelMap;
848 }
849
GetAstc(const Uri & uri)850 std::unique_ptr<PixelMap> MediaLibraryManager::GetAstc(const Uri &uri)
851 {
852 // uri is file://media/image/<id>&oper=astc&width=<width>&height=<height>&path=<path>
853 MediaLibraryTracer tracer;
854 string uriStr = uri.ToString();
855 if (uriStr.empty()) {
856 MEDIA_ERR_LOG("GetAstc failed, uri is empty");
857 return nullptr;
858 }
859 auto astcIndex = uriStr.find("astc");
860 if (astcIndex == string::npos || astcIndex > uriStr.length()) {
861 MEDIA_ERR_LOG("GetAstc failed, oper is invalid");
862 return nullptr;
863 }
864 UriParams uriParams;
865 if (!GetParamsFromUri(uriStr, false, uriParams)) {
866 MEDIA_ERR_LOG("GetAstc failed, get params from uri failed, uri :%{public}s", uriStr.c_str());
867 return nullptr;
868 }
869 tracer.Start("GetAstc uri:" + uriParams.fileUri);
870 string openUriStr = uriParams.fileUri + "?" + MEDIA_OPERN_KEYWORD + "=" +
871 MEDIA_DATA_DB_THUMB_ASTC + "&" + MEDIA_DATA_DB_WIDTH + "=" + to_string(uriParams.size.width) +
872 "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(uriParams.size.height);
873 tracer.Start("MediaLibraryManager::OpenThumbnail");
874 UniqueFd uniqueFd(MediaLibraryManager::OpenThumbnail(openUriStr, uriParams.path, uriParams.size, true));
875 if (uniqueFd.Get() < 0) {
876 MEDIA_ERR_LOG("OpenThumbnail failed, errCode is %{public}d, uri :%{public}s, path :%{public}s",
877 uniqueFd.Get(), uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
878 return nullptr;
879 }
880 tracer.Finish();
881 auto pixelmap = DecodeAstc(uniqueFd);
882 if (pixelmap == nullptr) {
883 MEDIA_ERR_LOG("pixelmap is null, uri :%{public}s, path :%{public}s",
884 uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
885 }
886 return pixelmap;
887 }
888
OpenReadOnlyAppSandboxVideo(const string & uri)889 static int32_t OpenReadOnlyAppSandboxVideo(const string& uri)
890 {
891 std::vector<std::string> uris;
892 if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
893 return -1;
894 }
895 AppFileService::ModuleFileUri::FileUri fileUri(uris[MOVING_PHOTO_VIDEO_POS]);
896 std::string realPath = fileUri.GetRealPath();
897 int32_t fd = open(realPath.c_str(), O_RDONLY);
898 if (fd < 0) {
899 MEDIA_ERR_LOG("Failed to open read only video file, errno: %{public}d", errno);
900 return -1;
901 }
902 return fd;
903 }
904
ReadMovingPhotoVideo(const string & uri)905 int32_t MediaLibraryManager::ReadMovingPhotoVideo(const string &uri)
906 {
907 if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
908 return OpenReadOnlyAppSandboxVideo(uri);
909 }
910 if (!CheckPhotoUri(uri)) {
911 MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
912 return E_ERR;
913 }
914
915 if (sDataShareHelper_ == nullptr) {
916 MEDIA_ERR_LOG("Failed to read video of moving photo, datashareHelper is nullptr");
917 return E_ERR;
918 }
919
920 string videoUri = uri;
921 MediaFileUtils::UriAppendKeyValue(videoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_MOVING_PHOTO_VIDEO);
922 Uri openVideoUri(videoUri);
923 return sDataShareHelper_->OpenFile(openVideoUri, MEDIA_FILEMODE_READONLY);
924 }
925
ReadPrivateMovingPhoto(const string & uri)926 int32_t MediaLibraryManager::ReadPrivateMovingPhoto(const string &uri)
927 {
928 if (!CheckPhotoUri(uri)) {
929 MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
930 return E_ERR;
931 }
932
933 if (sDataShareHelper_ == nullptr) {
934 MEDIA_ERR_LOG("Failed to read video of moving photo, datashareHelper is nullptr");
935 return E_ERR;
936 }
937
938 string movingPhotoUri = uri;
939 MediaFileUtils::UriAppendKeyValue(movingPhotoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_PRIVATE_LIVE_PHOTO);
940 Uri openMovingPhotoUri(movingPhotoUri);
941 return sDataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
942 }
943
GetMovingPhotoImageUri(const string & uri)944 std::string MediaLibraryManager::GetMovingPhotoImageUri(const string &uri)
945 {
946 if (uri.empty()) {
947 MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
948 return "";
949 }
950 if (MediaFileUtils::IsMediaLibraryUri(uri)) {
951 return uri;
952 }
953 std::vector<std::string> uris;
954 if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
955 return "";
956 }
957 return uris[MOVING_PHOTO_IMAGE_POS];
958 }
959
GetSandboxMovingPhotoTime(const string & uri)960 static int64_t GetSandboxMovingPhotoTime(const string& uri)
961 {
962 vector<string> uris;
963 if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
964 return E_ERR;
965 }
966
967 AppFileService::ModuleFileUri::FileUri imageFileUri(uris[MOVING_PHOTO_IMAGE_POS]);
968 string imageRealPath = imageFileUri.GetRealPath();
969 struct stat imageStatInfo {};
970 if (stat(imageRealPath.c_str(), &imageStatInfo) != 0) {
971 MEDIA_ERR_LOG("stat image error");
972 return E_ERR;
973 }
974 int64_t imageDateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(imageStatInfo.st_mtim));
975
976 AppFileService::ModuleFileUri::FileUri videoFileUri(uris[MOVING_PHOTO_VIDEO_POS]);
977 string videoRealPath = videoFileUri.GetRealPath();
978 struct stat videoStatInfo {};
979 if (stat(videoRealPath.c_str(), &videoStatInfo) != 0) {
980 MEDIA_ERR_LOG("stat video error");
981 return E_ERR;
982 }
983 int64_t videoDateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(videoStatInfo.st_mtim));
984 return imageDateModified >= videoDateModified ? imageDateModified : videoDateModified;
985 }
986
GetMovingPhotoDateModified(const string & uri)987 int64_t MediaLibraryManager::GetMovingPhotoDateModified(const string &uri)
988 {
989 if (uri.empty()) {
990 MEDIA_ERR_LOG("Failed to check empty uri");
991 return E_ERR;
992 }
993 if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
994 return GetSandboxMovingPhotoTime(uri);
995 }
996
997 if (!CheckPhotoUri(uri)) {
998 MEDIA_ERR_LOG("Failed to check invalid uri: %{public}s", uri.c_str());
999 return E_ERR;
1000 }
1001 Uri queryUri(PAH_QUERY_PHOTO);
1002 DataSharePredicates predicates;
1003 string fileId = MediaFileUtils::GetIdFromUri(uri);
1004 predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1005 DatashareBusinessError businessError;
1006 if (sDataShareHelper_ == nullptr) {
1007 MEDIA_ERR_LOG("sDataShareHelper_ is null");
1008 return E_ERR;
1009 }
1010 vector<string> columns = {
1011 MediaColumn::MEDIA_DATE_MODIFIED,
1012 };
1013 auto queryResultSet = sDataShareHelper_->Query(queryUri, predicates, columns, &businessError);
1014 if (queryResultSet == nullptr) {
1015 MEDIA_ERR_LOG("queryResultSet is null");
1016 return E_ERR;
1017 }
1018 if (queryResultSet->GoToNextRow() != NativeRdb::E_OK) {
1019 MEDIA_ERR_LOG("Failed to GoToNextRow");
1020 return E_ERR;
1021 }
1022 return GetInt64Val(MediaColumn::MEDIA_DATE_MODIFIED, queryResultSet);
1023 }
1024
UrisSourceMediaTypeClassify(const vector<string> & urisSource,vector<string> & photoFileIds,vector<string> & audioFileIds)1025 static int32_t UrisSourceMediaTypeClassify(const vector<string> &urisSource,
1026 vector<string> &photoFileIds, vector<string> &audioFileIds)
1027 {
1028 for (const auto &uri : urisSource) {
1029 int32_t tableType = -1;
1030 for (const auto &iter : tableMap) {
1031 if (uri.find(iter.first) != string::npos) {
1032 tableType = static_cast<int32_t>(iter.second);
1033 }
1034 }
1035 if (tableType == -1) {
1036 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
1037 return E_ERR;
1038 }
1039 string fileId = MediaFileUtils::GetIdFromUri(uri);
1040 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
1041 photoFileIds.emplace_back(fileId);
1042 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
1043 audioFileIds.emplace_back(fileId);
1044 } else {
1045 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
1046 return E_ERR;
1047 }
1048 }
1049 return E_SUCCESS;
1050 }
1051
CheckAccessTokenPermissionExecute(uint32_t tokenId,uint32_t checkFlag,TableType mediaType,bool & isReadable,bool & isWritable)1052 static void CheckAccessTokenPermissionExecute(uint32_t tokenId, uint32_t checkFlag, TableType mediaType,
1053 bool &isReadable, bool &isWritable)
1054 {
1055 static map<TableType, string> readPermmisionMap = {
1056 { TableType::TYPE_PHOTOS, PERM_READ_IMAGEVIDEO },
1057 { TableType::TYPE_AUDIOS, PERM_READ_AUDIO }
1058 };
1059 static map<TableType, string> writePermmisionMap = {
1060 { TableType::TYPE_PHOTOS, PERM_WRITE_IMAGEVIDEO },
1061 { TableType::TYPE_AUDIOS, PERM_WRITE_AUDIO }
1062 };
1063 int checkReadResult = -1;
1064 int checkWriteResult = -1;
1065 if (checkFlag == URI_PERMISSION_FLAG_READ) {
1066 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, readPermmisionMap[mediaType]);
1067 if (checkReadResult != PermissionState::PERMISSION_GRANTED) {
1068 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1069 }
1070 } else if (checkFlag == URI_PERMISSION_FLAG_WRITE) {
1071 checkWriteResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1072 } else if (checkFlag == URI_PERMISSION_FLAG_READWRITE) {
1073 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, readPermmisionMap[mediaType]);
1074 if (checkReadResult != PermissionState::PERMISSION_GRANTED) {
1075 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1076 }
1077 checkWriteResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1078 }
1079 isReadable = checkReadResult == PermissionState::PERMISSION_GRANTED;
1080 isWritable = checkWriteResult == PermissionState::PERMISSION_GRANTED;
1081 }
CheckAccessTokenPermission(uint32_t tokenId,uint32_t checkFlag,TableType mediaType,int32_t & queryFlag)1082 static void CheckAccessTokenPermission(uint32_t tokenId, uint32_t checkFlag,
1083 TableType mediaType, int32_t &queryFlag)
1084 {
1085 bool isReadable = FALSE;
1086 bool isWritable = FALSE;
1087 CheckAccessTokenPermissionExecute(tokenId, checkFlag, mediaType, isReadable, isWritable);
1088
1089 if (checkFlag == URI_PERMISSION_FLAG_READ) {
1090 queryFlag = isReadable ? -1 : URI_PERMISSION_FLAG_READ;
1091 } else if (checkFlag == URI_PERMISSION_FLAG_WRITE) {
1092 queryFlag = isWritable ? -1 : URI_PERMISSION_FLAG_WRITE;
1093 } else if (checkFlag == URI_PERMISSION_FLAG_READWRITE) {
1094 if (isReadable && isWritable) {
1095 queryFlag = -1;
1096 } else if (isReadable) {
1097 queryFlag = URI_PERMISSION_FLAG_WRITE;
1098 } else if (isWritable) {
1099 queryFlag = URI_PERMISSION_FLAG_READ;
1100 } else {
1101 queryFlag = URI_PERMISSION_FLAG_READWRITE;
1102 }
1103 }
1104 }
1105
MakePredicatesForCheckPhotoUriPermission(int32_t & checkFlag,DataSharePredicates & predicates,const string & appid,TableType mediaType,vector<string> & fileIds)1106 static void MakePredicatesForCheckPhotoUriPermission(int32_t &checkFlag, DataSharePredicates &predicates,
1107 const string &appid, TableType mediaType, vector<string> &fileIds)
1108 {
1109 predicates.EqualTo(AppUriPermissionColumn::APP_ID, appid);
1110 predicates.And()->EqualTo(AppUriPermissionColumn::URI_TYPE, to_string(static_cast<int32_t>(mediaType)));
1111 predicates.And()->In(AppUriPermissionColumn::FILE_ID, fileIds);
1112 vector<string> permissionTypes;
1113 switch (checkFlag) {
1114 case URI_PERMISSION_FLAG_READ:
1115 permissionTypes.emplace_back(
1116 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
1117 permissionTypes.emplace_back(
1118 to_string(static_cast<int32_t>(PhotoPermissionType::PERSIST_READ_IMAGEVIDEO)));
1119 permissionTypes.emplace_back(
1120 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
1121 permissionTypes.emplace_back(
1122 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
1123 break;
1124 case URI_PERMISSION_FLAG_WRITE:
1125 permissionTypes.emplace_back(
1126 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
1127 permissionTypes.emplace_back(
1128 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
1129 permissionTypes.emplace_back(
1130 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
1131 break;
1132 case URI_PERMISSION_FLAG_READWRITE:
1133 permissionTypes.emplace_back(
1134 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
1135 permissionTypes.emplace_back(
1136 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
1137 break;
1138 default:
1139 MEDIA_ERR_LOG("error flag object: %{public}d", checkFlag);
1140 return;
1141 }
1142 predicates.And()->In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
1143 }
1144
CheckPhotoUriPermissionQueryOperation(const sptr<IRemoteObject> & token,const DataSharePredicates & predicates,map<string,int32_t> & resultMap)1145 static int32_t CheckPhotoUriPermissionQueryOperation(const sptr<IRemoteObject> &token,
1146 const DataSharePredicates &predicates, map<string, int32_t> &resultMap)
1147 {
1148 vector<string> columns = {
1149 AppUriPermissionColumn::FILE_ID,
1150 AppUriPermissionColumn::PERMISSION_TYPE
1151 };
1152 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1153 DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
1154 if (dataShareHelper == nullptr) {
1155 MEDIA_ERR_LOG("Failed to checkPhotoUriPermission, datashareHelper is nullptr");
1156 return E_ERR;
1157 }
1158
1159 Uri uri(MEDIALIBRARY_CHECK_URIPERM_URI);
1160 auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
1161 if (queryResultSet == nullptr) {
1162 MEDIA_ERR_LOG("queryResultSet is null!");
1163 return E_ERR;
1164 }
1165 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1166 string fileId = GetStringVal(AppUriPermissionColumn::FILE_ID, queryResultSet);
1167 int32_t permissionType = GetInt32Val(AppUriPermissionColumn::PERMISSION_TYPE, queryResultSet);
1168 resultMap[fileId] = permissionType;
1169 }
1170 return E_SUCCESS;
1171 }
1172
SetCheckPhotoUriPermissionResult(const vector<string> & urisSource,vector<bool> & results,const map<string,int32_t> & photoResultMap,const map<string,int32_t> & audioResultMap,int32_t queryPhotoFlag,int32_t queryAudioFlag)1173 static int32_t SetCheckPhotoUriPermissionResult(const vector<string> &urisSource, vector<bool> &results,
1174 const map<string, int32_t> &photoResultMap, const map<string, int32_t> &audioResultMap,
1175 int32_t queryPhotoFlag, int32_t queryAudioFlag)
1176 {
1177 results.clear();
1178 for (const auto &uri : urisSource) {
1179 int32_t tableType = -1;
1180 for (const auto &iter : tableMap) {
1181 if (uri.find(iter.first) != string::npos) {
1182 tableType = static_cast<int32_t>(iter.second);
1183 }
1184 }
1185 string fileId = MediaFileUtils::GetIdFromUri(uri);
1186 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
1187 if (queryPhotoFlag == -1 || photoResultMap.find(fileId) != photoResultMap.end()) {
1188 results.emplace_back(TRUE);
1189 } else {
1190 results.emplace_back(FALSE);
1191 }
1192 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
1193 if (queryAudioFlag == -1 || audioResultMap.find(fileId) != audioResultMap.end()) {
1194 results.emplace_back(TRUE);
1195 } else {
1196 results.emplace_back(FALSE);
1197 }
1198 }
1199 }
1200 return E_SUCCESS;
1201 }
1202
CheckInputParameters(const vector<string> & urisSource,uint32_t flag)1203 static int32_t CheckInputParameters(const vector<string> &urisSource, uint32_t flag)
1204 {
1205 if (urisSource.empty()) {
1206 MEDIA_ERR_LOG("Media Uri list is empty");
1207 return E_ERR;
1208 }
1209 if (urisSource.size() > URI_MAX_SIZE) {
1210 MEDIA_ERR_LOG("Uri list is exceed one Thousand, current list size: %{public}d", (int)urisSource.size());
1211 return E_ERR;
1212 }
1213 if (flag == 0 || flag > URI_PERMISSION_FLAG_READWRITE) {
1214 MEDIA_ERR_LOG("Flag is invalid, current flag is: %{public}d", flag);
1215 return E_ERR;
1216 }
1217 return E_SUCCESS;
1218 }
1219
CheckPhotoUriPermission(uint32_t tokenId,const string & appid,const vector<string> & urisSource,vector<bool> & results,uint32_t flag)1220 int32_t MediaLibraryManager::CheckPhotoUriPermission(uint32_t tokenId, const string &appid,
1221 const vector<string> &urisSource, vector<bool> &results, uint32_t flag)
1222 {
1223 auto ret = CheckInputParameters(urisSource, flag);
1224 if (ret != E_SUCCESS) {
1225 return E_ERR;
1226 }
1227 vector<string> photoFileIds;
1228 vector<string> audioFileIds;
1229 ret = UrisSourceMediaTypeClassify(urisSource, photoFileIds, audioFileIds);
1230 if (ret != E_SUCCESS) {
1231 return E_ERR;
1232 }
1233 int32_t queryPhotoFlag = URI_PERMISSION_FLAG_READWRITE;
1234 int32_t queryAudioFlag = URI_PERMISSION_FLAG_READWRITE;
1235 if (photoFileIds.empty()) {
1236 queryPhotoFlag = -1;
1237 } else {
1238 CheckAccessTokenPermission(tokenId, flag, TableType::TYPE_PHOTOS, queryPhotoFlag);
1239 }
1240 if (audioFileIds.empty()) {
1241 queryAudioFlag = -1;
1242 } else {
1243 CheckAccessTokenPermission(tokenId, flag, TableType::TYPE_AUDIOS, queryAudioFlag);
1244 }
1245 map<string, int32_t> photoResultMap;
1246 map<string, int32_t> audioResultMap;
1247 if (queryPhotoFlag != -1) {
1248 DataSharePredicates predicates;
1249 MakePredicatesForCheckPhotoUriPermission(queryPhotoFlag, predicates,
1250 appid, TableType::TYPE_PHOTOS, photoFileIds);
1251 auto ret = CheckPhotoUriPermissionQueryOperation(token_, predicates, photoResultMap);
1252 if (ret != E_SUCCESS) {
1253 return E_ERR;
1254 }
1255 }
1256 if (queryAudioFlag != -1) {
1257 DataSharePredicates predicates;
1258 MakePredicatesForCheckPhotoUriPermission(queryAudioFlag, predicates,
1259 appid, TableType::TYPE_AUDIOS, audioFileIds);
1260 auto ret = CheckPhotoUriPermissionQueryOperation(token_, predicates, audioResultMap);
1261 if (ret != E_SUCCESS) {
1262 return E_ERR;
1263 }
1264 }
1265 return SetCheckPhotoUriPermissionResult(urisSource, results, photoResultMap, audioResultMap,
1266 queryPhotoFlag, queryAudioFlag);
1267 }
1268
GrantPhotoUriPermission(const string & appid,const vector<string> & uris,PhotoPermissionType photoPermissionType,HideSensitiveType hideSensitiveTpye)1269 int32_t MediaLibraryManager::GrantPhotoUriPermission(const string &appid, const vector<string> &uris,
1270 PhotoPermissionType photoPermissionType, HideSensitiveType hideSensitiveTpye)
1271 {
1272 vector<DataShareValuesBucket> valueSet;
1273 if ((uris.empty()) || (uris.size() > URI_MAX_SIZE)) {
1274 MEDIA_ERR_LOG("Media Uri list error, please check!");
1275 return E_ERR;
1276 }
1277 if (photoPermissionType != PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO &&
1278 photoPermissionType != PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO &&
1279 photoPermissionType != PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO) {
1280 MEDIA_ERR_LOG("photoPermissionType error, please check param!");
1281 return E_ERR;
1282 }
1283 if (hideSensitiveTpye < HideSensitiveType::ALL_DESENSITIZE ||
1284 hideSensitiveTpye > HideSensitiveType::NO_DESENSITIZE) {
1285 MEDIA_ERR_LOG("HideSensitiveType error, please check param!");
1286 return E_ERR;
1287 }
1288 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1289 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1290 if (dataShareHelper == nullptr) {
1291 MEDIA_ERR_LOG("dataShareHelper is nullptr");
1292 return E_ERR;
1293 }
1294 for (const auto &uri : uris) {
1295 int32_t tableType = -1;
1296 for (const auto &iter : tableMap) {
1297 if (uri.find(iter.first) != string::npos) {
1298 tableType = static_cast<int32_t>(iter.second);
1299 }
1300 }
1301 if (tableType == -1) {
1302 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
1303 return E_ERR;
1304 }
1305 string fileId = MediaFileUtils::GetIdFromUri(uri);
1306 DataShareValuesBucket valuesBucket;
1307 valuesBucket.Put(AppUriPermissionColumn::APP_ID, appid);
1308 valuesBucket.Put(AppUriPermissionColumn::FILE_ID, fileId);
1309 valuesBucket.Put(AppUriPermissionColumn::URI_TYPE, tableType);
1310 valuesBucket.Put(AppUriPermissionColumn::PERMISSION_TYPE, static_cast<int32_t>(photoPermissionType));
1311 valuesBucket.Put(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, static_cast<int32_t>(hideSensitiveTpye));
1312 valueSet.push_back(valuesBucket);
1313 }
1314 Uri insertUri(MEDIALIBRARY_GRANT_URIPERM_URI);
1315 auto ret = dataShareHelper->BatchInsert(insertUri, valueSet);
1316 return ret;
1317 }
1318
CreatePhotoAssetProxy(CameraShotType cameraShotType,uint32_t callingUid,int32_t userId)1319 shared_ptr<PhotoAssetProxy> MediaLibraryManager::CreatePhotoAssetProxy(CameraShotType cameraShotType,
1320 uint32_t callingUid, int32_t userId)
1321 {
1322 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1323 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1324 shared_ptr<PhotoAssetProxy> photoAssetProxy = make_shared<PhotoAssetProxy>(dataShareHelper, cameraShotType,
1325 callingUid, userId);
1326 return photoAssetProxy;
1327 }
1328
GetUrisByOldUris(std::vector<std::string> uris)1329 std::unordered_map<std::string, std::string> MediaLibraryManager::GetUrisByOldUris(std::vector<std::string> uris)
1330 {
1331 MEDIA_INFO_LOG("Start request uris by old uris, size: %{public}zu", uris.size());
1332 return TabOldPhotosClient(*this).GetUrisByOldUris(uris);
1333 }
1334 } // namespace Media
1335 } // namespace OHOS
1336