• 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 "moving_photo_file_utils.h"
48 #include "post_proc.h"
49 #include "permission_utils.h"
50 #include "result_set_utils.h"
51 #include "string_ex.h"
52 #include "system_ability_definition.h"
53 #include "thumbnail_const.h"
54 #include "unique_fd.h"
55 #include "userfilemgr_uri.h"
56 #include "data_secondary_directory_uri.h"
57 #include "medialibrary_business_code.h"
58 #include "user_inner_ipc_client.h"
59 #include "photo_album_column.h"
60 #include "add_visit_count_vo.h"
61 #include "create_asset_vo.h"
62 #include "get_result_set_from_db_vo.h"
63 #include "get_moving_photo_date_modified_vo.h"
64 #include "get_uri_from_filepath_vo.h"
65 #include "get_filepath_from_uri_vo.h"
66 #include "close_asset_vo.h"
67 #include "get_result_set_from_photos_extend_vo.h"
68 #include "get_albums_lpath_by_ids_vo.h"
69 #include "query_albums_vo.h"
70 #include "retain_cloud_media_asset_vo.h"
71 
72 #ifdef IMAGE_PURGEABLE_PIXELMAP
73 #include "purgeable_pixelmap_builder.h"
74 #endif
75 
76 using namespace std;
77 using namespace OHOS::NativeRdb;
78 using namespace OHOS::Security::AccessToken;
79 
80 namespace OHOS {
81 namespace Media {
82 shared_ptr<DataShare::DataShareHelper> MediaLibraryManager::sDataShareHelper_ = nullptr;
83 sptr<IRemoteObject> MediaLibraryManager::token_ = nullptr;
84 constexpr int32_t DEFAULT_THUMBNAIL_SIZE = 256;
85 constexpr int32_t MAX_DEFAULT_THUMBNAIL_SIZE = 768;
86 constexpr int32_t DEFAULT_MONTH_THUMBNAIL_SIZE = 128;
87 constexpr int32_t DEFAULT_YEAR_THUMBNAIL_SIZE = 64;
88 constexpr int32_t URI_MAX_SIZE = 1000;
89 
90 const std::string MULTI_USER_URI_FLAG = "user=";
91 
92 struct UriParams {
93     string path;
94     string fileUri;
95     Size size;
96     bool isAstc;
97     DecodeDynamicRange dynamicRange;
98     string user;
99 };
100 
GetMediaLibraryManager()101 MediaLibraryManager *MediaLibraryManager::GetMediaLibraryManager()
102 {
103     static MediaLibraryManager mediaLibMgr;
104     return &mediaLibMgr;
105 }
106 
InitMediaLibraryManager(const sptr<IRemoteObject> & token)107 void MediaLibraryManager::InitMediaLibraryManager(const sptr<IRemoteObject> &token)
108 {
109     token_ = token;
110     CHECK_AND_EXECUTE(sDataShareHelper_ != nullptr,
111         sDataShareHelper_ = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI));
112 }
113 
InitToken()114 sptr<IRemoteObject> MediaLibraryManager::InitToken()
115 {
116     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
117     CHECK_AND_RETURN_RET_LOG(saManager != nullptr, nullptr, "get system ability mgr failed.");
118     auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
119     CHECK_AND_RETURN_RET_LOG(remoteObj != nullptr, nullptr, "GetSystemAbility Service failed.");
120     return remoteObj;
121 }
122 
InitMediaLibraryManager()123 void MediaLibraryManager::InitMediaLibraryManager()
124 {
125     token_ = InitToken();
126     if (sDataShareHelper_ == nullptr && token_ != nullptr) {
127         sDataShareHelper_ = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
128     }
129 }
130 
CreateAsset(const string & displayName)131 string MediaLibraryManager::CreateAsset(const string &displayName)
132 {
133     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
134         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
135     if (dataShareHelper == nullptr || displayName.empty()) {
136         MEDIA_ERR_LOG("Failed to create Asset, datashareHelper is nullptr");
137         return "";
138     }
139     MediaType mediaType = MediaFileUtils::GetMediaType(displayName);
140     CHECK_AND_RETURN_RET_LOG((mediaType == MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO),
141         "", "Failed to create Asset, invalid file type.");
142     CreateAssetReqBody reqBody;
143     reqBody.mediaType = static_cast<int32_t>(mediaType);
144     reqBody.photoSubtype = static_cast<int32_t>(PhotoSubType::DEFAULT);
145     reqBody.displayName = displayName;
146     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_CREATE_ASSET);
147     CreateAssetRespBody respBody;
148     int32_t errCode =
149         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
150     if (errCode != 0) {
151         MEDIA_ERR_LOG("after IPC::UserDefineIPCClient().Call, errCode: %{public}d.", errCode);
152         return "";
153     }
154     string outUri = respBody.outUri;
155     return outUri;
156 }
157 
CheckUri(string & uri)158 static bool CheckUri(string &uri)
159 {
160     if (uri.find("../") != string::npos) {
161         return false;
162     }
163     string uriprex = "file://media";
164     return uri.substr(0, uriprex.size()) == uriprex;
165 }
166 
CheckPhotoUri(const string & uri)167 static bool CheckPhotoUri(const string &uri)
168 {
169     if (uri.find("../") != string::npos) {
170         return false;
171     }
172     string photoUriPrefix = "file://media/Photo/";
173     return MediaFileUtils::StartsWith(uri, photoUriPrefix);
174 }
175 
OpenAsset(string & uri,const string openMode)176 int32_t MediaLibraryManager::OpenAsset(string &uri, const string openMode)
177 {
178     CHECK_AND_RETURN_RET(!openMode.empty(), E_ERR);
179     CHECK_AND_RETURN_RET_LOG(CheckUri(uri), E_ERR, "invalid uri");
180     string originOpenMode = openMode;
181     std::transform(originOpenMode.begin(), originOpenMode.end(),
182         originOpenMode.begin(), [](unsigned char c) {return std::tolower(c);});
183     if (!MEDIA_OPEN_MODES.count(originOpenMode)) {
184         return E_ERR;
185     }
186 
187     if (sDataShareHelper_ == nullptr) {
188         MEDIA_ERR_LOG("Failed to open Asset, datashareHelper is nullptr");
189         return E_ERR;
190     }
191     Uri openUri(uri);
192     return sDataShareHelper_->OpenFile(openUri, openMode);
193 }
194 
CloseAsset(const string & uri,const int32_t fd)195 int32_t MediaLibraryManager::CloseAsset(const string &uri, const int32_t fd)
196 {
197     int32_t retVal = E_FAIL;
198 
199     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
200         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
201     if (dataShareHelper != nullptr) {
202         if (close(fd) == E_SUCCESS) {
203             CloseAssetReqBody reqBody;
204             reqBody.uri = uri;
205             retVal = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(
206                 static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_CLOSE_ASSET), reqBody);
207         }
208 
209         if (retVal == E_FAIL) {
210             MEDIA_ERR_LOG("Failed to close the file");
211         }
212     }
213 
214     return retVal;
215 }
216 
GetAstcYearAndMonth(const std::vector<string> & uris)217 int32_t MediaLibraryManager::GetAstcYearAndMonth(const std::vector<string> &uris)
218 {
219     if ((uris.empty()) || (uris.size() > URI_MAX_SIZE)) {
220         MEDIA_ERR_LOG("Failed to check uri size");
221         return E_ERR;
222     }
223 
224     if (sDataShareHelper_ == nullptr) {
225         MEDIA_ERR_LOG("Failed to GetAstcYearAndMonth, datashareHelper is nullptr");
226         return E_ERR;
227     }
228     string abilityUri = MEDIALIBRARY_DATA_URI;
229     Uri astcUri(abilityUri + "/" + MTH_AND_YEAR_ASTC + "/" + MTH_AND_YEAR_ASTC);
230     DataShareValuesBucket bucket;
231     for (auto uri : uris) {
232         bucket.Put(uri, false);
233     }
234     vector<DataShareValuesBucket> values;
235     values.emplace_back(bucket);
236     return sDataShareHelper_->BatchInsert(astcUri, values);
237 }
238 
QueryTotalSize(MediaVolume & outMediaVolume)239 int32_t MediaLibraryManager::QueryTotalSize(MediaVolume &outMediaVolume)
240 {
241     auto dataShareHelper = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
242     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, E_FAIL, "dataShareHelper is null");
243     vector<string> columns;
244     Uri uri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_QUERYOPRN_QUERYVOLUME + "/" + MEDIA_QUERYOPRN_QUERYVOLUME);
245     DataSharePredicates predicates;
246     auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
247     CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, E_FAIL, "queryResultSet is null!");
248     auto count = 0;
249     auto ret = queryResultSet->GetRowCount(count);
250     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR, "get rdbstore failed");
251     MEDIA_INFO_LOG("count = %{public}d", (int)count);
252 
253     if (count >= 0) {
254         int thumbnailType = -1;
255         while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
256             int mediatype = get<int32_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_MEDIA_TYPE,
257                 queryResultSet, TYPE_INT32));
258             int64_t size = get<int64_t>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_SIZE,
259                 queryResultSet, TYPE_INT64));
260             MEDIA_INFO_LOG("media_type: %{public}d, size: %{public}lld", mediatype, static_cast<long long>(size));
261             if (mediatype == MEDIA_TYPE_IMAGE || mediatype == thumbnailType) {
262                 outMediaVolume.SetSize(MEDIA_TYPE_IMAGE, outMediaVolume.GetImagesSize() + size);
263             } else {
264                 outMediaVolume.SetSize(mediatype, size);
265             }
266         }
267     }
268     MEDIA_INFO_LOG("Size: Files:%{public}lld, Videos:%{public}lld, Images:%{public}lld, Audio:%{public}lld",
269         static_cast<long long>(outMediaVolume.GetFilesSize()),
270         static_cast<long long>(outMediaVolume.GetVideosSize()),
271         static_cast<long long>(outMediaVolume.GetImagesSize()),
272         static_cast<long long>(outMediaVolume.GetAudiosSize())
273     );
274     return E_SUCCESS;
275 }
276 
GetResultSetFromPhotos(const string & value,vector<string> & columns,sptr<IRemoteObject> & token,shared_ptr<DataShare::DataShareHelper> & dataShareHelper)277 std::shared_ptr<DataShareResultSet> GetResultSetFromPhotos(const string &value, vector<string> &columns,
278     sptr<IRemoteObject> &token, shared_ptr<DataShare::DataShareHelper> &dataShareHelper)
279 {
280     CHECK_AND_RETURN_RET_LOG(CheckPhotoUri(value), nullptr, "Failed to check invalid uri: %{public}s", value.c_str());
281     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, nullptr, "datashareHelper is nullptr");
282 
283     GetResultSetFromPhotosExtendReqBody reqBody;
284     reqBody.value = value;
285     reqBody.columns = columns;
286     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_RESULT_SET_FROM_PHOTOS);
287     GetResultSetFromDbRespBody respBody;
288     int32_t errCode =
289         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
290     if (errCode != E_OK) {
291         MEDIA_ERR_LOG("errCode: %{public}d", errCode);
292         return nullptr;
293     }
294     return respBody.resultSet;
295 }
296 
GetResultSetFromDb(string columnName,const string & value,vector<string> & columns)297 std::shared_ptr<DataShareResultSet> MediaLibraryManager::GetResultSetFromDb(string columnName, const string &value,
298     vector<string> &columns)
299 {
300     if (columnName == MEDIA_DATA_DB_URI) {
301         auto resultSet = GetResultSetFromPhotos(value, columns, token_, sDataShareHelper_);
302         if (resultSet == nullptr) {
303             MEDIA_ERR_LOG("resultset is null, reconnect and retry");
304             shared_ptr<DataShare::DataShareHelper> dataShareHelper =
305                 DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
306             return GetResultSetFromPhotos(value, columns, token_, dataShareHelper);
307         } else {
308             return resultSet;
309         }
310     }
311 
312     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
313         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
314     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, nullptr, "dataShareHelper is null");
315 
316     GetResultSetFromDbReqBody reqBody;
317     reqBody.columnName = columnName;
318     reqBody.value = value;
319     reqBody.columns = columns;
320     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_RESULT_SET_FROM_DB);
321     GetResultSetFromDbRespBody respBody;
322     int32_t errCode =
323         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
324     if (errCode != 0) {
325         MEDIA_ERR_LOG("after IPC::UserDefineIPCClient().Call, errCode: %{public}d.", errCode);
326         return nullptr;
327     }
328     return respBody.resultSet;
329 }
330 
SolvePath(const string & filePath,string & tempPath,string & userId)331 static int32_t SolvePath(const string &filePath, string &tempPath, string &userId)
332 {
333     CHECK_AND_RETURN_RET(!filePath.empty(), E_INVALID_PATH);
334     string prePath = PRE_PATH_VALUES;
335     if (filePath.find(prePath) != 0) {
336         return E_CHECK_ROOT_DIR_FAIL;
337     }
338     string postpath = filePath.substr(prePath.length());
339     auto pos = postpath.find('/');
340     CHECK_AND_RETURN_RET(pos != string::npos, E_INVALID_ARGUMENTS);
341     userId = postpath.substr(0, pos);
342     postpath = postpath.substr(pos + 1);
343     tempPath = prePath + postpath;
344     return E_SUCCESS;
345 }
346 
CheckResultSet(std::shared_ptr<DataShareResultSet> & resultSet)347 int32_t MediaLibraryManager::CheckResultSet(std::shared_ptr<DataShareResultSet> &resultSet)
348 {
349     if (resultSet == nullptr) {
350         MEDIA_ERR_LOG("Input resultset is nullptr");
351         return E_FAIL;
352     }
353     int count = 0;
354     auto ret = resultSet->GetRowCount(count);
355     if (ret != NativeRdb::E_OK) {
356         MEDIA_ERR_LOG("Failed to get resultset row count, ret: %{public}d", ret);
357         return ret;
358     }
359     if (count <= 0) {
360         MEDIA_ERR_LOG("Failed to get count, count: %{public}d", count);
361         return E_FAIL;
362     }
363     ret = resultSet->GoToFirstRow();
364     if (ret != NativeRdb::E_OK) {
365         MEDIA_ERR_LOG("Failed to go to first row, ret: %{public}d", ret);
366         return ret;
367     }
368     return E_SUCCESS;
369 }
370 
GetFilePathResultSetFromDb(const string & virId,sptr<IRemoteObject> token)371 static std::shared_ptr<DataShareResultSet> GetFilePathResultSetFromDb(const string &virId, sptr<IRemoteObject> token)
372 {
373     GetFilePathFromUriReqBody reqBody;
374     GetFilePathFromUriRespBody respBody;
375     reqBody.virtualId = virId;
376 
377     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_FILEPATH_FROM_URI);
378     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
379         DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
380     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, nullptr, "dataShareHelper is null");
381     int32_t errCode =
382         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
383     if (errCode != 0) {
384         MEDIA_ERR_LOG("after IPC::UserDefineIPCClient().Call, errCode: %{public}d.", errCode);
385     }
386     return respBody.resultSet;
387 }
388 
GetFilePathFromUri(const Uri & fileUri,string & filePath,string userId)389 int32_t MediaLibraryManager::GetFilePathFromUri(const Uri &fileUri, string &filePath, string userId)
390 {
391     string uri = fileUri.ToString();
392     MediaFileUri virtualUri(uri);
393     CHECK_AND_RETURN_RET(virtualUri.IsValid(), E_URI_INVALID);
394     string virtualId = virtualUri.GetFileId();
395 #ifdef MEDIALIBRARY_COMPATIBILITY
396     if (MediaFileUtils::GetTableFromVirtualUri(uri) != MEDIALIBRARY_TABLE) {
397         MEDIA_INFO_LOG("uri:%{private}s does not match Files Table", uri.c_str());
398         return E_URI_INVALID;
399     }
400 #endif
401     vector<string> columns = { MEDIA_DATA_DB_FILE_PATH };
402     auto resultSet = GetFilePathResultSetFromDb(virtualId, token_);
403     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_INVALID_URI,
404         "GetFilePathFromUri::uri is not correct: %{private}s", uri.c_str());
405     if (CheckResultSet(resultSet) != E_SUCCESS) {
406         return E_FAIL;
407     }
408 
409     std::string tempPath = ResultSetUtils::GetStringValFromColumn(1, resultSet);
410     if (tempPath.find(ROOT_MEDIA_DIR) != 0) {
411         return E_CHECK_ROOT_DIR_FAIL;
412     }
413     string relativePath = tempPath.substr((ROOT_MEDIA_DIR + DOCS_PATH).length());
414     auto pos = relativePath.find('/');
415     if (pos == string::npos) {
416         return E_INVALID_ARGUMENTS;
417     }
418     relativePath = relativePath.substr(0, pos + 1);
419     if ((relativePath != DOC_DIR_VALUES) && (relativePath != DOWNLOAD_DIR_VALUES)) {
420         return E_DIR_CHECK_DIR_FAIL;
421     }
422 
423     string prePath = PRE_PATH_VALUES;
424     string postpath = tempPath.substr(prePath.length());
425     tempPath = prePath + userId + "/" + postpath;
426     filePath = tempPath;
427     return E_SUCCESS;
428 }
429 
GetUriResultSetFromDb(const string & tempPath,sptr<IRemoteObject> token)430 static std::shared_ptr<DataShareResultSet> GetUriResultSetFromDb(
431     const string &tempPath, sptr<IRemoteObject> token)
432 {
433     GetUriFromFilePathReqBody reqBody;
434     GetUriFromFilePathRespBody respBody;
435     reqBody.tempPath = tempPath;
436 
437     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_URI_FROM_FILEPATH);
438     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
439         DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
440     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, nullptr, "dataShareHelper is null");
441     int32_t errCode =
442         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
443     if (errCode != 0) {
444         MEDIA_ERR_LOG("after IPC::UserDefineIPCClient().Call, errCode: %{public}d.", errCode);
445     }
446     return respBody.resultSet;
447 }
448 
GetUriFromFilePath(const string & filePath,Uri & fileUri,string & userId)449 int32_t MediaLibraryManager::GetUriFromFilePath(const string &filePath, Uri &fileUri, string &userId)
450 {
451     if (filePath.empty()) {
452         return E_INVALID_PATH;
453     }
454 
455     string tempPath;
456     SolvePath(filePath, tempPath, userId);
457     if (tempPath.find(ROOT_MEDIA_DIR) != 0) {
458         return E_CHECK_ROOT_DIR_FAIL;
459     }
460     string relativePath = tempPath.substr((ROOT_MEDIA_DIR + DOCS_PATH).length());
461     auto pos = relativePath.find('/');
462     if (pos == string::npos) {
463         return E_INVALID_ARGUMENTS;
464     }
465     relativePath = relativePath.substr(0, pos + 1);
466     if ((relativePath != DOC_DIR_VALUES) && (relativePath != DOWNLOAD_DIR_VALUES)) {
467         return E_DIR_CHECK_DIR_FAIL;
468     }
469 
470     vector<string> columns = { MEDIA_DATA_DB_ID};
471     auto resultSet = GetUriResultSetFromDb(tempPath, token_);
472     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_INVALID_URI,
473         "GetUriFromFilePath::tempPath is not correct: %{private}s", tempPath.c_str());
474     if (CheckResultSet(resultSet) != E_SUCCESS) {
475         return E_FAIL;
476     }
477 
478     int32_t fileId = ResultSetUtils::GetIntValFromColumn(0, resultSet);
479 #ifdef MEDIALIBRARY_COMPATIBILITY
480     int64_t virtualId = MediaFileUtils::GetVirtualIdByType(fileId, MediaType::MEDIA_TYPE_FILE);
481     fileUri = MediaFileUri(MediaType::MEDIA_TYPE_FILE, to_string(virtualId), "", MEDIA_API_VERSION_V9);
482 #else
483     fileUri = MediaFileUri(MediaType::MEDIA_TYPE_FILE, to_string(fileId), "", MEDIA_API_VERSION_V9);
484 #endif
485     return E_SUCCESS;
486 }
487 
GetSandboxPath(const std::string & path,const Size & size,bool isAstc)488 std::string MediaLibraryManager::GetSandboxPath(const std::string &path, const Size &size, bool isAstc)
489 {
490     if (path.length() < ROOT_MEDIA_DIR.length()) {
491         return "";
492     }
493     int min = std::min(size.width, size.height);
494     int max = std::max(size.width, size.height);
495     std::string suffixStr = path.substr(ROOT_MEDIA_DIR.length()) + "/";
496     if (min == DEFAULT_ORIGINAL && max == DEFAULT_ORIGINAL) {
497         suffixStr += "LCD.jpg";
498     } else if (min <= DEFAULT_THUMBNAIL_SIZE && max <= MAX_DEFAULT_THUMBNAIL_SIZE) {
499         suffixStr += isAstc ? "THM_ASTC.astc" : "THM.jpg";
500     } else {
501         suffixStr += "LCD.jpg";
502     }
503 
504     return ROOT_SANDBOX_DIR + ".thumbs/" + suffixStr;
505 }
506 
GetFdFromSandbox(const string & path,string & sandboxPath,bool isAstc)507 static int32_t GetFdFromSandbox(const string &path, string &sandboxPath, bool isAstc)
508 {
509     int32_t fd = -1;
510     CHECK_AND_RETURN_RET_LOG(!sandboxPath.empty(), fd, "OpenThumbnail sandboxPath is empty, path :%{public}s",
511         MediaFileUtils::DesensitizePath(path).c_str());
512     string absFilePath;
513     CHECK_AND_RETURN_RET(!PathToRealPath(sandboxPath, absFilePath), open(absFilePath.c_str(), O_RDONLY));
514     CHECK_AND_RETURN_RET(isAstc, fd);
515     string suffixStr = "THM_ASTC.astc";
516     size_t thmIdx = sandboxPath.find(suffixStr);
517     CHECK_AND_RETURN_RET(thmIdx != std::string::npos, fd);
518     sandboxPath.replace(thmIdx, suffixStr.length(), "THM.jpg");
519     CHECK_AND_RETURN_RET(PathToRealPath(sandboxPath, absFilePath), fd);
520     return open(absFilePath.c_str(), O_RDONLY);
521 }
522 
UpdateAssetVisitCount(shared_ptr<DataShare::DataShareHelper> dataShareHelper,const string & fileIdStr)523 static void UpdateAssetVisitCount(shared_ptr<DataShare::DataShareHelper> dataShareHelper, const string &fileIdStr)
524 {
525     MEDIA_INFO_LOG("UpdateAssetVisitCount fileIdStr :%{public}s", fileIdStr.c_str());
526     AddAssetVisitCountReqBody reqBody;
527     reqBody.fileId = fileIdStr.empty() ? -1 : atoi(fileIdStr.c_str());
528     reqBody.visitType = 1; // LCD
529 
530     int32_t businessCode = static_cast<int32_t>(MediaLibraryBusinessCode::INNER_ADD_ASSET_VISIT_COUNT);
531     int32_t errCode = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody);
532     if (errCode < 0) {
533         MEDIA_ERR_LOG("after IPC::UserDefineIPCClient().Call, errCode: %{public}d.", errCode);
534     }
535 }
536 
OpenThumbnail(string & uriStr,const string & path,const Size & size,bool isAstc)537 int MediaLibraryManager::OpenThumbnail(string &uriStr, const string &path, const Size &size, bool isAstc)
538 {
539     // To ensure performance.
540     std::string str = uriStr;
541     size_t pos = str.find(MULTI_USER_URI_FLAG);
542     std::string userId = "";
543     if (pos != std::string::npos) {
544         pos += MULTI_USER_URI_FLAG.length();
545         size_t end = str.find_first_of("&?", pos);
546         CHECK_AND_EXECUTE(end != std::string::npos, end = str.length());
547         userId = str.substr(pos, end - pos);
548         MEDIA_ERR_LOG("OpenThumbnail for other user is %{public}s", userId.c_str());
549     }
550     shared_ptr<DataShare::DataShareHelper> dataShareHelper = userId != "" ? DataShare::DataShareHelper::Creator(token_,
551         MEDIALIBRARY_DATA_URI + "?" + MULTI_USER_URI_FLAG + userId) : sDataShareHelper_;
552     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, E_ERR, "Failed to open thumbnail, dataShareHelper is nullptr");
553     if (path.empty()) {
554         MEDIA_ERR_LOG("OpenThumbnail path is empty");
555         Uri openUri(uriStr);
556         return dataShareHelper->OpenFile(openUri, "R");
557     }
558     string sandboxPath = GetSandboxPath(path, size, isAstc);
559     int32_t fd = GetFdFromSandbox(path, sandboxPath, isAstc);
560     if (fd > 0 && sandboxPath.find("LCD.jpg") != std::string::npos) {
561         UpdateAssetVisitCount(dataShareHelper, MediaFileUtils::GetIdFromUri(uriStr));
562     }
563     CHECK_AND_RETURN_RET(fd <= 0, fd);
564     MEDIA_INFO_LOG("OpenThumbnail from andboxPath failed, errno %{public}d path :%{public}s fd %{public}d",
565         errno, MediaFileUtils::DesensitizePath(path).c_str(), fd);
566     CHECK_AND_EXECUTE(!IsAsciiString(path), uriStr += "&" + THUMBNAIL_PATH + "=" + path);
567     Uri openUri(uriStr);
568     return dataShareHelper->OpenFile(openUri, "R");
569 }
570 
571 /**
572  * Get the file uri prefix with id
573  * eg. Input: file://media/Photo/10/IMG_xxx/01.jpg
574  *     Output: file://media/Photo/10
575  */
GetUriIdPrefix(std::string & fileUri)576 void MediaLibraryManager::GetUriIdPrefix(std::string &fileUri)
577 {
578     MediaFileUri mediaUri(fileUri);
579     CHECK_AND_RETURN(mediaUri.IsApi10());
580     auto slashIdx = fileUri.rfind('/');
581     if (slashIdx == std::string::npos) {
582         return;
583     }
584     auto tmpUri = fileUri.substr(0, slashIdx);
585     slashIdx = tmpUri.rfind('/');
586     if (slashIdx == std::string::npos) {
587         return;
588     }
589     fileUri = tmpUri.substr(0, slashIdx);
590 }
591 
GetUriParamsFromQueryKey(UriParams & uriParams,std::unordered_map<std::string,std::string> & queryKey)592 static void GetUriParamsFromQueryKey(UriParams& uriParams,
593     std::unordered_map<std::string, std::string>& queryKey)
594 {
595     if (queryKey.count(THUMBNAIL_PATH) != 0) {
596         uriParams.path = queryKey[THUMBNAIL_PATH];
597     }
598     if (queryKey.count(THUMBNAIL_WIDTH) != 0) {
599         if (MediaFileUtils::IsValidInteger(queryKey[THUMBNAIL_WIDTH])) {
600             uriParams.size.width = stoi(queryKey[THUMBNAIL_WIDTH]);
601         }
602     }
603     if (queryKey.count(THUMBNAIL_HEIGHT) != 0) {
604         if (MediaFileUtils::IsValidInteger(queryKey[THUMBNAIL_HEIGHT])) {
605             uriParams.size.height = stoi(queryKey[THUMBNAIL_HEIGHT]);
606         }
607     }
608     if (queryKey.count(THUMBNAIL_OPER) != 0) {
609         uriParams.isAstc = queryKey[THUMBNAIL_OPER] == MEDIA_DATA_DB_THUMB_ASTC;
610     }
611     if (queryKey.count(THUMBNAIL_USER) != 0) {
612         uriParams.user = queryKey[THUMBNAIL_USER];
613     }
614     uriParams.dynamicRange = DecodeDynamicRange::AUTO;
615     if (queryKey.count(DYNAMIC_RANGE) != 0) {
616         if (MediaFileUtils::IsValidInteger(queryKey[DYNAMIC_RANGE])) {
617             uriParams.dynamicRange = static_cast<DecodeDynamicRange>(stoi(queryKey[DYNAMIC_RANGE]));
618         }
619     }
620 }
621 
GetParamsFromUri(const string & uri,const bool isOldVer,UriParams & uriParams)622 static bool GetParamsFromUri(const string &uri, const bool isOldVer, UriParams &uriParams)
623 {
624     MediaFileUri mediaUri(uri);
625     CHECK_AND_RETURN_RET(mediaUri.IsValid(), false);
626     if (isOldVer) {
627         auto index = uri.find("thumbnail");
628         if (index == string::npos || index == 0) {
629             return false;
630         }
631         uriParams.fileUri = uri.substr(0, index - 1);
632         MediaLibraryManager::GetUriIdPrefix(uriParams.fileUri);
633         index += strlen("thumbnail");
634         index = uri.find('/', index);
635         CHECK_AND_RETURN_RET(index != string::npos, false);
636 
637         index += 1;
638         auto tmpIdx = uri.find('/', index);
639         CHECK_AND_RETURN_RET(tmpIdx != string::npos, false);
640 
641         int32_t width = 0;
642         StrToInt(uri.substr(index, tmpIdx - index), width);
643         int32_t height = 0;
644         StrToInt(uri.substr(tmpIdx + 1), height);
645         uriParams.size = { .width = width, .height = height };
646     } else {
647         auto qIdx = uri.find('?');
648         if (qIdx == string::npos) {
649             return false;
650         }
651         uriParams.fileUri = uri.substr(0, qIdx);
652         MediaLibraryManager::GetUriIdPrefix(uriParams.fileUri);
653         auto &queryKey = mediaUri.GetQueryKeys();
654         GetUriParamsFromQueryKey(uriParams, queryKey);
655     }
656     return true;
657 }
658 
IfSizeEqualsRatio(const Size & imageSize,const Size & targetSize)659 bool MediaLibraryManager::IfSizeEqualsRatio(const Size &imageSize, const Size &targetSize)
660 {
661     bool cond = (imageSize.height <= 0 || targetSize.height <= 0);
662     CHECK_AND_RETURN_RET(!cond, false);
663     float imageSizeScale = static_cast<float>(imageSize.width) / static_cast<float>(imageSize.height);
664     float targetSizeScale = static_cast<float>(targetSize.width) / static_cast<float>(targetSize.height);
665     if (imageSizeScale - targetSizeScale > FLOAT_EPSILON || targetSizeScale - imageSizeScale > FLOAT_EPSILON) {
666         return false;
667     } else {
668         return true;
669     }
670 }
671 
DecodeThumbnail(UniqueFd & uniqueFd,const Size & size,DecodeDynamicRange dynamicRange)672 unique_ptr<PixelMap> MediaLibraryManager::DecodeThumbnail(UniqueFd& uniqueFd, const Size& size,
673     DecodeDynamicRange dynamicRange)
674 {
675     MediaLibraryTracer tracer;
676     tracer.Start("ImageSource::CreateImageSource");
677     SourceOptions opts;
678     uint32_t err = 0;
679     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
680     CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, nullptr, "CreateImageSource err %{public}d", err);
681 
682     ImageInfo imageInfo;
683     err = imageSource->GetImageInfo(0, imageInfo);
684     CHECK_AND_RETURN_RET_LOG(err == E_OK, nullptr, "GetImageInfo err %{public}d", err);
685 
686     bool isEqualsRatio = IfSizeEqualsRatio(imageInfo.size, size);
687     DecodeOptions decodeOpts;
688     decodeOpts.desiredSize = isEqualsRatio ? size : imageInfo.size;
689     decodeOpts.desiredDynamicRange = dynamicRange;
690     unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
691     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "CreatePixelMap err %{public}d", err);
692 
693     PostProc postProc;
694     bool cond = (size.width != 0 && size.width != DEFAULT_ORIGINAL && !isEqualsRatio &&
695         !postProc.CenterScale(size, *pixelMap));
696     CHECK_AND_RETURN_RET_LOG(!cond, nullptr, "CenterScale failed, size: %{public}d * %{public}d,"
697         " imageInfo size: %{public}d * %{public}d", size.width, size.height,
698         imageInfo.size.width, imageInfo.size.height);
699 
700     // Make the ashmem of pixelmap to be purgeable after the operation on ashmem.
701     // And then make the pixelmap subject to PurgeableManager's control.
702 #ifdef IMAGE_PURGEABLE_PIXELMAP
703     PurgeableBuilder::MakePixelMapToBePurgeable(pixelMap, imageSource, decodeOpts, size);
704 #endif
705     return pixelMap;
706 }
707 
QueryThumbnail(UriParams & params)708 unique_ptr<PixelMap> MediaLibraryManager::QueryThumbnail(UriParams& params)
709 {
710     MediaLibraryTracer tracer;
711     tracer.Start("QueryThumbnail uri:" + params.fileUri);
712 
713     string oper = params.isAstc ? MEDIA_DATA_DB_THUMB_ASTC : MEDIA_DATA_DB_THUMBNAIL;
714     string openUriStr = params.fileUri + "?" + MEDIA_OPERN_KEYWORD + "=" + oper + "&" + MEDIA_DATA_DB_WIDTH +
715         "=" + to_string(params.size.width) + "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(params.size.height);
716     if (params.user != "") {
717         openUriStr = openUriStr + "&" + THUMBNAIL_USER + "=" + params.user;
718         bool cond = (!params.path.empty() && !params.path.find(MULTI_USER_URI_FLAG));
719         CHECK_AND_EXECUTE(!cond, params.path = params.path + "&" + THUMBNAIL_USER + "=" + params.user);
720     }
721     tracer.Start("DataShare::OpenThumbnail");
722     UniqueFd uniqueFd(MediaLibraryManager::OpenThumbnail(openUriStr, params.path, params.size, params.isAstc));
723     CHECK_AND_RETURN_RET_LOG(uniqueFd.Get() >= 0, nullptr, "queryThumb is null, errCode is %{public}d", uniqueFd.Get());
724     tracer.Finish();
725     return DecodeThumbnail(uniqueFd, params.size, params.dynamicRange);
726 }
727 
GetThumbnail(const Uri & uri)728 std::unique_ptr<PixelMap> MediaLibraryManager::GetThumbnail(const Uri &uri)
729 {
730     // uri is dataability:///media/image/<id>/thumbnail/<width>/<height>
731     string uriStr = uri.ToString();
732     auto thumbLatIdx = uriStr.find("thumbnail");
733     bool isAstc = false;
734     if (thumbLatIdx == string::npos || thumbLatIdx > uriStr.length()) {
735         thumbLatIdx = uriStr.find("astc");
736         if (thumbLatIdx == string::npos || thumbLatIdx > uriStr.length()) {
737             MEDIA_ERR_LOG("GetThumbnail failed, oper is invalid");
738             return nullptr;
739         }
740         isAstc = true;
741     }
742     thumbLatIdx += isAstc ? strlen("astc") : strlen("thumbnail");
743     bool isOldVersion = uriStr[thumbLatIdx] == '/';
744     UriParams uriParams;
745     if (!GetParamsFromUri(uriStr, isOldVersion, uriParams)) {
746         MEDIA_ERR_LOG("GetThumbnail failed, get params from uri failed, uri :%{public}s", uriStr.c_str());
747         return nullptr;
748     }
749     auto pixelmap = QueryThumbnail(uriParams);
750     if (pixelmap == nullptr) {
751         MEDIA_ERR_LOG("pixelmap is null, uri :%{public}s, path :%{public}s",
752             uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
753     }
754     return pixelmap;
755 }
756 
GetAstcsByOffset(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)757 static int32_t GetAstcsByOffset(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
758 {
759     UriParams uriParams;
760     if (!GetParamsFromUri(uriBatch.at(0), false, uriParams)) {
761         MEDIA_ERR_LOG("GetParamsFromUri failed in GetAstcsByOffset");
762         return E_INVALID_URI;
763     }
764     vector<string> timeIdBatch;
765     int32_t start = 0;
766     int32_t count = 0;
767     MediaFileUri::GetTimeIdFromUri(uriBatch, timeIdBatch, start, count);
768     CHECK_AND_RETURN_RET_LOG(!timeIdBatch.empty(), E_INVALID_URI, "GetTimeIdFromUri failed");
769     MEDIA_INFO_LOG("GetAstcsByOffset image batch size: %{public}zu, begin: %{public}s, end: %{public}s,"
770         "start: %{public}d, count: %{public}d", uriBatch.size(), timeIdBatch.back().c_str(),
771         timeIdBatch.front().c_str(), start, count);
772 
773     KvStoreValueType valueType;
774     if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
775         valueType = KvStoreValueType::MONTH_ASTC;
776     } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
777         uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
778         valueType = KvStoreValueType::YEAR_ASTC;
779     } else {
780         MEDIA_ERR_LOG("GetAstcsByOffset invalid image size");
781         return E_INVALID_URI;
782     }
783 
784     vector<string> newTimeIdBatch;
785     MediaAssetRdbStore::GetInstance()->QueryTimeIdBatch(start, count, newTimeIdBatch);
786     auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
787     if (kvStore == nullptr) {
788         MEDIA_ERR_LOG("GetAstcsByOffset kvStore is nullptr");
789         return E_DB_FAIL;
790     }
791     int32_t status = kvStore->BatchQuery(newTimeIdBatch, astcBatch);
792     if (status != E_OK) {
793         MEDIA_ERR_LOG("GetAstcsByOffset failed, status %{public}d", status);
794         return status;
795     }
796     return E_OK;
797 }
798 
GetAstcsBatch(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)799 static int32_t GetAstcsBatch(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
800 {
801     UriParams uriParams;
802     if (!GetParamsFromUri(uriBatch.at(0), false, uriParams)) {
803         MEDIA_ERR_LOG("GetParamsFromUri failed in GetAstcsBatch");
804         return E_INVALID_URI;
805     }
806     vector<string> timeIdBatch;
807     MediaFileUri::GetTimeIdFromUri(uriBatch, timeIdBatch);
808     CHECK_AND_RETURN_RET_LOG(!timeIdBatch.empty(), E_INVALID_URI, "GetTimeIdFromUri failed");
809     MEDIA_INFO_LOG("GetAstcsBatch image batch size: %{public}zu, begin: %{public}s, end: %{public}s",
810         uriBatch.size(), timeIdBatch.back().c_str(), timeIdBatch.front().c_str());
811 
812     KvStoreValueType valueType;
813     if (uriParams.size.width == DEFAULT_MONTH_THUMBNAIL_SIZE && uriParams.size.height == DEFAULT_MONTH_THUMBNAIL_SIZE) {
814         valueType = KvStoreValueType::MONTH_ASTC;
815     } else if (uriParams.size.width == DEFAULT_YEAR_THUMBNAIL_SIZE &&
816         uriParams.size.height == DEFAULT_YEAR_THUMBNAIL_SIZE) {
817         valueType = KvStoreValueType::YEAR_ASTC;
818     } else {
819         MEDIA_ERR_LOG("GetAstcsBatch invalid image size");
820         return E_INVALID_URI;
821     }
822 
823     auto kvStore = MediaLibraryKvStoreManager::GetInstance().GetKvStore(KvStoreRoleType::VISITOR, valueType);
824     CHECK_AND_RETURN_RET_LOG(kvStore != nullptr, E_DB_FAIL, "GetAstcsBatch kvStore is nullptr");
825     int32_t status = kvStore->BatchQuery(timeIdBatch, astcBatch);
826     CHECK_AND_RETURN_RET_LOG(status == E_OK, status, "GetAstcsBatch failed, status %{public}d", status);
827     return E_OK;
828 }
829 
GetBatchAstcs(const vector<string> & uriBatch,vector<vector<uint8_t>> & astcBatch)830 int32_t MediaLibraryManager::GetBatchAstcs(const vector<string> &uriBatch, vector<vector<uint8_t>> &astcBatch)
831 {
832     if (uriBatch.empty()) {
833         MEDIA_INFO_LOG("GetBatchAstcs uriBatch is empty");
834         return E_INVALID_URI;
835     }
836     if (uriBatch.at(0).find(ML_URI_OFFSET) != std::string::npos) {
837         return GetAstcsByOffset(uriBatch, astcBatch);
838     } else {
839         return GetAstcsBatch(uriBatch, astcBatch);
840     }
841 }
842 
DecodeAstc(UniqueFd & uniqueFd)843 unique_ptr<PixelMap> MediaLibraryManager::DecodeAstc(UniqueFd &uniqueFd)
844 {
845     if (uniqueFd.Get() < 0) {
846         MEDIA_ERR_LOG("Fd is invalid, errCode is %{public}d", uniqueFd.Get());
847         return nullptr;
848     }
849     MediaLibraryTracer tracer;
850     tracer.Start("MediaLibraryManager::DecodeAstc");
851     SourceOptions opts;
852     uint32_t err = 0;
853     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(uniqueFd.Get(), opts, err);
854     CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, nullptr, "CreateImageSource err %{public}d", err);
855 
856     DecodeOptions decodeOpts;
857     decodeOpts.fastAstc = true;
858     decodeOpts.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
859     unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
860     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "CreatePixelMap err %{public}d", err);
861     return pixelMap;
862 }
863 
GetAstc(const Uri & uri)864 std::unique_ptr<PixelMap> MediaLibraryManager::GetAstc(const Uri &uri)
865 {
866     // uri is file://media/image/<id>&oper=astc&width=<width>&height=<height>&path=<path>
867     MediaLibraryTracer tracer;
868     string uriStr = uri.ToString();
869     if (uriStr.empty()) {
870         MEDIA_ERR_LOG("GetAstc failed, uri is empty");
871         return nullptr;
872     }
873     auto astcIndex = uriStr.find("astc");
874     if (astcIndex == string::npos || astcIndex > uriStr.length()) {
875         MEDIA_ERR_LOG("GetAstc failed, oper is invalid");
876         return nullptr;
877     }
878     UriParams uriParams;
879     if (!GetParamsFromUri(uriStr, false, uriParams)) {
880         MEDIA_ERR_LOG("GetAstc failed, get params from uri failed, uri :%{public}s", uriStr.c_str());
881         return nullptr;
882     }
883     tracer.Start("GetAstc uri:" + uriParams.fileUri);
884     string openUriStr = uriParams.fileUri + "?" + MEDIA_OPERN_KEYWORD + "=" +
885         MEDIA_DATA_DB_THUMB_ASTC + "&" + MEDIA_DATA_DB_WIDTH + "=" + to_string(uriParams.size.width) +
886             "&" + MEDIA_DATA_DB_HEIGHT + "=" + to_string(uriParams.size.height);
887     if (uriParams.user != "") {
888         openUriStr = openUriStr + "&" + THUMBNAIL_USER + "=" + uriParams.user;
889         if (!uriParams.path.empty() && !uriParams.path.find(MULTI_USER_URI_FLAG)) {
890             uriParams.path = uriParams.path + "&" + THUMBNAIL_USER + "=" + uriParams.user;
891         }
892     }
893     tracer.Start("MediaLibraryManager::OpenThumbnail");
894     UniqueFd uniqueFd(MediaLibraryManager::OpenThumbnail(openUriStr, uriParams.path, uriParams.size, true));
895     if (uniqueFd.Get() < 0) {
896         MEDIA_ERR_LOG("OpenThumbnail failed, errCode is %{public}d, uri :%{public}s, path :%{public}s",
897             uniqueFd.Get(), uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
898         return nullptr;
899     }
900     tracer.Finish();
901     auto pixelmap = DecodeAstc(uniqueFd);
902     if (pixelmap == nullptr) {
903         MEDIA_ERR_LOG("pixelmap is null, uri :%{public}s, path :%{public}s",
904             uriParams.fileUri.c_str(), MediaFileUtils::DesensitizePath(uriParams.path).c_str());
905     }
906     return pixelmap;
907 }
908 
OpenReadOnlyAppSandboxVideo(const string & uri)909 int32_t MediaLibraryManager::OpenReadOnlyAppSandboxVideo(const string& uri)
910 {
911     std::vector<std::string> uris;
912     if (!MediaFileUtils::SplitMovingPhotoUri(uri, uris)) {
913         return -1;
914     }
915     AppFileService::ModuleFileUri::FileUri fileUri(uris[MOVING_PHOTO_VIDEO_POS]);
916     std::string realPath = fileUri.GetRealPath();
917     int32_t fd = open(realPath.c_str(), O_RDONLY);
918     if (fd < 0) {
919         MEDIA_ERR_LOG("Failed to open read only video file, errno: %{public}d", errno);
920         return -1;
921     }
922     return fd;
923 }
924 
ReadMovingPhotoVideo(const string & uri,const string & option)925 int32_t MediaLibraryManager::ReadMovingPhotoVideo(const string &uri, const string &option)
926 {
927     std::string str = uri;
928     size_t pos = str.find(MULTI_USER_URI_FLAG);
929     std::string userId = "";
930     if (pos != std::string::npos) {
931         pos += MULTI_USER_URI_FLAG.length();
932         size_t end = str.find_first_of("&?", pos);
933         if (end == std::string::npos) {
934             end = str.length();
935         }
936         userId = str.substr(pos, end - pos);
937         MEDIA_INFO_LOG("ReadMovingPhotoVideo for other user is %{public}s", userId.c_str());
938     }
939     shared_ptr<DataShare::DataShareHelper> dataShareHelper = userId != "" ?
940         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI + "?" + MULTI_USER_URI_FLAG + userId) :
941         sDataShareHelper_;
942     if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
943         return OpenReadOnlyAppSandboxVideo(uri);
944     }
945     if (!CheckPhotoUri(uri)) {
946         MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
947         return E_ERR;
948     }
949 
950     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, E_ERR,
951         "Failed to read video of moving photo, datashareHelper is nullptr");
952     string videoUri = uri;
953     MediaFileUtils::UriAppendKeyValue(videoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, option);
954     Uri openVideoUri(videoUri);
955     return dataShareHelper->OpenFile(openVideoUri, MEDIA_FILEMODE_READONLY);
956 }
957 
ReadMovingPhotoVideo(const string & uri)958 int32_t MediaLibraryManager::ReadMovingPhotoVideo(const string &uri)
959 {
960     return ReadMovingPhotoVideo(uri, OPEN_MOVING_PHOTO_VIDEO);
961 }
962 
ReadMovingPhotoVideo(const string & uri,off_t & offset)963 int32_t MediaLibraryManager::ReadMovingPhotoVideo(const string &uri, off_t &offset)
964 {
965     int32_t fd = ReadMovingPhotoVideo(uri, OPEN_MOVING_PHOTO_VIDEO_CLOUD);
966     if (fd < 0) {
967         MEDIA_ERR_LOG("Failed to open video of moving photo: %{public}d", fd);
968         return E_ERR;
969     }
970 
971     if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
972         return fd;
973     }
974 
975     int64_t liveSize = 0;
976     if (MovingPhotoFileUtils::GetLivePhotoSize(fd, liveSize) != E_OK) {
977         return fd;
978     }
979 
980     struct stat st;
981     if (fstat(fd, &st) != E_OK || st.st_size < liveSize + PLAY_INFO_LEN + LIVE_TAG_LEN) {
982         MEDIA_ERR_LOG("video size is wrong");
983         return E_ERR;
984     }
985     offset = st.st_size - liveSize - PLAY_INFO_LEN - LIVE_TAG_LEN;
986     MEDIA_DEBUG_LOG("offset is %{public}" PRId64, offset);
987     return fd;
988 }
989 
ReadPrivateMovingPhoto(const string & uri)990 int32_t MediaLibraryManager::ReadPrivateMovingPhoto(const string &uri)
991 {
992     if (!CheckPhotoUri(uri)) {
993         MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
994         return E_ERR;
995     }
996     CHECK_AND_RETURN_RET_LOG(sDataShareHelper_ != nullptr, E_ERR,
997         "Failed to read video of moving photo, datashareHelper is nullptr");
998     string movingPhotoUri = uri;
999     MediaFileUtils::UriAppendKeyValue(movingPhotoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_PRIVATE_LIVE_PHOTO);
1000     Uri openMovingPhotoUri(movingPhotoUri);
1001     return sDataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
1002 }
1003 
GetMovingPhotoImageUri(const string & uri)1004 std::string MediaLibraryManager::GetMovingPhotoImageUri(const string &uri)
1005 {
1006     if (uri.empty()) {
1007         MEDIA_ERR_LOG("invalid uri: %{public}s", uri.c_str());
1008         return "";
1009     }
1010     if (MediaFileUtils::IsMediaLibraryUri(uri)) {
1011         return uri;
1012     }
1013     std::vector<std::string> uris;
1014     CHECK_AND_RETURN_RET(MediaFileUtils::SplitMovingPhotoUri(uri, uris), "");
1015     return uris[MOVING_PHOTO_IMAGE_POS];
1016 }
1017 
GetSandboxMovingPhotoTime(const string & uri)1018 int64_t MediaLibraryManager::GetSandboxMovingPhotoTime(const string& uri)
1019 {
1020     vector<string> uris;
1021     CHECK_AND_RETURN_RET(MediaFileUtils::SplitMovingPhotoUri(uri, uris), E_ERR);
1022     AppFileService::ModuleFileUri::FileUri imageFileUri(uris[MOVING_PHOTO_IMAGE_POS]);
1023     string imageRealPath = imageFileUri.GetRealPath();
1024     struct stat imageStatInfo {};
1025     CHECK_AND_RETURN_RET_LOG(stat(imageRealPath.c_str(), &imageStatInfo) == 0, E_ERR, "stat image error");
1026 
1027     int64_t imageDateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(imageStatInfo.st_mtim));
1028     AppFileService::ModuleFileUri::FileUri videoFileUri(uris[MOVING_PHOTO_VIDEO_POS]);
1029     string videoRealPath = videoFileUri.GetRealPath();
1030     struct stat videoStatInfo {};
1031     CHECK_AND_RETURN_RET_LOG(stat(videoRealPath.c_str(), &videoStatInfo) == 0, E_ERR, "stat video error");
1032     int64_t videoDateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(videoStatInfo.st_mtim));
1033     return imageDateModified >= videoDateModified ? imageDateModified : videoDateModified;
1034 }
1035 
GetMovingPhotoDateModifiedIPCExecute(const std::shared_ptr<DataShare::DataShareHelper> & helper,const string & fileId)1036 static int64_t GetMovingPhotoDateModifiedIPCExecute(
1037     const std::shared_ptr<DataShare::DataShareHelper> &helper, const string &fileId)
1038 {
1039     GetMovingPhotoDateModifiedReqBody reqBody;
1040     GetMovingPhotoDateModifiedRespBody respBody;
1041     reqBody.fileId = fileId;
1042     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_MOVING_PHOTO_DATE_MODIFIED);
1043 
1044     int32_t err = IPC::UserInnerIPCClient().SetDataShareHelper(helper).Call(businessCode, reqBody, respBody);
1045     if (err != E_OK) {
1046         MEDIA_ERR_LOG("get position fail. err:%{public}d", err);
1047         return E_ERR;
1048     }
1049 
1050     return respBody.dateModified;
1051 }
1052 
GetMovingPhotoDateModified(const string & uri)1053 int64_t MediaLibraryManager::GetMovingPhotoDateModified(const string &uri)
1054 {
1055     CHECK_AND_RETURN_RET_LOG(!uri.empty(), E_ERR, "Failed to check empty uri");
1056     if (!MediaFileUtils::IsMediaLibraryUri(uri)) {
1057         return GetSandboxMovingPhotoTime(uri);
1058     }
1059 
1060     CHECK_AND_RETURN_RET_LOG(CheckPhotoUri(uri), E_ERR, "Failed to check invalid uri: %{public}s", uri.c_str());
1061     Uri queryUri(PAH_QUERY_PHOTO);
1062     DataSharePredicates predicates;
1063     string fileId = MediaFileUtils::GetIdFromUri(uri);
1064     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1065 
1066     CHECK_AND_RETURN_RET_LOG(sDataShareHelper_ != nullptr, E_ERR, "sDataShareHelper_ is null");
1067     OperationObject object = OperationObject::UNKNOWN_OBJECT;
1068     if (!MediaAssetRdbStore::GetInstance()->IsQueryAccessibleViaSandBox(queryUri, object, predicates)) {
1069         return GetMovingPhotoDateModifiedIPCExecute(sDataShareHelper_, fileId);
1070     }
1071 
1072     DatashareBusinessError businessError;
1073     vector<string> columns = {
1074         MediaColumn::MEDIA_DATE_MODIFIED,
1075     };
1076     auto queryResultSet = sDataShareHelper_->Query(queryUri, predicates, columns, &businessError);
1077     CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, E_ERR, "queryResultSet is null");
1078     CHECK_AND_RETURN_RET_LOG(queryResultSet->GoToNextRow() == NativeRdb::E_OK, E_ERR, "Failed to GoToNextRow");
1079     return GetInt64Val(MediaColumn::MEDIA_DATE_MODIFIED, queryResultSet);
1080 }
1081 
CreatePhotoAssetProxy(CameraShotType cameraShotType,uint32_t callingUid,int32_t userId,uint32_t callingTokenId)1082 shared_ptr<PhotoAssetProxy> MediaLibraryManager::CreatePhotoAssetProxy(CameraShotType cameraShotType,
1083     uint32_t callingUid, int32_t userId, uint32_t callingTokenId)
1084 {
1085     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1086         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1087     MEDIA_INFO_LOG("dataShareHelper is ready, ret = %{public}d.", dataShareHelper != nullptr);
1088     shared_ptr<PhotoAssetProxy> photoAssetProxy = make_shared<PhotoAssetProxy>(dataShareHelper, cameraShotType,
1089         callingUid, userId, callingTokenId);
1090     return photoAssetProxy;
1091 }
1092 
GetUrisByOldUris(std::vector<std::string> uris)1093 std::unordered_map<std::string, std::string> MediaLibraryManager::GetUrisByOldUris(std::vector<std::string> uris)
1094 {
1095     MEDIA_INFO_LOG("Start request uris by old uris, size: %{public}zu", uris.size());
1096     return TabOldPhotosClient(*this).GetUrisByOldUris(uris);
1097 }
1098 
GetAlbumLpath(uint32_t ownerAlbumId,std::string & lpath)1099 int32_t MediaLibraryManager::GetAlbumLpath(uint32_t ownerAlbumId, std::string &lpath)
1100 {
1101     MEDIA_DEBUG_LOG("MediaLibraryManager::GetAlbumLpath Start.");
1102     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1103         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1104     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, E_FAIL, "dataShareHelper is nullptr");
1105 
1106     GetAlbumsLpathByIdsReqBody reqBody;
1107     reqBody.albumId = ownerAlbumId;
1108     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_PAH_QUERY_GET_ALBUMS_BY_IDS);
1109     GetAlbumsLpathByIdsRespBody respBody;
1110     int32_t errCode =
1111         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
1112     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "after IPC::UserDefineIPCClient().Call, errCode: %{public}d.",
1113         errCode);
1114     lpath = respBody.lpath;
1115     MEDIA_DEBUG_LOG("MediaLibraryManager::GetAlbumLpath End. lpath: %{public}s", lpath.c_str());
1116     return errCode;
1117 }
1118 
GetAlbumLpaths(uint32_t albumType,std::shared_ptr<DataShare::ResultSet> & resultSet)1119 int32_t MediaLibraryManager::GetAlbumLpaths(uint32_t albumType, std::shared_ptr<DataShare::ResultSet> &resultSet)
1120 {
1121     MEDIA_DEBUG_LOG("MediaLibraryManager::GetAlbumLpaths Start.");
1122     CHECK_AND_RETURN_RET_LOG(albumType == PhotoAlbumType::USER || albumType == PhotoAlbumType::SOURCE, E_FAIL,
1123         "GetAlbumLpaths albumType not support");
1124     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1125         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1126     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, E_FAIL, "dataShareHelper is nullptr");
1127 
1128     QueryAlbumsReqBody reqBody;
1129     reqBody.albumType = albumType;
1130     reqBody.albumSubType =
1131         (albumType == PhotoAlbumType::SOURCE ? PhotoAlbumSubType::SOURCE_GENERIC : PhotoAlbumSubType::USER_GENERIC);
1132     reqBody.columns = { PhotoAlbumColumns::ALBUM_ID, PhotoAlbumColumns::ALBUM_LPATH};
1133     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_PAH_QUERY_PHOTO_ALBUMS);
1134     QueryAlbumsRespBody respBody;
1135     int32_t errCode =
1136         IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody, respBody);
1137     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "after IPC::UserDefineIPCClient().Call, errCode: %{public}d.",
1138         errCode);
1139     resultSet = respBody.resultSet;
1140     MEDIA_DEBUG_LOG("MediaLibraryManager::GetAlbumLpaths End.");
1141     return errCode;
1142 }
1143 
RetainCloudMediaAsset(CloudMediaRetainType retainType)1144 int32_t MediaLibraryManager::RetainCloudMediaAsset(CloudMediaRetainType retainType)
1145 {
1146     MEDIA_DEBUG_LOG("MediaLibraryManager::RetainCloudMediaAsset Start.");
1147     shared_ptr<DataShare::DataShareHelper> dataShareHelper =
1148         DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
1149     CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, E_FAIL, "dataShareHelper is nullptr");
1150 
1151     RetainCloudMediaAssetReqBody reqBody;
1152     reqBody.cloudMediaRetainType = static_cast<int32_t>(retainType);
1153     uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_RETAIN_CLOUDMEDIA_ASSET);
1154     int32_t errCode = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper).Call(businessCode, reqBody);
1155     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "after IPC::UserDefineIPCClient().Call, errCode: %{public}d.",
1156         errCode);
1157     MEDIA_DEBUG_LOG("MediaLibraryManager::RetainCloudMediaAsset End.");
1158     return errCode;
1159 }
1160 } // namespace Media
1161 } // namespace OHOS
1162