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