• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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