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 MEDIA_INFO_LOG("GetAstcsByOffset image batch size: %{public}zu, begin: %{public}s, end: %{public}s,"
743 "start: %{public}d, count: %{public}d", uriBatch.size(), timeIdBatch.back().c_str(),
744 timeIdBatch.front().c_str(), start, count);
745
746 KvStoreValueType valueType;
747 if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
748 valueType = KvStoreValueType::MONTH_ASTC;
749 } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
750 uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
751 valueType = KvStoreValueType::YEAR_ASTC;
752 } else {
753 MEDIA_ERR_LOG("GetAstcsByOffset invalid image size");
754 return E_INVALID_URI;
755 }
756
757 vector<string> newTimeIdBatch;
758 MediaAssetRdbStore::GetInstance()->QueryTimeIdBatch(start, count, newTimeIdBatch);
759 auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
760 if (kvStore == nullptr) {
761 MEDIA_ERR_LOG("GetAstcsByOffset kvStore is nullptr");
762 return E_DB_FAIL;
763 }
764 int32_t status = kvStore->BatchQuery(newTimeIdBatch, astcBatch);
765 if (status != E_OK) {
766 MEDIA_ERR_LOG("GetAstcsByOffset failed, status %{public}d", status);
767 return status;
768 }
769 return E_OK;
770 }
771
GetAstcsBatch(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)772 static int32_t GetAstcsBatch(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
773 {
774 UriParams uriParams;
775 if (!GetParamsFromUri(uriBatch.at(0), false, uriParams)) {
776 MEDIA_ERR_LOG("GetParamsFromUri failed in GetAstcsBatch");
777 return E_INVALID_URI;
778 }
779 vector<string> timeIdBatch;
780 MediaFileUri::GetTimeIdFromUri(uriBatch, timeIdBatch);
781 MEDIA_INFO_LOG("GetAstcsBatch image batch size: %{public}zu, begin: %{public}s, end: %{public}s",
782 uriBatch.size(), timeIdBatch.back().c_str(), timeIdBatch.front().c_str());
783
784 KvStoreValueType valueType;
785 if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
786 valueType = KvStoreValueType::MONTH_ASTC;
787 } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
788 uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
789 valueType = KvStoreValueType::YEAR_ASTC;
790 } else {
791 MEDIA_ERR_LOG("GetAstcsBatch invalid image size");
792 return E_INVALID_URI;
793 }
794
795 auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
796 if (kvStore == nullptr) {
797 MEDIA_ERR_LOG("GetAstcsBatch kvStore is nullptr");
798 return E_DB_FAIL;
799 }
800 int32_t status = kvStore->BatchQuery(timeIdBatch, astcBatch);
801 if (status != E_OK) {
802 MEDIA_ERR_LOG("GetAstcsBatch failed, status %{public}d", status);
803 return status;
804 }
805 return E_OK;
806 }
807
GetBatchAstcs(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)808 int32_t MediaLibraryManager::GetBatchAstcs(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
809 {
810 if (uriBatch.empty()) {
811 MEDIA_INFO_LOG("GetBatchAstcs uriBatch is empty");
812 return E_INVALID_URI;
813 }
814 if (uriBatch.at(0).find(ML_URI_OFFSET) != std::string::npos) {
815 return GetAstcsByOffset(uriBatch, astcBatch);
816 } else {
817 return GetAstcsBatch(uriBatch, astcBatch);
818 }
819 }
820
DecodeAstc(UniqueFd & uniqueFd)821 unique_ptr<PixelMap> MediaLibraryManager::DecodeAstc(UniqueFd &uniqueFd)
822 {
823 if (uniqueFd.Get() < 0) {
824 MEDIA_ERR_LOG("Fd is invalid, errCode is %{public}d", uniqueFd.Get());
825 return nullptr;
826 }
827 MediaLibraryTracer tracer;
828 tracer.Start("MediaLibraryManager::DecodeAstc");
829 SourceOptions opts;
830 uint32_t err = 0;
831 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
832 if (imageSource == nullptr) {
833 MEDIA_ERR_LOG("CreateImageSource err %{public}d", err);
834 return nullptr;
835 }
836
837 DecodeOptions decodeOpts;
838 decodeOpts.fastAstc = true;
839 decodeOpts.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
840 unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
841 if (pixelMap == nullptr) {
842 MEDIA_ERR_LOG("CreatePixelMap err %{public}d", err);
843 return nullptr;
844 }
845 return pixelMap;
846 }
847
GetAstc(const Uri & uri)848 std::unique_ptr<PixelMap> MediaLibraryManager::GetAstc(const Uri &uri)
849 {
850 // uri is file://media/image/<id>&oper=astc&width=<width>&height=<height>&path=<path>
851 MediaLibraryTracer tracer;
852 string uriStr = uri.ToString();
853 if (uriStr.empty()) {
854 MEDIA_ERR_LOG("GetAstc failed, uri is empty");
855 return nullptr;
856 }
857 auto astcIndex = uriStr.find("astc");
858 if (astcIndex == string::npos || astcIndex > uriStr.length()) {
859 MEDIA_ERR_LOG("GetAstc failed, oper is invalid");
860 return nullptr;
861 }
862 UriParams uriParams;
863 if (!GetParamsFromUri(uriStr, false, uriParams)) {
864 MEDIA_ERR_LOG("GetAstc failed, get params from uri failed, uri :%{public}s", uriStr.c_str());
865 return nullptr;
866 }
867 tracer.Start("GetAstc uri:" + uriParams.fileUri);
868 string openUriStr = uriParams.fileUri + "?" + MEDIA_OPERN_KEYWORD + "=" +
869 MEDIA_DATA_DB_THUMB_ASTC + "&" + MEDIA_DATA_DB_WIDTH + "=" + to_string(uriParams.size.width) +
870 "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(uriParams.size.height);
871 tracer.Start("MediaLibraryManager::OpenThumbnail");
872 UniqueFd uniqueFd(MediaLibraryManager::OpenThumbnail(openUriStr, uriParams.path, uriParams.size, true));
873 if (uniqueFd.Get() < 0) {
874 MEDIA_ERR_LOG("OpenThumbnail failed, errCode is %{public}d, uri :%{public}s, path :%{public}s",
875 uniqueFd.Get(), uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
876 return nullptr;
877 }
878 tracer.Finish();
879 auto pixelmap = DecodeAstc(uniqueFd);
880 if (pixelmap == nullptr) {
881 MEDIA_ERR_LOG("pixelmap is null, uri :%{public}s, path :%{public}s",
882 uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
883 }
884 return pixelmap;
885 }
886
OpenReadOnlyAppSandboxVideo(const string & uri)887 static int32_t OpenReadOnlyAppSandboxVideo(const string& uri)
888 {
889 std::vector<std::string> uris;
890 if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
891 return -1;
892 }
893 AppFileService::ModuleFileUri::FileUri fileUri(uris[MOVING_PHOTO_VIDEO_POS]);
894 std::string realPath = fileUri.GetRealPath();
895 int32_t fd = open(realPath.c_str(), O_RDONLY);
896 if (fd < 0) {
897 MEDIA_ERR_LOG("Failed to open read only video file, errno: %{public}d", errno);
898 return -1;
899 }
900 return fd;
901 }
902
ReadMovingPhotoVideo(const string & uri)903 int32_t MediaLibraryManager::ReadMovingPhotoVideo(const string &uri)
904 {
905 if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
906 return OpenReadOnlyAppSandboxVideo(uri);
907 }
908 if (!CheckPhotoUri(uri)) {
909 MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
910 return E_ERR;
911 }
912
913 if (sDataShareHelper_ == nullptr) {
914 MEDIA_ERR_LOG("Failed to read video of moving photo, datashareHelper is nullptr");
915 return E_ERR;
916 }
917
918 string videoUri = uri;
919 MediaFileUtils::UriAppendKeyValue(videoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_MOVING_PHOTO_VIDEO);
920 Uri openVideoUri(videoUri);
921 return sDataShareHelper_->OpenFile(openVideoUri, MEDIA_FILEMODE_READONLY);
922 }
923
ReadPrivateMovingPhoto(const string & uri)924 int32_t MediaLibraryManager::ReadPrivateMovingPhoto(const string &uri)
925 {
926 if (!CheckPhotoUri(uri)) {
927 MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
928 return E_ERR;
929 }
930
931 if (sDataShareHelper_ == nullptr) {
932 MEDIA_ERR_LOG("Failed to read video of moving photo, datashareHelper is nullptr");
933 return E_ERR;
934 }
935
936 string movingPhotoUri = uri;
937 MediaFileUtils::UriAppendKeyValue(movingPhotoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_PRIVATE_LIVE_PHOTO);
938 Uri openMovingPhotoUri(movingPhotoUri);
939 return sDataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
940 }
941
GetMovingPhotoImageUri(const string & uri)942 std::string MediaLibraryManager::GetMovingPhotoImageUri(const string &uri)
943 {
944 if (uri.empty()) {
945 MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
946 return "";
947 }
948 if (MediaFileUtils::IsMediaLibraryUri(uri)) {
949 return uri;
950 }
951 std::vector<std::string> uris;
952 if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
953 return "";
954 }
955 return uris[MOVING_PHOTO_IMAGE_POS];
956 }
957
GetSandboxMovingPhotoTime(const string & uri)958 static int64_t GetSandboxMovingPhotoTime(const string& uri)
959 {
960 vector<string> uris;
961 if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
962 return E_ERR;
963 }
964
965 AppFileService::ModuleFileUri::FileUri imageFileUri(uris[MOVING_PHOTO_IMAGE_POS]);
966 string imageRealPath = imageFileUri.GetRealPath();
967 struct stat imageStatInfo {};
968 if (stat(imageRealPath.c_str(), &imageStatInfo) != 0) {
969 MEDIA_ERR_LOG("stat image error");
970 return E_ERR;
971 }
972 int64_t imageDateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(imageStatInfo.st_mtim));
973
974 AppFileService::ModuleFileUri::FileUri videoFileUri(uris[MOVING_PHOTO_VIDEO_POS]);
975 string videoRealPath = videoFileUri.GetRealPath();
976 struct stat videoStatInfo {};
977 if (stat(videoRealPath.c_str(), &videoStatInfo) != 0) {
978 MEDIA_ERR_LOG("stat video error");
979 return E_ERR;
980 }
981 int64_t videoDateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(videoStatInfo.st_mtim));
982 return imageDateModified >= videoDateModified ? imageDateModified : videoDateModified;
983 }
984
GetMovingPhotoDateModified(const string & uri)985 int64_t MediaLibraryManager::GetMovingPhotoDateModified(const string &uri)
986 {
987 if (uri.empty()) {
988 MEDIA_ERR_LOG("Failed to check empty uri");
989 return E_ERR;
990 }
991 if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
992 return GetSandboxMovingPhotoTime(uri);
993 }
994
995 if (!CheckPhotoUri(uri)) {
996 MEDIA_ERR_LOG("Failed to check invalid uri: %{public}s", uri.c_str());
997 return E_ERR;
998 }
999 Uri queryUri(PAH_QUERY_PHOTO);
1000 DataSharePredicates predicates;
1001 string fileId = MediaFileUtils::GetIdFromUri(uri);
1002 predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1003 DatashareBusinessError businessError;
1004 if (sDataShareHelper_ == nullptr) {
1005 MEDIA_ERR_LOG("sDataShareHelper_ is null");
1006 return E_ERR;
1007 }
1008 vector<string> columns = {
1009 MediaColumn::MEDIA_DATE_MODIFIED,
1010 };
1011 auto queryResultSet = sDataShareHelper_->Query(queryUri, predicates, columns, &businessError);
1012 if (queryResultSet == nullptr) {
1013 MEDIA_ERR_LOG("queryResultSet is null");
1014 return E_ERR;
1015 }
1016 if (queryResultSet->GoToNextRow() != NativeRdb::E_OK) {
1017 MEDIA_ERR_LOG("Failed to GoToNextRow");
1018 return E_ERR;
1019 }
1020 return GetInt64Val(MediaColumn::MEDIA_DATE_MODIFIED, queryResultSet);
1021 }
1022
UrisSourceMediaTypeClassify(const vector<string> & urisSource,vector<string> & photoFileIds,vector<string> & audioFileIds)1023 static int32_t UrisSourceMediaTypeClassify(const vector<string> &urisSource,
1024 vector<string> &photoFileIds, vector<string> &audioFileIds)
1025 {
1026 for (const auto &uri : urisSource) {
1027 int32_t tableType = -1;
1028 for (const auto &iter : tableMap) {
1029 if (uri.find(iter.first) != string::npos) {
1030 tableType = static_cast<int32_t>(iter.second);
1031 }
1032 }
1033 if (tableType == -1) {
1034 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
1035 return E_ERR;
1036 }
1037 string fileId = MediaFileUtils::GetIdFromUri(uri);
1038 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
1039 photoFileIds.emplace_back(fileId);
1040 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
1041 audioFileIds.emplace_back(fileId);
1042 } else {
1043 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
1044 return E_ERR;
1045 }
1046 }
1047 return E_SUCCESS;
1048 }
1049
CheckAccessTokenPermissionExecute(uint32_t tokenId,uint32_t checkFlag,TableType mediaType,bool & isReadable,bool & isWritable)1050 static void CheckAccessTokenPermissionExecute(uint32_t tokenId, uint32_t checkFlag, TableType mediaType,
1051 bool &isReadable, bool &isWritable)
1052 {
1053 static map<TableType, string> readPermmisionMap = {
1054 { TableType::TYPE_PHOTOS, PERM_READ_IMAGEVIDEO },
1055 { TableType::TYPE_AUDIOS, PERM_READ_AUDIO }
1056 };
1057 static map<TableType, string> writePermmisionMap = {
1058 { TableType::TYPE_PHOTOS, PERM_WRITE_IMAGEVIDEO },
1059 { TableType::TYPE_AUDIOS, PERM_WRITE_AUDIO }
1060 };
1061 int checkReadResult = -1;
1062 int checkWriteResult = -1;
1063 if (checkFlag == URI_PERMISSION_FLAG_READ) {
1064 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, readPermmisionMap[mediaType]);
1065 if (checkReadResult != PermissionState::PERMISSION_GRANTED) {
1066 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1067 }
1068 } else if (checkFlag == URI_PERMISSION_FLAG_WRITE) {
1069 checkWriteResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1070 } else if (checkFlag == URI_PERMISSION_FLAG_READWRITE) {
1071 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, readPermmisionMap[mediaType]);
1072 if (checkReadResult != PermissionState::PERMISSION_GRANTED) {
1073 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1074 }
1075 checkWriteResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
1076 }
1077 isReadable = checkReadResult == PermissionState::PERMISSION_GRANTED;
1078 isWritable = checkWriteResult == PermissionState::PERMISSION_GRANTED;
1079 }
CheckAccessTokenPermission(uint32_t tokenId,uint32_t checkFlag,TableType mediaType,int32_t & queryFlag)1080 static void CheckAccessTokenPermission(uint32_t tokenId, uint32_t checkFlag,
1081 TableType mediaType, int32_t &queryFlag)
1082 {
1083 bool isReadable = FALSE;
1084 bool isWritable = FALSE;
1085 CheckAccessTokenPermissionExecute(tokenId, checkFlag, mediaType, isReadable, isWritable);
1086
1087 if (checkFlag == URI_PERMISSION_FLAG_READ) {
1088 queryFlag = isReadable ? -1 : URI_PERMISSION_FLAG_READ;
1089 } else if (checkFlag == URI_PERMISSION_FLAG_WRITE) {
1090 queryFlag = isWritable ? -1 : URI_PERMISSION_FLAG_WRITE;
1091 } else if (checkFlag == URI_PERMISSION_FLAG_READWRITE) {
1092 if (isReadable && isWritable) {
1093 queryFlag = -1;
1094 } else if (isReadable) {
1095 queryFlag = URI_PERMISSION_FLAG_WRITE;
1096 } else if (isWritable) {
1097 queryFlag = URI_PERMISSION_FLAG_READ;
1098 } else {
1099 queryFlag = URI_PERMISSION_FLAG_READWRITE;
1100 }
1101 }
1102 }
1103
MakePredicatesForCheckPhotoUriPermission(int32_t & checkFlag,DataSharePredicates & predicates,const string & appid,TableType mediaType,vector<string> & fileIds)1104 static void MakePredicatesForCheckPhotoUriPermission(int32_t &checkFlag, DataSharePredicates &predicates,
1105 const string &appid, TableType mediaType, vector<string> &fileIds)
1106 {
1107 predicates.EqualTo(AppUriPermissionColumn::APP_ID, appid);
1108 predicates.And()->EqualTo(AppUriPermissionColumn::URI_TYPE, to_string(static_cast<int32_t>(mediaType)));
1109 predicates.And()->In(AppUriPermissionColumn::FILE_ID, fileIds);
1110 vector<string> permissionTypes;
1111 switch (checkFlag) {
1112 case URI_PERMISSION_FLAG_READ:
1113 permissionTypes.emplace_back(
1114 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
1115 permissionTypes.emplace_back(
1116 to_string(static_cast<int32_t>(PhotoPermissionType::PERSIST_READ_IMAGEVIDEO)));
1117 permissionTypes.emplace_back(
1118 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
1119 permissionTypes.emplace_back(
1120 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
1121 break;
1122 case URI_PERMISSION_FLAG_WRITE:
1123 permissionTypes.emplace_back(
1124 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
1125 permissionTypes.emplace_back(
1126 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
1127 permissionTypes.emplace_back(
1128 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
1129 break;
1130 case URI_PERMISSION_FLAG_READWRITE:
1131 permissionTypes.emplace_back(
1132 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
1133 permissionTypes.emplace_back(
1134 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
1135 break;
1136 default:
1137 MEDIA_ERR_LOG("error flag object: %{public}d", checkFlag);
1138 return;
1139 }
1140 predicates.And()->In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
1141 }
1142
CheckPhotoUriPermissionQueryOperation(const sptr<IRemoteObject> & token,const DataSharePredicates & predicates,map<string,int32_t> & resultMap)1143 static int32_t CheckPhotoUriPermissionQueryOperation(const sptr<IRemoteObject> &token,
1144 const DataSharePredicates &predicates, map<string, int32_t> &resultMap)
1145 {
1146 vector<string> columns = {
1147 AppUriPermissionColumn::FILE_ID,
1148 AppUriPermissionColumn::PERMISSION_TYPE
1149 };
1150 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1151 DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
1152 if (dataShareHelper == nullptr) {
1153 MEDIA_ERR_LOG("Failed to checkPhotoUriPermission, datashareHelper is nullptr");
1154 return E_ERR;
1155 }
1156
1157 Uri uri(MEDIALIBRARY_CHECK_URIPERM_URI);
1158 auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
1159 if (queryResultSet == nullptr) {
1160 MEDIA_ERR_LOG("queryResultSet is null!");
1161 return E_ERR;
1162 }
1163 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1164 string fileId = GetStringVal(AppUriPermissionColumn::FILE_ID, queryResultSet);
1165 int32_t permissionType = GetInt32Val(AppUriPermissionColumn::PERMISSION_TYPE, queryResultSet);
1166 resultMap[fileId] = permissionType;
1167 }
1168 return E_SUCCESS;
1169 }
1170
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)1171 static int32_t SetCheckPhotoUriPermissionResult(const vector<string> &urisSource, vector<bool> &results,
1172 const map<string, int32_t> &photoResultMap, const map<string, int32_t> &audioResultMap,
1173 int32_t queryPhotoFlag, int32_t queryAudioFlag)
1174 {
1175 results.clear();
1176 for (const auto &uri : urisSource) {
1177 int32_t tableType = -1;
1178 for (const auto &iter : tableMap) {
1179 if (uri.find(iter.first) != string::npos) {
1180 tableType = static_cast<int32_t>(iter.second);
1181 }
1182 }
1183 string fileId = MediaFileUtils::GetIdFromUri(uri);
1184 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
1185 if (queryPhotoFlag == -1 || photoResultMap.find(fileId) != photoResultMap.end()) {
1186 results.emplace_back(TRUE);
1187 } else {
1188 results.emplace_back(FALSE);
1189 }
1190 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
1191 if (queryAudioFlag == -1 || audioResultMap.find(fileId) != audioResultMap.end()) {
1192 results.emplace_back(TRUE);
1193 } else {
1194 results.emplace_back(FALSE);
1195 }
1196 }
1197 }
1198 return E_SUCCESS;
1199 }
1200
CheckInputParameters(const vector<string> & urisSource,uint32_t flag)1201 static int32_t CheckInputParameters(const vector<string> &urisSource, uint32_t flag)
1202 {
1203 if (urisSource.empty()) {
1204 MEDIA_ERR_LOG("Media Uri list is empty");
1205 return E_ERR;
1206 }
1207 if (urisSource.size() > URI_MAX_SIZE) {
1208 MEDIA_ERR_LOG("Uri list is exceed one Thousand, current list size: %{public}d", (int)urisSource.size());
1209 return E_ERR;
1210 }
1211 if (flag == 0 || flag > URI_PERMISSION_FLAG_READWRITE) {
1212 MEDIA_ERR_LOG("Flag is invalid, current flag is: %{public}d", flag);
1213 return E_ERR;
1214 }
1215 return E_SUCCESS;
1216 }
1217
CheckPhotoUriPermission(uint32_t tokenId,const string & appid,const vector<string> & urisSource,vector<bool> & results,uint32_t flag)1218 int32_t MediaLibraryManager::CheckPhotoUriPermission(uint32_t tokenId, const string &appid,
1219 const vector<string> &urisSource, vector<bool> &results, uint32_t flag)
1220 {
1221 auto ret = CheckInputParameters(urisSource, flag);
1222 if (ret != E_SUCCESS) {
1223 return E_ERR;
1224 }
1225 vector<string> photoFileIds;
1226 vector<string> audioFileIds;
1227 ret = UrisSourceMediaTypeClassify(urisSource, photoFileIds, audioFileIds);
1228 if (ret != E_SUCCESS) {
1229 return E_ERR;
1230 }
1231 int32_t queryPhotoFlag = URI_PERMISSION_FLAG_READWRITE;
1232 int32_t queryAudioFlag = URI_PERMISSION_FLAG_READWRITE;
1233 if (photoFileIds.empty()) {
1234 queryPhotoFlag = -1;
1235 } else {
1236 CheckAccessTokenPermission(tokenId, flag, TableType::TYPE_PHOTOS, queryPhotoFlag);
1237 }
1238 if (audioFileIds.empty()) {
1239 queryAudioFlag = -1;
1240 } else {
1241 CheckAccessTokenPermission(tokenId, flag, TableType::TYPE_AUDIOS, queryAudioFlag);
1242 }
1243 map<string, int32_t> photoResultMap;
1244 map<string, int32_t> audioResultMap;
1245 if (queryPhotoFlag != -1) {
1246 DataSharePredicates predicates;
1247 MakePredicatesForCheckPhotoUriPermission(queryPhotoFlag, predicates,
1248 appid, TableType::TYPE_PHOTOS, photoFileIds);
1249 auto ret = CheckPhotoUriPermissionQueryOperation(token_, predicates, photoResultMap);
1250 if (ret != E_SUCCESS) {
1251 return E_ERR;
1252 }
1253 }
1254 if (queryAudioFlag != -1) {
1255 DataSharePredicates predicates;
1256 MakePredicatesForCheckPhotoUriPermission(queryAudioFlag, predicates,
1257 appid, TableType::TYPE_AUDIOS, audioFileIds);
1258 auto ret = CheckPhotoUriPermissionQueryOperation(token_, predicates, audioResultMap);
1259 if (ret != E_SUCCESS) {
1260 return E_ERR;
1261 }
1262 }
1263 return SetCheckPhotoUriPermissionResult(urisSource, results, photoResultMap, audioResultMap,
1264 queryPhotoFlag, queryAudioFlag);
1265 }
1266
GrantPhotoUriPermission(const string & appid,const vector<string> & uris,PhotoPermissionType photoPermissionType,HideSensitiveType hideSensitiveTpye)1267 int32_t MediaLibraryManager::GrantPhotoUriPermission(const string &appid, const vector<string> &uris,
1268 PhotoPermissionType photoPermissionType, HideSensitiveType hideSensitiveTpye)
1269 {
1270 vector<DataShareValuesBucket> valueSet;
1271 if ((uris.empty()) || (uris.size() > URI_MAX_SIZE)) {
1272 MEDIA_ERR_LOG("Media Uri list error, please check!");
1273 return E_ERR;
1274 }
1275 if (photoPermissionType != PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO &&
1276 photoPermissionType != PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO &&
1277 photoPermissionType != PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO) {
1278 MEDIA_ERR_LOG("photoPermissionType error, please check param!");
1279 return E_ERR;
1280 }
1281 if (hideSensitiveTpye < HideSensitiveType::ALL_DESENSITIZE ||
1282 hideSensitiveTpye > HideSensitiveType::NO_DESENSITIZE) {
1283 MEDIA_ERR_LOG("HideSensitiveType error, please check param!");
1284 return E_ERR;
1285 }
1286 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1287 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1288 if (dataShareHelper == nullptr) {
1289 MEDIA_ERR_LOG("dataShareHelper is nullptr");
1290 return E_ERR;
1291 }
1292 for (const auto &uri : uris) {
1293 int32_t tableType = -1;
1294 for (const auto &iter : tableMap) {
1295 if (uri.find(iter.first) != string::npos) {
1296 tableType = static_cast<int32_t>(iter.second);
1297 }
1298 }
1299 if (tableType == -1) {
1300 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
1301 return E_ERR;
1302 }
1303 string fileId = MediaFileUtils::GetIdFromUri(uri);
1304 DataShareValuesBucket valuesBucket;
1305 valuesBucket.Put(AppUriPermissionColumn::APP_ID, appid);
1306 valuesBucket.Put(AppUriPermissionColumn::FILE_ID, fileId);
1307 valuesBucket.Put(AppUriPermissionColumn::URI_TYPE, tableType);
1308 valuesBucket.Put(AppUriPermissionColumn::PERMISSION_TYPE, static_cast<int32_t>(photoPermissionType));
1309 valuesBucket.Put(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, static_cast<int32_t>(hideSensitiveTpye));
1310 valueSet.push_back(valuesBucket);
1311 }
1312 Uri insertUri(MEDIALIBRARY_GRANT_URIPERM_URI);
1313 auto ret = dataShareHelper->BatchInsert(insertUri, valueSet);
1314 return ret;
1315 }
1316
CreatePhotoAssetProxy(CameraShotType cameraShotType,uint32_t callingUid,int32_t userId)1317 shared_ptr<PhotoAssetProxy> MediaLibraryManager::CreatePhotoAssetProxy(CameraShotType cameraShotType,
1318 uint32_t callingUid, int32_t userId)
1319 {
1320 shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1321 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1322 shared_ptr<PhotoAssetProxy> photoAssetProxy = make_shared<PhotoAssetProxy>(dataShareHelper, cameraShotType,
1323 callingUid, userId);
1324 return photoAssetProxy;
1325 }
1326
GetUrisByOldUris(std::vector<std::string> uris)1327 std::unordered_map<std::string, std::string> MediaLibraryManager::GetUrisByOldUris(std::vector<std::string> uris)
1328 {
1329 MEDIA_INFO_LOG("Start request uris by old uris, size: %{public}zu", uris.size());
1330 return TabOldPhotosClient(*this).GetUrisByOldUris(uris);
1331 }
1332 } // namespace Media
1333 } // namespace OHOS
1334