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