• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #define MLOG_TAG "SmartAlbum"
16 
17 #include "medialibrary_smartalbum_map_operations.h"
18 
19 #include "datashare_predicates.h"
20 #include "datashare_result_set.h"
21 #include "fetch_result.h"
22 #include "medialibrary_common_utils.h"
23 #include "medialibrary_data_manager.h"
24 #include "medialibrary_dir_operations.h"
25 #include "medialibrary_errno.h"
26 #include "medialibrary_file_operations.h"
27 #include "medialibrary_notify.h"
28 #include "medialibrary_object_utils.h"
29 #include "medialibrary_smartalbum_operations.h"
30 #include "media_file_utils.h"
31 #include "media_log.h"
32 #include "rdb_utils.h"
33 #include "result_set_utils.h"
34 
35 using namespace std;
36 using namespace OHOS::NativeRdb;
37 using namespace OHOS::DataShare;
38 using namespace OHOS::RdbDataShareAdapter;
39 
40 namespace OHOS {
41 namespace Media {
42 using ChangeType = AAFwk::ChangeInfo::ChangeType;
43 static const std::string HASH_COLLISION_SUFFIX = "(1)";
44 static const std::string ASSET_RECYCLE_SUFFIX = "-copy";
45 static const std::string DIR_RECYCLE_SUFFIX = "_recycle";
46 const std::string RECYCLE_DIR = ".recycle/";
47 constexpr int64_t ONEDAY_TO_SEC = 60 * 60 * 24;
48 constexpr int32_t HASH_COLLISION_MAX_TRY = 10;
49 std::atomic<bool> MediaLibrarySmartAlbumMapOperations::isInterrupt_ = false;
50 mutex MediaLibrarySmartAlbumMapOperations::g_opMutex;
51 
MakeSuffixPathName(const string & assetPath)52 static string MakeSuffixPathName(const string &assetPath)
53 {
54     string outSuffixPath;
55     size_t extensionIndex = assetPath.rfind(".");
56     if (extensionIndex != string::npos) {
57         string extension = assetPath.substr(extensionIndex);
58         string noExtensionPath = assetPath.substr(0, extensionIndex);
59         outSuffixPath = noExtensionPath + ASSET_RECYCLE_SUFFIX + extension;
60     } else {
61         outSuffixPath = assetPath + ASSET_RECYCLE_SUFFIX;
62     }
63     MEDIA_DEBUG_LOG("outSuffixPath = %{public}s", outSuffixPath.c_str());
64     return outSuffixPath;
65 }
66 
QueryAgeingTrashFiles()67 static shared_ptr<NativeRdb::ResultSet> QueryAgeingTrashFiles()
68 {
69     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
70     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, nullptr, "UniStore is nullptr");
71 
72     MediaLibraryCommand querySmartAlbumCmd(OperationObject::SMART_ALBUM, OperationType::QUERY);
73     querySmartAlbumCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUM_DB_ID, to_string(TRASH_ALBUM_ID_VALUES));
74     auto resultSet = uniStore->Query(querySmartAlbumCmd, { SMARTALBUM_DB_EXPIRED_TIME });
75     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "Failed to query rdb");
76 
77     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "Failed to query rdb");
78     auto recycleDays = GetInt32Val(SMARTALBUM_DB_EXPIRED_TIME, resultSet);
79     resultSet.reset();
80 
81     int64_t dateAgeing = MediaFileUtils::UTCTimeSeconds();
82     string strAgeingQueryCondition = MEDIA_DATA_DB_DATE_TRASHED + "> 0" + " AND " + to_string(dateAgeing) + " - " +
83         MEDIA_DATA_DB_DATE_TRASHED + " > " + to_string(recycleDays * ONEDAY_TO_SEC);
84     MEDIA_INFO_LOG("StrAgeingQueryCondition = %{public}s", strAgeingQueryCondition.c_str());
85 
86     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
87     cmd.GetAbsRdbPredicates()->SetWhereClause(strAgeingQueryCondition);
88     return MediaLibraryObjectUtils::QueryWithCondition(cmd, {});
89 }
90 
HandleAgingOperation()91 int32_t MediaLibrarySmartAlbumMapOperations::HandleAgingOperation()
92 {
93     auto resultSet = QueryAgeingTrashFiles();
94     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Failed to query ageing trash files");
95 
96     int32_t count = 0;
97     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
98         "Get query result count failed");
99     if (count == 0) {
100         MEDIA_INFO_LOG("Have no ageing trash file");
101         return E_SUCCESS;
102     }
103 
104     auto fetchFileResult = make_shared<FetchResult<FileAsset>>();
105     for (int32_t row = 0; row < count; row++) {
106         if (MediaLibrarySmartAlbumMapOperations::GetInterrupt()) {
107             MEDIA_INFO_LOG("recieve interrupt, stop aging");
108             return E_ERR;
109         }
110 
111         unique_ptr<FileAsset> fileAsset = fetchFileResult->GetObjectFromRdb(resultSet, row);
112         CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Get fileAsset failed");
113         int32_t errCode;
114         if (fileAsset->GetIsTrash() == TRASHED_ASSET) {
115             errCode = MediaLibraryObjectUtils::DeleteFileObj(move(fileAsset));
116         } else if (fileAsset->GetIsTrash() == TRASHED_DIR) {
117             errCode = MediaLibraryObjectUtils::DeleteDirObj(move(fileAsset));
118         } else {
119             MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
120             errCode = MediaLibraryObjectUtils::DeleteInfoByIdInDb(cmd, to_string(fileAsset->GetId()));
121         }
122         CHECK_AND_RETURN_RET_LOG(errCode >= 0, errCode, "Failed to delete during trash aging: %{public}d", errCode);
123     }
124     return E_SUCCESS;
125 }
126 
GetAssetRecycle(const int32_t assetId,string & filePath,string & outTrashDirPath)127 static string GetAssetRecycle(const int32_t assetId, string &filePath, string &outTrashDirPath)
128 {
129     auto dirQuerySetMap = MediaLibraryDataManager::GetDirQuerySetMap();
130     for (pair<string, DirAsset> dirPair : dirQuerySetMap) {
131         DirAsset dirAsset = dirPair.second;
132         string rootPath = ROOT_MEDIA_DIR + dirAsset.GetDirectory();
133         if (filePath.find(rootPath) == 0) {
134             string trashDirPath = rootPath + RECYCLE_DIR;
135             return trashDirPath;
136         }
137     }
138     return "";
139 }
140 
MakeRecycleDisplayName(const int32_t assetId,const string & trashDirPath,string & outRecyclePath)141 static int32_t MakeRecycleDisplayName(const int32_t assetId, const string &trashDirPath, string &outRecyclePath)
142 {
143     shared_ptr<FileAsset> fileAsset = MediaLibraryObjectUtils::GetFileAssetFromId(to_string(assetId));
144     if (fileAsset == nullptr) {
145         MEDIA_ERR_LOG("Failed to get asset, assetId = %{public}d", assetId);
146         return E_GET_ASSET_FAIL;
147     }
148     string hashDisplayName;
149     string name = to_string(fileAsset->GetId()) + fileAsset->GetRelativePath() + fileAsset->GetDisplayName();
150     int32_t errorCode = MediaLibraryCommonUtils::GenKeySHA256(name, hashDisplayName);
151     if (errorCode != E_OK) {
152         MEDIA_ERR_LOG("Failed to genKey, err: %{public}d", errorCode);
153         return E_MAKE_HASHNAME_FAIL;
154     }
155     string extension;
156     outRecyclePath = trashDirPath + hashDisplayName;
157     if (fileAsset->GetMediaType() != MEDIA_TYPE_ALBUM) {
158         size_t extensionIndex = fileAsset->GetDisplayName().rfind(".");
159         if (extensionIndex != string::npos) {
160             extension = fileAsset->GetDisplayName().substr(extensionIndex);
161         }
162         outRecyclePath += extension;
163         MEDIA_INFO_LOG("Asset outRecyclePath = %{private}s", outRecyclePath.c_str());
164     }
165     int32_t suffixTime = 0;
166     while (MediaLibraryObjectUtils::IsColumnValueExist(outRecyclePath, MEDIA_DATA_DB_RECYCLE_PATH)) {
167         if (suffixTime > HASH_COLLISION_MAX_TRY) {
168             MEDIA_ERR_LOG("Reach max hash collision times");
169             errorCode = E_MAKE_HASHNAME_FAIL;
170             break;
171         }
172         name += HASH_COLLISION_SUFFIX;
173         errorCode = MediaLibraryCommonUtils::GenKeySHA256(name, hashDisplayName);
174         if (errorCode != E_OK) {
175             MEDIA_ERR_LOG("Failed to genKey, err: %{public}d", errorCode);
176             return E_MAKE_HASHNAME_FAIL;
177         }
178         outRecyclePath = trashDirPath + hashDisplayName;
179         if (!extension.empty()) {
180             outRecyclePath += extension;
181         }
182         suffixTime++;
183     }
184     return errorCode;
185 }
186 
UpdateChildRecycleInfoInDb(const int32_t assetId)187 static int32_t UpdateChildRecycleInfoInDb(const int32_t assetId)
188 {
189     ValuesBucket values;
190     values.PutLong(MEDIA_DATA_DB_DATE_TRASHED, 0);
191     values.PutInt(MEDIA_DATA_DB_IS_TRASH, 0);
192     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
193     return MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd, to_string(assetId));
194 }
195 
RecycleChildAssetsInfoUtil(const int32_t parentId)196 static int32_t RecycleChildAssetsInfoUtil(const int32_t parentId)
197 {
198     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
199     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
200 
201     MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
202     queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_PARENT_ID, to_string(parentId))->And()->
203         EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(TRASHED_DIR_CHILD));
204     auto resultSet = uniStore->Query(queryCmd, { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE });
205     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "QueryResultSet is nullptr");
206 
207     int32_t errCode = E_SUCCESS;
208     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
209         int32_t fileId = GetInt32Val(MEDIA_DATA_DB_ID, resultSet);
210         errCode = UpdateChildRecycleInfoInDb(fileId);
211         CHECK_AND_RETURN_RET_LOG(errCode > 0, errCode, "Failed to UpdateChildRecycleInfoInDb");
212 
213         if (GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, resultSet) == MEDIA_TYPE_ALBUM) {
214             errCode = RecycleChildAssetsInfoUtil(fileId);
215             CHECK_AND_RETURN_RET_LOG(errCode >= 0, errCode, "Failed to RecycleChildAssetsInfoUtil");
216         }
217     }
218     return errCode;
219 }
220 
GetNewPath(const string & path,const string & srcRelPath,const string & newRelPath)221 static string GetNewPath(const string &path, const string &srcRelPath, const string &newRelPath)
222 {
223     if ((path.find(srcRelPath) != 0) && (path.find(ROOT_MEDIA_DIR + srcRelPath) != 0)) {
224         return "";
225     }
226     string newPath = newRelPath;
227     if (path.find(ROOT_MEDIA_DIR) != string::npos) {
228         newPath = ROOT_MEDIA_DIR + newPath;
229     }
230     newPath += path.substr(path.find(srcRelPath) + srcRelPath.length());
231     return newPath;
232 }
233 
RecycleChildSameNameInfoUtil(const int32_t parentId,const string & srcRelPath,const string & newRelPath,bool isFirstLevel)234 static int32_t RecycleChildSameNameInfoUtil(const int32_t parentId, const string &srcRelPath, const string &newRelPath,
235     bool isFirstLevel)
236 {
237     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
238     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
239 
240     MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
241     queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_PARENT_ID, to_string(parentId));
242     vector<string> columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_MEDIA_TYPE,
243         MEDIA_DATA_DB_IS_TRASH, MEDIA_DATA_DB_RECYCLE_PATH, MEDIA_DATA_DB_RELATIVE_PATH };
244     auto result = uniStore->Query(queryCmd, columns);
245     CHECK_AND_RETURN_RET_LOG(result != nullptr, E_HAS_DB_ERROR, "Failed to obtain value from database");
246 
247     int32_t count = -1;
248     CHECK_AND_RETURN_RET(result->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR);
249     for (int32_t i = 0; i < count; i++) {
250         CHECK_AND_RETURN_RET(result->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR);
251         ValuesBucket values;
252         string relativePath = GetStringVal(MEDIA_DATA_DB_RELATIVE_PATH, result);
253         values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, GetNewPath(relativePath, srcRelPath, newRelPath));
254 
255         int32_t mediaType = GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, result);
256         if (isFirstLevel && (mediaType != MEDIA_TYPE_ALBUM)) {
257             string newParentName = newRelPath;
258             // delete the final '/' in relative_path
259             newParentName.pop_back();
260             newParentName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(newParentName);
261             values.PutString(MEDIA_DATA_DB_BUCKET_NAME, newParentName);
262         }
263 
264         // Update recycle_path for TRASHED_ASSET and TRASHED_DIR, update data for TRASHED_DIR_CHILD.
265         int32_t isTrash = GetInt32Val(MEDIA_DATA_DB_IS_TRASH, result);
266         if (isTrash == TRASHED_DIR_CHILD) {
267             string path = GetStringVal(MEDIA_DATA_DB_FILE_PATH, result);
268             values.PutString(MEDIA_DATA_DB_FILE_PATH, GetNewPath(path, srcRelPath, newRelPath));
269         } else {
270             string recyclePath = GetStringVal(MEDIA_DATA_DB_RECYCLE_PATH, result);
271             values.PutString(MEDIA_DATA_DB_RECYCLE_PATH, GetNewPath(recyclePath, srcRelPath, newRelPath));
272         }
273 
274         int32_t fileId = GetInt32Val(MEDIA_DATA_DB_ID, result);
275         MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
276         updateCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(fileId));
277         int32_t changedRows = -1;
278         auto ret = uniStore->Update(updateCmd, changedRows);
279         if ((ret != NativeRdb::E_OK) || (changedRows <= 0)) {
280             MEDIA_ERR_LOG("Update DB failed. Ret: %{public}d. Update fileId: %{public}d", ret, fileId);
281             return E_HAS_DB_ERROR;
282         }
283 
284         if (mediaType == MEDIA_TYPE_ALBUM) {
285             ret = RecycleChildSameNameInfoUtil(fileId, srcRelPath, newRelPath, false);
286             CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_HAS_DB_ERROR, "Update DB failed. fileId: %{public}d", fileId);
287         }
288     }
289     return E_SUCCESS;
290 }
291 
RecycleDir(const shared_ptr<FileAsset> & fileAsset)292 static int32_t RecycleDir(const shared_ptr<FileAsset> &fileAsset)
293 {
294     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
295     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
296 
297     ValuesBucket values;
298     int32_t parentId = MediaLibraryObjectUtils::CreateDirWithPath(ROOT_MEDIA_DIR + fileAsset->GetRelativePath());
299     if (parentId != fileAsset->GetParent()) {
300         values.PutInt(MEDIA_DATA_DB_PARENT_ID, parentId);
301     }
302 
303     bool hasSameName = false;
304     string assetPath = fileAsset->GetRecyclePath();
305     while (MediaLibraryObjectUtils::IsFileExistInDb(assetPath)) {
306         hasSameName = true;
307         assetPath = assetPath + DIR_RECYCLE_SUFFIX;
308     }
309 
310     if (!MediaFileUtils::RenameDir(fileAsset->GetPath(), assetPath)) {
311         if (errno == ENAMETOOLONG) {
312             return -ENAMETOOLONG;
313         }
314         return E_RENAME_DIR_FAIL;
315     }
316 
317     if (hasSameName) {
318         fileAsset->SetRecyclePath(assetPath);
319         // update dir info
320         string newName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(assetPath);
321         values.PutString(MEDIA_DATA_DB_NAME, newName);
322         values.PutString(MEDIA_DATA_DB_TITLE, newName);
323         values.PutString(MEDIA_DATA_DB_RECYCLE_PATH, assetPath);
324 
325         // update child info
326         string srcRelPath = fileAsset->GetRelativePath() + fileAsset->GetDisplayName() + "/";
327         string newRelPath = fileAsset->GetRelativePath() + newName + "/";
328         RecycleChildSameNameInfoUtil(fileAsset->GetId(), srcRelPath, newRelPath, true);
329     }
330 
331     if (!values.IsEmpty()) {
332         MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
333         updateCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(fileAsset->GetId()));
334         int32_t changedRows = -1;
335         return uniStore->Update(updateCmd, changedRows);
336     }
337 
338     return E_SUCCESS;
339 }
340 
UpdateRecycleInfoInDb(const int32_t assetId,const string & realPath)341 static int32_t UpdateRecycleInfoInDb(const int32_t assetId, const string &realPath)
342 {
343     ValuesBucket values;
344     values.PutString(MEDIA_DATA_DB_FILE_PATH, realPath);
345     values.PutString(MEDIA_DATA_DB_RECYCLE_PATH, "");
346     values.PutLong(MEDIA_DATA_DB_DATE_TRASHED, 0);
347     values.PutInt(MEDIA_DATA_DB_IS_TRASH, 0);
348     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
349     return MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd, to_string(assetId));
350 }
351 
RecycleDirAssetsInfoUtil(const shared_ptr<FileAsset> & fileAsset)352 static int32_t RecycleDirAssetsInfoUtil(const shared_ptr<FileAsset> &fileAsset)
353 {
354     if (!MediaFileUtils::IsDirectory(fileAsset->GetPath())) {
355         MEDIA_ERR_LOG("recycle dir is not exists");
356         return E_RECYCLE_FILE_IS_NULL;
357     }
358 
359     auto errorCode = RecycleDir(fileAsset);
360     CHECK_AND_RETURN_RET_LOG(errorCode == E_SUCCESS, errorCode, "Failed to RecycleDir");
361 
362     errorCode = RecycleChildAssetsInfoUtil(fileAsset->GetId());
363     CHECK_AND_RETURN_RET_LOG(errorCode >= 0, errorCode, "Failed to recycleChildAssetsInfoUtil");
364 
365     string dirRealPath = fileAsset->GetRecyclePath();
366     return UpdateRecycleInfoInDb(fileAsset->GetId(), dirRealPath);
367 }
368 
RecycleFile(const shared_ptr<FileAsset> & fileAsset)369 static int32_t RecycleFile(const shared_ptr<FileAsset> &fileAsset)
370 {
371     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
372     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
373 
374     ValuesBucket values;
375     int32_t parentId = MediaLibraryObjectUtils::CreateDirWithPath(ROOT_MEDIA_DIR + fileAsset->GetRelativePath());
376     if (parentId != fileAsset->GetParent()) {
377         values.PutInt(MEDIA_DATA_DB_PARENT_ID, parentId);
378         values.PutInt(MEDIA_DATA_DB_BUCKET_ID, parentId);
379     }
380 
381     bool hasSameName = false;
382     string assetPath = fileAsset->GetRecyclePath();
383     while (MediaLibraryObjectUtils::IsFileExistInDb(assetPath)) {
384         hasSameName = true;
385         assetPath = MakeSuffixPathName(assetPath);
386     }
387 
388     if (!MediaFileUtils::MoveFile(fileAsset->GetPath(), assetPath)) {
389         if (errno == ENAMETOOLONG) {
390             return -ENAMETOOLONG;
391         }
392         return E_RENAME_FILE_FAIL;
393     }
394     MediaLibraryObjectUtils::InvalidateThumbnail(to_string(fileAsset->GetId()));
395 
396     if (hasSameName) {
397         fileAsset->SetRecyclePath(assetPath);
398         string newName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(assetPath);
399         values.PutString(MEDIA_DATA_DB_NAME, newName);
400         values.PutString(MEDIA_DATA_DB_RECYCLE_PATH, assetPath);
401         MediaType mediaType = fileAsset->GetMediaType();
402         if ((mediaType != MEDIA_TYPE_VIDEO) && (mediaType != MEDIA_TYPE_AUDIO)) {
403             values.PutString(MEDIA_DATA_DB_TITLE, newName);
404         }
405     }
406 
407     if (!values.IsEmpty()) {
408         MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
409         updateCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(fileAsset->GetId()));
410         int32_t changedRows = -1;
411         return uniStore->Update(updateCmd, changedRows);
412     }
413 
414     return E_SUCCESS;
415 }
416 
RecycleFileAssetsInfoUtil(const shared_ptr<FileAsset> & fileAsset)417 static int32_t RecycleFileAssetsInfoUtil(const shared_ptr<FileAsset> &fileAsset)
418 {
419     string recyclePath = fileAsset->GetPath();
420     if (!MediaFileUtils::IsFileExists(recyclePath)) {
421         MEDIA_ERR_LOG("RecycleFile is null, fileid = %{private}d", fileAsset->GetId());
422         return E_RECYCLE_FILE_IS_NULL;
423     }
424 
425     int32_t errorCode = RecycleFile(fileAsset);
426     CHECK_AND_RETURN_RET_LOG(errorCode >= 0, errorCode, "Failed to recycleFile");
427 
428     string fileRealPath = fileAsset->GetRecyclePath();
429     return UpdateRecycleInfoInDb(fileAsset->GetId(), fileRealPath);
430 }
431 
RemoveTrashAssetsInfoUtil(const int32_t fileAssetId)432 static int32_t RemoveTrashAssetsInfoUtil(const int32_t fileAssetId)
433 {
434     shared_ptr<FileAsset> fileAsset = MediaLibraryObjectUtils::GetFileAssetFromId(to_string(fileAssetId));
435     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_GET_ASSET_FAIL, "fileAsset is nullptr, assetId: %{public}d",
436         fileAssetId);
437 
438     int32_t ret = 0;
439     if (fileAsset->GetMediaType() != MEDIA_TYPE_ALBUM) {
440         ret = RecycleFileAssetsInfoUtil(fileAsset);
441     } else {
442         ret = RecycleDirAssetsInfoUtil(fileAsset);
443     }
444     return ret;
445 }
446 
UpdateFavoriteAssetsInfoUtil(const int32_t fileAssetId,const bool isFavorites)447 static int32_t UpdateFavoriteAssetsInfoUtil(const int32_t fileAssetId, const bool isFavorites)
448 {
449     ValuesBucket values;
450     values.PutInt(MEDIA_DATA_DB_IS_FAV, isFavorites ? 1 : 0);
451     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
452     return MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd, to_string(fileAssetId));
453 }
454 
HandleRemoveAssetOperation(const int32_t albumId,const int32_t childFileAssetId,MediaLibraryCommand & cmd)455 int32_t MediaLibrarySmartAlbumMapOperations::HandleRemoveAssetOperation(const int32_t albumId,
456     const int32_t childFileAssetId, MediaLibraryCommand &cmd)
457 {
458     lock_guard<mutex> guard(g_opMutex);
459     int32_t errorCode = E_SUCCESS;
460     if (albumId == TRASH_ALBUM_ID_VALUES) {
461         errorCode = RemoveTrashAssetsInfoUtil(childFileAssetId);
462     } else if (albumId == FAVOURITE_ALBUM_ID_VALUES) {
463         errorCode = UpdateFavoriteAssetsInfoUtil(childFileAssetId, false);
464     }
465     CHECK_AND_RETURN_RET_LOG(errorCode >= 0, errorCode, "Failed to handleRemoveAssetOperations");
466     cmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUMMAP_DB_ALBUM_ID, to_string(albumId))->And()->
467         EqualTo(SMARTALBUMMAP_DB_CHILD_ASSET_ID, to_string(childFileAssetId));
468     return MediaLibraryObjectUtils::DeleteInfoByIdInDb(cmd);
469 }
470 
UpdateChildTrashInfoInDb(const int32_t assetId,const int64_t trashDate)471 static int32_t UpdateChildTrashInfoInDb(const int32_t assetId, const int64_t trashDate)
472 {
473     ValuesBucket values;
474     values.PutLong(MEDIA_DATA_DB_DATE_TRASHED, trashDate);
475     values.PutInt(MEDIA_DATA_DB_IS_TRASH, TRASHED_DIR_CHILD);
476     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
477     return MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd, to_string(assetId));
478 }
479 
TrashChildAssetsInfoUtil(const int32_t parentId,const int64_t & trashDate)480 static int32_t TrashChildAssetsInfoUtil(const int32_t parentId, const int64_t &trashDate)
481 {
482     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
483     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
484 
485     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
486     string parentPath = MediaLibraryObjectUtils::GetPathByIdFromDb(to_string(parentId));
487     cmd.GetAbsRdbPredicates()->Like(MEDIA_DATA_DB_FILE_PATH, parentPath + "/%")->And()->
488         EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
489 
490     auto result = uniStore->Query(cmd, { MEDIA_DATA_DB_ID });
491     CHECK_AND_RETURN_RET_LOG(result != nullptr, E_HAS_DB_ERROR, "QueryResultSet is nullptr");
492 
493     auto count = 0;
494     CHECK_AND_RETURN_RET_LOG(result->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
495         "Get query result count failed");
496     if (count == 0) {
497         MEDIA_INFO_LOG("Have no child assets");
498         return E_SUCCESS;
499     }
500 
501     while (result->GoToNextRow() == NativeRdb::E_OK) {
502         auto ret = UpdateChildTrashInfoInDb(GetInt32Val(MEDIA_DATA_DB_ID, result), trashDate);
503         CHECK_AND_RETURN_RET_LOG(ret >= 0, ret, "Failed to updateChildTrashInfoInDb");
504     }
505     return E_SUCCESS;
506 }
507 
UpdateTrashInfoInDb(const int32_t assetId,const int64_t trashDate,string & recyclePath,const string & oldPath,const uint32_t trashType)508 static int32_t UpdateTrashInfoInDb(const int32_t assetId, const int64_t trashDate, string &recyclePath,
509     const string &oldPath, const uint32_t trashType)
510 {
511     ValuesBucket values;
512     values.PutString(MEDIA_DATA_DB_FILE_PATH, recyclePath);
513     values.PutString(MEDIA_DATA_DB_RECYCLE_PATH, oldPath);
514     values.PutLong(MEDIA_DATA_DB_DATE_TRASHED, trashDate);
515     values.PutInt(MEDIA_DATA_DB_IS_TRASH, trashType);
516     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE, values);
517     return MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd, to_string(assetId));
518 }
519 
TrashDirAssetsInfoUtil(const int32_t assetId)520 static int32_t TrashDirAssetsInfoUtil(const int32_t assetId)
521 {
522     string oldPath = MediaLibraryObjectUtils::GetPathByIdFromDb(to_string(assetId));
523     string trashDirPath = GetAssetRecycle(assetId, oldPath, trashDirPath);
524     CHECK_AND_RETURN_RET_LOG(!trashDirPath.empty(), E_CHECK_ROOT_DIR_FAIL, "Failed to get recycle dir");
525     if (!MediaFileUtils::IsDirectory(trashDirPath)) {
526         if (!MediaFileUtils::CreateDirectory(trashDirPath)) {
527             MEDIA_ERR_LOG("TrashDirPath create failed");
528             return E_CREATE_TRASHDIR_FAIL;
529         }
530     }
531     string recyclePath;
532     auto errorCode = MakeRecycleDisplayName(assetId, trashDirPath, recyclePath);
533     CHECK_AND_RETURN_RET_LOG(errorCode == E_SUCCESS, errorCode, "Failed to makeRecycleDisplayName");
534     if (!MediaFileUtils::RenameDir(oldPath, recyclePath)) {
535         return E_MODIFY_DATA_FAIL;
536     }
537     int64_t trashDate = MediaFileUtils::UTCTimeSeconds();
538     errorCode = TrashChildAssetsInfoUtil(assetId, trashDate);
539     CHECK_AND_RETURN_RET_LOG(errorCode == E_SUCCESS, errorCode, "Failed to trashChildAssetsInfoUtil");
540     return UpdateTrashInfoInDb(assetId, trashDate, recyclePath, oldPath, TRASHED_DIR);
541 }
542 
TrashFileAssetsInfoUtil(const int32_t assetId)543 static int32_t TrashFileAssetsInfoUtil(const int32_t assetId)
544 {
545     string oldPath = MediaLibraryObjectUtils::GetPathByIdFromDb(to_string(assetId));
546     string trashDirPath = GetAssetRecycle(assetId, oldPath, trashDirPath);
547     CHECK_AND_RETURN_RET_LOG(!trashDirPath.empty(), E_CHECK_ROOT_DIR_FAIL, "Failed to get recycle dir");
548     if (!MediaFileUtils::IsDirectory(trashDirPath)) {
549         if (!MediaFileUtils::CreateDirectory(trashDirPath)) {
550             MEDIA_ERR_LOG("TrashDirPath create failed");
551             return E_CREATE_TRASHDIR_FAIL;
552         }
553     }
554     string recyclePath;
555     auto errorCode = MakeRecycleDisplayName(assetId, trashDirPath, recyclePath);
556     CHECK_AND_RETURN_RET_LOG(errorCode == E_SUCCESS, errorCode, "Failed to make recycle display name");
557     errorCode = MediaFileUtils::ModifyAsset(oldPath, recyclePath);
558     CHECK_AND_RETURN_RET_LOG(errorCode == E_SUCCESS, errorCode, "Failed to modifyAsset");
559     MediaLibraryObjectUtils::InvalidateThumbnail(to_string(assetId));
560     int64_t trashDate = MediaFileUtils::UTCTimeSeconds();
561     return UpdateTrashInfoInDb(assetId, trashDate, recyclePath, oldPath, TRASHED_ASSET);
562 }
563 
InsertTrashAssetsInfoUtil(const int32_t fileAssetId)564 static int32_t InsertTrashAssetsInfoUtil(const int32_t fileAssetId)
565 {
566     shared_ptr<FileAsset> fileAsset = MediaLibraryObjectUtils::GetFileAssetFromId(to_string(fileAssetId));
567     if (fileAsset == nullptr) {
568         MEDIA_ERR_LOG("FileAsset is nullptr");
569         return E_GET_ASSET_FAIL;
570     }
571     if (fileAsset->GetDateTrashed() != 0) {
572         return E_IS_RECYCLED;
573     }
574     if (fileAsset->GetMediaType() != MEDIA_TYPE_ALBUM) {
575         return TrashFileAssetsInfoUtil(fileAssetId);
576     } else {
577         return TrashDirAssetsInfoUtil(fileAssetId);
578     }
579 }
580 
HandleAddAssetOperation(const int32_t albumId,const int32_t childFileAssetId,const int32_t childAlbumId,MediaLibraryCommand & cmd)581 int32_t MediaLibrarySmartAlbumMapOperations::HandleAddAssetOperation(const int32_t albumId,
582     const int32_t childFileAssetId, const int32_t childAlbumId, MediaLibraryCommand &cmd)
583 {
584     MEDIA_DEBUG_LOG("HandleAddAssetOperations albumId = %{public}d, childFileAssetId = %{public}d",
585         albumId, childFileAssetId);
586     lock_guard<mutex> guard(g_opMutex);
587     int32_t errorCode = E_SUCCESS;
588     if (albumId == TRASH_ALBUM_ID_VALUES) {
589         errorCode = InsertTrashAssetsInfoUtil(childFileAssetId);
590     } else if (albumId == FAVOURITE_ALBUM_ID_VALUES) {
591         errorCode = UpdateFavoriteAssetsInfoUtil(childFileAssetId, true);
592     }
593     CHECK_AND_RETURN_RET_LOG(errorCode >= 0, errorCode, "Failed to handleAddAssetOperations");
594     if (childAlbumId != DEFAULT_ALBUMID) {
595         if (!MediaLibraryObjectUtils::IsParentSmartAlbum(albumId, true)) {
596             MEDIA_ERR_LOG("Child can not add smart album");
597             return E_CHILD_CAN_NOT_ADD_SMARTALBUM;
598         }
599     }
600     if (childFileAssetId != DEFAULT_ASSETID) {
601         if (MediaLibraryObjectUtils::IsParentSmartAlbum(albumId)) {
602             MEDIA_ERR_LOG("Parent can not add assets");
603             return E_PARENT_CAN_NOT_ADDASSETS;
604         }
605     }
606     return MediaLibraryObjectUtils::InsertInDb(cmd);
607 }
608 
HandleSmartAlbumMapOperation(MediaLibraryCommand & cmd)609 int32_t MediaLibrarySmartAlbumMapOperations::HandleSmartAlbumMapOperation(MediaLibraryCommand &cmd)
610 {
611     ValueObject valueObject;
612     ValuesBucket values = cmd.GetValueBucket();
613     int32_t albumId = DEFAULT_ALBUMID;
614     if (values.GetObject(SMARTALBUMMAP_DB_ALBUM_ID, valueObject)) {
615         valueObject.GetInt(albumId);
616     }
617     CHECK_AND_RETURN_RET_LOG(MediaLibraryObjectUtils::IsSmartAlbumExistInDb(albumId),
618         E_SMARTALBUM_IS_NOT_EXISTED, "Failed to get smartAlbumId");
619     int32_t childAssetId = DEFAULT_ASSETID;
620     int32_t childAlbumId = DEFAULT_ALBUMID;
621     if (values.GetObject(SMARTALBUMMAP_DB_CHILD_ASSET_ID, valueObject)) {
622         valueObject.GetInt(childAssetId);
623     }
624     if (values.GetObject(SMARTALBUMMAP_DB_CHILD_ALBUM_ID, valueObject)) {
625         valueObject.GetInt(childAlbumId);
626     }
627     // childAssetId and childAlbumId only one has value
628     if ((childAlbumId == DEFAULT_ALBUMID) && (childAssetId == DEFAULT_ASSETID)) {
629         MEDIA_ERR_LOG("GetObject failed");
630         return E_GET_VALUEBUCKET_FAIL;
631     }
632     if (childAlbumId != DEFAULT_ALBUMID) {
633         CHECK_AND_RETURN_RET_LOG(MediaLibraryObjectUtils::IsSmartAlbumExistInDb(childAlbumId),
634             E_SMARTALBUM_IS_NOT_EXISTED, "Failed to get childAlbumId");
635     }
636     if (childAssetId != DEFAULT_ASSETID) {
637         CHECK_AND_RETURN_RET_LOG(MediaLibraryObjectUtils::IsAssetExistInDb(childAssetId,
638             true), E_GET_ASSET_FAIL, "Failed to get childAssetId");
639     }
640     MEDIA_INFO_LOG("childAssetId = %{public}d , childAlbumId = %{public}d", childAssetId, childAlbumId);
641     int32_t errCode = E_ERR;
642     switch (cmd.GetOprnType()) {
643         case OperationType::CREATE:
644             errCode = HandleAddAssetOperation(albumId, childAssetId, childAlbumId, cmd);
645             break;
646         case OperationType::DELETE:
647             errCode = HandleRemoveAssetOperation(albumId, childAssetId, cmd);
648             break;
649         case OperationType::AGING:
650             errCode = HandleAgingOperation();
651             break;
652         default:
653             MEDIA_WARN_LOG("Unknown operation type %{private}d", cmd.GetOprnType());
654             break;
655         }
656     return errCode;
657 }
658 
SetInterrupt(bool interrupt)659 void MediaLibrarySmartAlbumMapOperations::SetInterrupt(bool interrupt)
660 {
661     isInterrupt_ = interrupt;
662 }
663 
GetInterrupt()664 bool MediaLibrarySmartAlbumMapOperations::GetInterrupt()
665 {
666     return isInterrupt_.load();
667 }
668 } // namespace Media
669 } // namespace OHOS
670