• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024-2025 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 
16 #define MLOG_TAG "CloudMediaAssetManager"
17 
18 #include "cloud_media_asset_manager.h"
19 
20 #include <iostream>
21 #include <chrono>
22 #include <mutex>
23 #include <cinttypes>
24 
25 #include "abs_rdb_predicates.h"
26 #include "album_accurate_refresh.h"
27 #include "asset_accurate_refresh.h"
28 #include "cloud_media_asset_download_operation.h"
29 #include "cloud_media_asset_types.h"
30 #include "cloud_sync_notify_handler.h"
31 #include "cloud_sync_helper.h"
32 #include "cloud_sync_utils.h"
33 #include "media_column.h"
34 #include "media_file_utils.h"
35 #include "media_log.h"
36 #include "medialibrary_album_fusion_utils.h"
37 #include "medialibrary_async_worker.h"
38 #include "medialibrary_command.h"
39 #include "medialibrary_db_const.h"
40 #include "medialibrary_errno.h"
41 #ifdef META_RECOVERY_SUPPORT
42 #include "medialibrary_meta_recovery.h"
43 #endif
44 #include "medialibrary_operation.h"
45 #include "medialibrary_rdb_utils.h"
46 #include "medialibrary_rdbstore.h"
47 #include "medialibrary_tracer.h"
48 #include "medialibrary_type_const.h"
49 #include "medialibrary_unistore_manager.h"
50 #include "medialibrary_notify.h"
51 #include "parameters.h"
52 #include "photo_album_column.h"
53 #include "rdb_store.h"
54 #include "result_set_utils.h"
55 #include "thumbnail_service.h"
56 #include "cloud_media_asset_uri.h"
57 #include "dfx_const.h"
58 
59 using namespace std;
60 using namespace OHOS::NativeRdb;
61 
62 namespace OHOS {
63 namespace Media {
64 using namespace FileManagement::CloudSync;
65 
66 static const std::string UNKNOWN_VALUE = "NA";
67 // batch limit count of update cloud data
68 constexpr int32_t BATCH_UPDATE_LIMIT_COUNT = 500;
69 // batch limit count of delete cloud data
70 constexpr int32_t BATCH_DELETE_LIMIT_COUNT = 300;
71 static const int32_t CYCLE_NUMBER = 1024 * 1024;
72 static const int32_t SLEEP_FOR_DELETE = 600;
73 static const int32_t BATCH_NOTIFY_CLOUD_FILE = 2000;
74 static const std::string DELETE_DISPLAY_NAME = "cloud_media_asset_deleted";
75 static const int32_t ALBUM_FROM_CLOUD = 2;
76 static const int32_t ZERO_ASSET_OF_ALBUM = 0;
77 const std::string START_QUERY_ZERO = "0";
78 
79 const std::string SQL_CONDITION_EMPTY_CLOUD_ALBUMS = "FROM " + PhotoAlbumColumns::TABLE + " WHERE " +
80     "( " + PhotoAlbumColumns::ALBUM_IS_LOCAL + " = " + to_string(ALBUM_FROM_CLOUD) + " AND " +
81     PhotoAlbumColumns::ALBUM_ID + " NOT IN ( " +
82         "SELECT DISTINCT " + PhotoColumn::PHOTO_OWNER_ALBUM_ID +
83         " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
84         PhotoColumn::PHOTO_CLEAN_FLAG + " = " + to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) + " ))" +
85     " OR " + PhotoAlbumColumns::ALBUM_DIRTY + " = " + to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED));
86 const std::string SQL_QUERY_EMPTY_CLOUD_ALBUMS = "SELECT * " + SQL_CONDITION_EMPTY_CLOUD_ALBUMS;
87 const std::string SQL_DELETE_EMPTY_CLOUD_ALBUMS = "DELETE " + SQL_CONDITION_EMPTY_CLOUD_ALBUMS;
88 
89 // 持久化清除状态, 防止重启后清除错误服务端的图片数据: 时间戳|0
90 static const std::string CLOUD_RETIAN_STATUS_KEY = "persist.multimedia.medialibrary.retain.cloud.status";
91 static const std::string HDC_RETIAN_STATUS_KEY = "persist.multimedia.medialibrary.retain.hdc.status";
92 
93 static const std::string MEIDA_RESTORE_FLAG = "multimedia.medialibrary.restoreFlag";
94 static const std::string MEIDA_BACKUP_FLAG = "multimedia.medialibrary.backupFlag";
95 
96 // 同步服务模块使用: 时间戳|0,时间戳表征任务正在清理中,0表示无清理任务
97 static const std::string CLOUDSYNC_SWITCH_STATUS_KEY = "persist.kernel.cloudsync.switch_status"; // ms
98 
99 // 超时时间 ForceRetainDownloadCloudMedia
100 static constexpr int64_t SOUTH_DEVICE_CLEAN_DATA_TIMEOUT_MILLISECOND = 12 * 60 * 60 * 1000;
101 static constexpr int64_t FORCE_RETAIN_CLOUD_MEDIA_WAIT_RESTORE_TIMEOUT_SECOND = 6 * 60 * 60;
102 static constexpr int64_t FORCE_RETAIN_CLOUD_MEDIA_WAIT_BACKUP_TIMEOUT_SECOND = 2 * 60 * 60;
103 static constexpr int64_t FORCE_RETAIN_CLOUD_MEDIA_WAIT_BACKUP_OR_RESTORE_SLEEP_TIME_MILLISECOND = 15000;
104 
105 static std::mutex g_syncStatusMutex;
SetSystemParameter(const std::string & key,int64_t value)106 static bool SetSystemParameter(const std::string& key, int64_t value)
107 {
108     std::string valueStr = std::to_string(value);
109     return system::SetParameter(key, valueStr);
110 }
111 
SetSouthDeviceSyncSwitchStatus(CloudSyncStatus status)112 static void SetSouthDeviceSyncSwitchStatus(CloudSyncStatus status)
113 {
114     std::lock_guard<std::mutex> lock(g_syncStatusMutex);
115     bool retFlag = false;
116     if (status == CloudSyncStatus::CLOUD_CLEANING) {
117         auto timeStamp = MediaFileUtils::UTCTimeMilliSeconds();
118         retFlag = SetSystemParameter(CLOUDSYNC_SWITCH_STATUS_KEY, timeStamp);
119     } else {
120         retFlag = SetSystemParameter(CLOUDSYNC_SWITCH_STATUS_KEY, 0);
121     }
122     MEDIA_INFO_LOG("set CloudSyncStatus: %{public}d, result bool: %{public}d", static_cast<int32_t>(status), retFlag);
123 }
124 
SetSouthDeviceCleanStatus(CloudMediaRetainType retainType,CloudSyncStatus statusKey)125 static void SetSouthDeviceCleanStatus(CloudMediaRetainType retainType, CloudSyncStatus statusKey)
126 {
127     auto retainTypeToInt = static_cast<int32_t>(retainType);
128     // 防止一直无法恢复, 使用时间戳代替开关
129     int64_t timeStamp = 0;
130     if (statusKey ==  CloudSyncStatus::CLOUD_CLEANING) {
131         timeStamp = MediaFileUtils::UTCTimeMilliSeconds();
132     }
133 
134     std::lock_guard<std::mutex> lock(g_syncStatusMutex);
135     bool retFlag = false;
136     if (retainType == CloudMediaRetainType::RETAIN_FORCE) {
137         retFlag = SetSystemParameter(CLOUD_RETIAN_STATUS_KEY, timeStamp);
138     } else if (retainType == CloudMediaRetainType::HDC_RETAIN_FORCE) {
139         retFlag = SetSystemParameter(HDC_RETIAN_STATUS_KEY, timeStamp);
140     } else {
141         MEDIA_ERR_LOG("invalid retainType: %{public}d, status: %{public}d", retainTypeToInt, statusKey);
142         return;
143     }
144     MEDIA_INFO_LOG("set retainType: %{public}d, status: %{public}d, result bool: %{public}d",
145         retainTypeToInt, statusKey, retFlag);
146 }
147 
IsSouthDeviceSyncCleaning(CloudMediaRetainType retainType,bool checkTimeout=true)148 static bool IsSouthDeviceSyncCleaning(CloudMediaRetainType retainType, bool checkTimeout = true)
149 {
150     std::lock_guard<std::mutex> lock(g_syncStatusMutex);
151     int64_t timeStamp = 0;
152     if (retainType == CloudMediaRetainType::RETAIN_FORCE) {
153         timeStamp = system::GetIntParameter(CLOUD_RETIAN_STATUS_KEY, timeStamp);
154     } else if (retainType == CloudMediaRetainType::HDC_RETAIN_FORCE) {
155         timeStamp = system::GetIntParameter(HDC_RETIAN_STATUS_KEY, timeStamp);
156     } else {
157         MEDIA_ERR_LOG("get invalid retainType: %{public}d", static_cast<int32_t>(retainType));
158     }
159     if (timeStamp == 0) {
160         return false;
161     }
162 
163     if (!checkTimeout) {
164         return true;
165     }
166 
167     auto nowTime = MediaFileUtils::UTCTimeSeconds();
168     return ((nowTime - timeStamp) < SOUTH_DEVICE_CLEAN_DATA_TIMEOUT_MILLISECOND);
169 }
170 
WaitIfBackUpingOrRestoring(const std::string & key,int64_t waitTimeout,const std::string & info="unknown")171 static void WaitIfBackUpingOrRestoring(const std::string& key, int64_t waitTimeout, const std::string& info = "unknown")
172 {
173     constexpr int64_t defaultValueTime = 0;
174     int64_t startTimeClone = system::GetIntParameter(key, defaultValueTime);
175     int64_t startTimeWait = MediaFileUtils::UTCTimeSeconds();
176     MEDIA_INFO_LOG("Wait for %{public}s to exit. startTimeWait: %{public}" PRId64
177         ", startTimeClone: %{public}" PRId64, info.c_str(), startTimeWait, startTimeClone);
178     while (startTimeClone > 0) {
179         auto nowTime = MediaFileUtils::UTCTimeSeconds();
180         if ((nowTime - startTimeWait) > waitTimeout) {
181             MEDIA_WARN_LOG("[%{public}s] timeout: now: %{public}" PRId64", startTimeWait: %{public}" PRId64
182                 ", startTimeClone: %{public}" PRId64, info.c_str(), nowTime, startTimeWait, startTimeClone);
183             break;
184         }
185         MEDIA_DEBUG_LOG("[%{public}s] waiting: now: %{public}" PRId64", startTimeWait: %{public}" PRId64
186             ", startTimeClone: %{public}" PRId64, info.c_str(), nowTime, startTimeWait, startTimeClone);
187         std::this_thread::sleep_for(chrono::milliseconds(
188             FORCE_RETAIN_CLOUD_MEDIA_WAIT_BACKUP_OR_RESTORE_SLEEP_TIME_MILLISECOND));
189         startTimeClone = system::GetIntParameter(key, defaultValueTime);
190     }
191 
192     MEDIA_INFO_LOG("the %{public}s has exited, currtime: %{public}" PRId64,
193         info.c_str(), MediaFileUtils::UTCTimeSeconds());
194 }
195 
WaitIfBackUpingOrRestoring()196 static void WaitIfBackUpingOrRestoring()
197 {
198     WaitIfBackUpingOrRestoring(MEIDA_RESTORE_FLAG,
199         FORCE_RETAIN_CLOUD_MEDIA_WAIT_RESTORE_TIMEOUT_SECOND, "db restore");
200 
201     WaitIfBackUpingOrRestoring(MEIDA_BACKUP_FLAG,
202         FORCE_RETAIN_CLOUD_MEDIA_WAIT_BACKUP_TIMEOUT_SECOND, "db backup");
203 }
204 
205 enum class SouthDeviceType : int32_t {
206     SOUTH_DEVICE_NULL = 0,
207     SOUTH_DEVICE_CLOUD = 1,
208     SOUTH_DEVICE_HDC = 2
209 };
210 
GetInstance()211 CloudMediaAssetManager& CloudMediaAssetManager::GetInstance()
212 {
213     static CloudMediaAssetManager instance;
214     return instance;
215 }
216 
CheckDownloadTypeOfTask(const CloudMediaDownloadType & type)217 int32_t CloudMediaAssetManager::CheckDownloadTypeOfTask(const CloudMediaDownloadType &type)
218 {
219     if (static_cast<int32_t>(type) < static_cast<int32_t>(CloudMediaDownloadType::DOWNLOAD_FORCE) ||
220         static_cast<int32_t>(type) > static_cast<int32_t>(CloudMediaDownloadType::DOWNLOAD_GENTLE)) {
221         MEDIA_ERR_LOG("CloudMediaDownloadType invalid input. downloadType: %{public}d", static_cast<int32_t>(type));
222         return E_ERR;
223     }
224     return E_OK;
225 }
226 
StartDownloadCloudAsset(const CloudMediaDownloadType & type)227 int32_t CloudMediaAssetManager::StartDownloadCloudAsset(const CloudMediaDownloadType &type)
228 {
229     if (operation_ == nullptr) {
230         CloudMediaAssetDownloadOperation taskOperator;
231         operation_ = taskOperator.GetInstance();
232     }
233     if (CheckDownloadTypeOfTask(type) != E_OK) {
234         return E_ERR;
235     }
236     operation_->ResetDownloadTryTime();
237     switch (operation_->GetTaskStatus()) {
238         case CloudMediaAssetTaskStatus::IDLE: {
239             return operation_->StartDownloadTask(static_cast<int32_t>(type));
240         }
241         case CloudMediaAssetTaskStatus::PAUSED: {
242             return operation_->ManualActiveRecoverTask(static_cast<int32_t>(type));
243         }
244         case CloudMediaAssetTaskStatus::DOWNLOADING: {
245             if (type == operation_->GetDownloadType()) {
246                 MEDIA_WARN_LOG("No status changed.");
247                 return E_OK;
248             }
249             if (type == CloudMediaDownloadType::DOWNLOAD_GENTLE) {
250                 return operation_->PauseDownloadTask(CloudMediaTaskPauseCause::BACKGROUND_TASK_UNAVAILABLE);
251             }
252             return E_ERR;
253         }
254         default: {
255             MEDIA_ERR_LOG("StartDownloadCloudAsset failed. now: taskStatus_, %{public}d; \
256                 downloadType_, %{public}d. input: type, %{public}d;",
257                 static_cast<int32_t>(operation_->GetTaskStatus()), static_cast<int32_t>(operation_->GetDownloadType()),
258                 static_cast<int32_t>(type));
259             return E_ERR;
260         }
261     }
262 }
263 
RecoverDownloadCloudAsset(const CloudMediaTaskRecoverCause & cause)264 int32_t CloudMediaAssetManager::RecoverDownloadCloudAsset(const CloudMediaTaskRecoverCause &cause)
265 {
266     bool cond = (operation_ == nullptr || operation_->GetTaskStatus() == CloudMediaAssetTaskStatus::IDLE);
267     CHECK_AND_RETURN_RET(!cond, E_ERR);
268 
269     operation_->ResetDownloadTryTime();
270     MEDIA_INFO_LOG("enter RecoverDownloadCloudAsset, RecoverCause: %{public}d", static_cast<int32_t>(cause));
271     CHECK_AND_RETURN_RET_LOG(operation_->GetTaskStatus() != CloudMediaAssetTaskStatus::DOWNLOADING, E_OK,
272         "The task status is download, no need to recover.");
273     int32_t ret = operation_->PassiveStatusRecoverTask(cause);
274     MEDIA_INFO_LOG("end to RecoverDownloadCloudAsset, status: %{public}s, ret: %{public}d.",
275         GetCloudMediaAssetTaskStatus().c_str(), ret);
276     return ret;
277 }
278 
CheckStorageAndRecoverDownloadTask()279 void CloudMediaAssetManager::CheckStorageAndRecoverDownloadTask()
280 {
281     bool cond = (operation_ == nullptr || operation_->GetTaskStatus() != CloudMediaAssetTaskStatus::PAUSED ||
282         operation_->GetTaskPauseCause() != CloudMediaTaskPauseCause::ROM_LIMIT);
283     CHECK_AND_RETURN(!cond);
284     MEDIA_INFO_LOG("begin to check storage and recover downloadTask.");
285     operation_->CheckStorageAndRecoverDownloadTask();
286 }
287 
PauseDownloadCloudAsset(const CloudMediaTaskPauseCause & pauseCause)288 int32_t CloudMediaAssetManager::PauseDownloadCloudAsset(const CloudMediaTaskPauseCause &pauseCause)
289 {
290     if (operation_ == nullptr || operation_->GetTaskStatus() == CloudMediaAssetTaskStatus::IDLE) {
291         MEDIA_INFO_LOG("no need to pause");
292         return E_OK;
293     }
294     int32_t ret = operation_->PauseDownloadTask(pauseCause);
295     MEDIA_INFO_LOG("end to PauseDownloadCloudAsset, status: %{public}s, ret: %{public}d.",
296         GetCloudMediaAssetTaskStatus().c_str(), ret);
297     return ret;
298 }
299 
CancelDownloadCloudAsset()300 int32_t CloudMediaAssetManager::CancelDownloadCloudAsset()
301 {
302     if (operation_ == nullptr || operation_->GetTaskStatus() == CloudMediaAssetTaskStatus::IDLE) {
303         MEDIA_INFO_LOG("no need to cancel");
304         return E_OK;
305     }
306     int32_t ret = operation_->CancelDownloadTask();
307     operation_.reset();
308     return ret;
309 }
310 
StartDeleteCloudMediaAssets()311 void CloudMediaAssetManager::StartDeleteCloudMediaAssets()
312 {
313     TaskDeleteState expect = TaskDeleteState::IDLE;
314     if (doDeleteTask_.compare_exchange_strong(expect, TaskDeleteState::BACKGROUND_DELETE)) {
315         MEDIA_INFO_LOG("start delete cloud media assets task.");
316         DeleteAllCloudMediaAssetsAsync();
317     }
318 }
319 
StopDeleteCloudMediaAssets()320 void CloudMediaAssetManager::StopDeleteCloudMediaAssets()
321 {
322     TaskDeleteState expect = TaskDeleteState::BACKGROUND_DELETE;
323     if (!doDeleteTask_.compare_exchange_strong(expect, TaskDeleteState::IDLE)) {
324         MEDIA_INFO_LOG("current status is not suitable for stop delete cloud media assets task.");
325     }
326 }
327 
DeleteBatchCloudFile(const std::vector<std::string> & fileIds)328 int32_t CloudMediaAssetManager::DeleteBatchCloudFile(const std::vector<std::string> &fileIds)
329 {
330     MediaLibraryTracer tracer;
331     tracer.Start("DeleteBatchCloudFile");
332     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
333     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "DeleteBatchCloudFile failed. rdbStore is null");
334     AbsRdbPredicates deletePredicates(PhotoColumn::PHOTOS_TABLE);
335     deletePredicates.In(MediaColumn::MEDIA_ID, fileIds);
336     int32_t deletedRows = E_HAS_DB_ERROR;
337     int32_t ret = rdbStore->Delete(deletedRows, deletePredicates);
338     if (ret != NativeRdb::E_OK || deletedRows <= 0) {
339         MEDIA_ERR_LOG("Delete db operation failed. ret %{public}d. Deleted %{public}d", ret, deletedRows);
340         return E_ERR;
341     }
342     MEDIA_INFO_LOG("Delete db operation successful. ret %{public}d. Deleted %{public}d", ret, deletedRows);
343     return E_OK;
344 }
345 
ReadyDataForDelete(std::vector<std::string> & fileIds,std::vector<std::string> & paths,std::vector<std::string> & dateTakens)346 int32_t CloudMediaAssetManager::ReadyDataForDelete(std::vector<std::string> &fileIds, std::vector<std::string> &paths,
347     std::vector<std::string> &dateTakens)
348 {
349     MediaLibraryTracer tracer;
350     tracer.Start("ReadyDataForDelete");
351     MEDIA_INFO_LOG("enter ReadyDataForDelete");
352     AbsRdbPredicates queryPredicates(PhotoColumn::PHOTOS_TABLE);
353     queryPredicates.EqualTo(MediaColumn::MEDIA_NAME, DELETE_DISPLAY_NAME);
354     queryPredicates.Limit(BATCH_DELETE_LIMIT_COUNT);
355     vector<string> columns = {MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH, MediaColumn::MEDIA_DATE_TAKEN};
356 
357     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
358     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "ReadyDataForDelete failed. rdbStorePtr is null");
359     auto resultSet = rdbStore->Query(queryPredicates, columns);
360     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_ERR, "ReadyDataForDelete failed. resultSet is null");
361     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
362         string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
363         if (path.empty()) {
364             MEDIA_WARN_LOG("Failed to get path!");
365             continue;
366         }
367         MEDIA_DEBUG_LOG("get path: %{public}s.", MediaFileUtils::DesensitizePath(path).c_str());
368         fileIds.emplace_back(GetStringVal(MediaColumn::MEDIA_ID, resultSet));
369         paths.emplace_back(path);
370         dateTakens.emplace_back(GetStringVal(MediaColumn::MEDIA_DATE_TAKEN, resultSet));
371     }
372     resultSet->Close();
373     return E_OK;
374 }
375 
GetEditDataDirPath(const std::string & path)376 std::string CloudMediaAssetManager::GetEditDataDirPath(const std::string &path)
377 {
378     CHECK_AND_RETURN_RET(path.length() >= ROOT_MEDIA_DIR.length(), "");
379     return MEDIA_EDIT_DATA_DIR + path.substr(ROOT_MEDIA_DIR.length());
380 }
381 
DeleteEditdata(const std::string & path)382 int32_t CloudMediaAssetManager::DeleteEditdata(const std::string &path)
383 {
384     string editDataDirPath = GetEditDataDirPath(path);
385     CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_ERR, "Cannot get editPath, path: %{private}s", path.c_str());
386     if (MediaFileUtils::IsFileExists(editDataDirPath)) {
387         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteDir(editDataDirPath), E_ERR,
388             "Failed to delete edit data, path: %{private}s", editDataDirPath.c_str());
389     }
390     return E_OK;
391 }
392 
DeleteAllCloudMediaAssetsOperation(AsyncTaskData * data)393 void CloudMediaAssetManager::DeleteAllCloudMediaAssetsOperation(AsyncTaskData *data)
394 {
395     std::lock_guard<std::mutex> lock(deleteMutex_);
396     MEDIA_INFO_LOG("enter DeleteAllCloudMediaAssetsOperation");
397     MediaLibraryTracer tracer;
398     tracer.Start("DeleteAllCloudMediaAssetsOperation");
399 
400     std::vector<std::string> fileIds;
401     fileIds.reserve(BATCH_DELETE_LIMIT_COUNT);
402     std::vector<std::string> paths;
403     paths.reserve(BATCH_DELETE_LIMIT_COUNT);
404     std::vector<std::string> dateTakens;
405     dateTakens.reserve(BATCH_DELETE_LIMIT_COUNT);
406     int32_t cycleNumber = 0;
407     while (doDeleteTask_.load() > TaskDeleteState::IDLE && cycleNumber <= CYCLE_NUMBER) {
408         int32_t ret = ReadyDataForDelete(fileIds, paths, dateTakens);
409         if (ret != E_OK || fileIds.empty()) {
410             MEDIA_WARN_LOG("ReadyDataForDelete failed or fileIds is empty, ret: %{public}d, size: %{public}d",
411                 ret, static_cast<int32_t>(fileIds.size()));
412             break;
413         }
414         ret = DeleteBatchCloudFile(fileIds);
415         CHECK_AND_BREAK_ERR_LOG(ret == E_OK, "DeleteBatchCloudFile failed!");
416         for (size_t i = 0; i < fileIds.size(); i++) {
417             CHECK_AND_PRINT_LOG(DeleteEditdata(paths[i]) == E_OK, "DeleteEditdata error.");
418 #ifdef META_RECOVERY_SUPPORT
419             CHECK_AND_PRINT_LOG(MediaLibraryMetaRecovery::DeleteMetaDataByPath(paths[i]) == E_OK,
420                 "DeleteMetaDataByPath error.");
421 #endif
422             CloudSyncManager::GetInstance().CleanGalleryDentryFile(paths[i]);
423         }
424         MEDIA_INFO_LOG("delete thumb files.");
425         CHECK_AND_PRINT_LOG(ThumbnailService::GetInstance()->BatchDeleteThumbnailDirAndAstc(PhotoColumn::PHOTOS_TABLE,
426             fileIds, paths, dateTakens), "DeleteThumbnailDirAndAstc error.");
427         MEDIA_INFO_LOG("delete all cloud media asset. loop: %{public}d, deleted asset number: %{public}zu",
428             cycleNumber, fileIds.size());
429         fileIds.clear();
430         paths.clear();
431         dateTakens.clear();
432         cycleNumber++;
433         this_thread::sleep_for(chrono::milliseconds(SLEEP_FOR_DELETE));
434     }
435     doDeleteTask_.store(TaskDeleteState::IDLE);
436     MEDIA_INFO_LOG("exit DeleteAllCloudMediaAssetsOperation");
437 }
438 
DeleteAllCloudMediaAssetsAsync()439 void CloudMediaAssetManager::DeleteAllCloudMediaAssetsAsync()
440 {
441     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
442     CHECK_AND_RETURN_LOG(asyncWorker != nullptr, "Can not get asyncWorker");
443 
444     shared_ptr<MediaLibraryAsyncTask> deleteAsyncTask =
445         make_shared<MediaLibraryAsyncTask>(DeleteAllCloudMediaAssetsOperation, nullptr);
446     CHECK_AND_RETURN_LOG(deleteAsyncTask != nullptr, "Can not get deleteAsyncTask");
447 
448     asyncWorker->AddTask(deleteAsyncTask, true);
449 }
450 
HasDataForUpdate(CloudMediaRetainType retainType,std::vector<std::string> & updateFileIds,const std::string & lastFileId)451 bool CloudMediaAssetManager::HasDataForUpdate(CloudMediaRetainType retainType,
452     std::vector<std::string> &updateFileIds, const std::string &lastFileId)
453 {
454     updateFileIds.clear();
455     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
456     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "HasDataForUpdate failed. rdbStore is null.");
457     AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
458     predicates.GreaterThan(MediaColumn::MEDIA_ID, lastFileId);
459     predicates.EqualTo(PhotoColumn::PHOTO_POSITION, to_string(static_cast<int32_t>(PhotoPositionType::CLOUD)));
460     predicates.NotEqualTo(MediaColumn::MEDIA_NAME, DELETE_DISPLAY_NAME);
461     predicates.OrderByAsc(MediaColumn::MEDIA_ID);
462     predicates.Limit(BATCH_UPDATE_LIMIT_COUNT);
463     std::vector<std::string> columns = { MediaColumn::MEDIA_ID };
464     auto resultSet = rdbStore->Query(predicates, columns);
465     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "HasDataForUpdate failed. resultSet is null.");
466 
467     updateFileIds.reserve(BATCH_UPDATE_LIMIT_COUNT);
468     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
469         std::string fileId = GetStringVal(MediaColumn::MEDIA_ID, resultSet);
470         updateFileIds.emplace_back(fileId);
471     }
472     resultSet->Close();
473     CHECK_AND_RETURN_RET_LOG(updateFileIds.size() > 0, false, "the size of updateFileIds 0.");
474     return true;
475 }
476 
UpdateCloudAssets(const std::vector<std::string> & updateFileIds)477 int32_t CloudMediaAssetManager::UpdateCloudAssets(const std::vector<std::string> &updateFileIds)
478 {
479     MediaLibraryTracer tracer;
480     tracer.Start("UpdateCloudAssets");
481     CHECK_AND_RETURN_RET_LOG(!updateFileIds.empty(), E_ERR, "updateFileIds is null.");
482     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
483     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "UpdateCloudAssets failed. rdbStore is null.");
484     AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
485     predicates.In(MediaColumn::MEDIA_ID, updateFileIds);
486 
487     ValuesBucket values;
488     values.PutString(MediaColumn::MEDIA_NAME, DELETE_DISPLAY_NAME);
489     values.PutInt(PhotoColumn::PHOTO_CLEAN_FLAG, static_cast<int32_t>(CleanType::TYPE_NEED_CLEAN));
490     values.PutInt(PhotoColumn::PHOTO_DIRTY, -1);
491     values.PutLong(PhotoColumn::PHOTO_CLOUD_VERSION, 0);
492     values.PutNull(PhotoColumn::PHOTO_CLOUD_ID);
493 
494     int32_t changedRows = -1;
495     int32_t ret = rdbStore->Update(changedRows, values, predicates);
496     CHECK_AND_RETURN_RET_LOG((ret == E_OK && changedRows > 0), E_ERR,
497         "Failed to UpdateCloudAssets, ret: %{public}d, updateRows: %{public}d", ret, changedRows);
498     MEDIA_INFO_LOG("UpdateCloudAssets successfully. ret: %{public}d, updateRows: %{public}d", ret, changedRows);
499     return E_OK;
500 }
501 
NotifyUpdateAssetsChange(const std::vector<std::string> & notifyFileIds)502 void CloudMediaAssetManager::NotifyUpdateAssetsChange(const std::vector<std::string> &notifyFileIds)
503 {
504     AccurateRefresh::AssetAccurateRefresh::NotifyForReCheck();
505     CHECK_AND_RETURN_LOG(!notifyFileIds.empty(), "notifyFileIds is null.");
506     auto watch = MediaLibraryNotify::GetInstance();
507     CHECK_AND_RETURN_LOG(watch != nullptr, "watch is null.");
508     for (size_t i = 0; i < notifyFileIds.size(); i++) {
509         watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, notifyFileIds[i]),
510             NotifyType::NOTIFY_REMOVE);
511     }
512 }
513 
UpdateCloudMediaAssets(CloudMediaRetainType retainType)514 int32_t CloudMediaAssetManager::UpdateCloudMediaAssets(CloudMediaRetainType retainType)
515 {
516     MediaLibraryTracer tracer;
517     tracer.Start("UpdateCloudMediaAssets");
518 
519     int32_t cycleNumber = 0;
520     std::string lastFileId = START_QUERY_ZERO;
521     std::vector<std::string> notifyFileIds;
522     notifyFileIds.reserve(BATCH_NOTIFY_CLOUD_FILE);
523     std::vector<std::string> updateFileIds;
524     int32_t actualRet = E_OK;
525     MEDIA_INFO_LOG("begin UpdateCloudMediaAssets");
526     while (HasDataForUpdate(retainType, updateFileIds, lastFileId) && cycleNumber <= CYCLE_NUMBER) {
527         int32_t ret = UpdateCloudAssets(updateFileIds);
528         if (ret != E_OK) {
529             MEDIA_WARN_LOG("UpdateCloudAssets failed, and try again ret: %{public}d", ret);
530             ret = UpdateCloudAssets(updateFileIds);
531         }
532         if (ret != E_OK) {
533             MEDIA_ERR_LOG("UpdateCloudAssets failed, ret: %{public}d", ret);
534             actualRet = ret;
535             continue;
536         }
537         lastFileId = updateFileIds.back();
538         notifyFileIds.insert(notifyFileIds.end(), updateFileIds.begin(), updateFileIds.end());
539         if (notifyFileIds.size() >= BATCH_NOTIFY_CLOUD_FILE) {
540             NotifyUpdateAssetsChange(notifyFileIds);
541             notifyFileIds.clear();
542         }
543 
544         cycleNumber++;
545     }
546     MEDIA_INFO_LOG("end UpdateCloudMediaAssets");
547     if (notifyFileIds.size() > 0) {
548         NotifyUpdateAssetsChange(notifyFileIds);
549         notifyFileIds.clear();
550     }
551     if (cycleNumber > 0) {
552         MEDIA_INFO_LOG("begin to refresh all albums.");
553         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
554         CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_OK, "UpdateAllAlbums failed. rdbStore is null.");
555         MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore);
556     }
557     return actualRet;
558 }
559 
DeleteEmptyCloudAlbums()560 int32_t CloudMediaAssetManager::DeleteEmptyCloudAlbums()
561 {
562     MEDIA_INFO_LOG("start DeleteEmptyCloudAlbums.");
563     MediaLibraryTracer tracer;
564     tracer.Start("DeleteEmptyCloudAlbums");
565     std::shared_ptr<AccurateRefresh::AlbumAccurateRefresh> albumRefresh =
566         std::make_shared<AccurateRefresh::AlbumAccurateRefresh>();
567     CHECK_AND_RETURN_RET_LOG(albumRefresh != nullptr, E_ERR, "DeleteEmptyCloudAlbums failed. albumRefresh is null");
568     int32_t ret = albumRefresh->Init(SQL_QUERY_EMPTY_CLOUD_ALBUMS, std::vector<NativeRdb::ValueObject>());
569     CHECK_AND_RETURN_RET_LOG(ret == AccurateRefresh::ACCURATE_REFRESH_RET_OK, E_ERR, "Failed to init albumRefresh");
570 
571     ret = albumRefresh->ExecuteSql(SQL_DELETE_EMPTY_CLOUD_ALBUMS, AccurateRefresh::RdbOperation::RDB_OPERATION_REMOVE);
572     CHECK_AND_RETURN_RET_LOG(ret == AccurateRefresh::ACCURATE_REFRESH_RET_OK, E_ERR,
573         "Failed to delete. ret %{public}d.", ret);
574     albumRefresh->Notify();
575     MEDIA_INFO_LOG("end DeleteEmptyCloudAlbums. ret %{public}d.", ret);
576     return E_OK;
577 }
578 
HasLocalAndCloudAssets(CloudMediaRetainType retainType,std::vector<std::string> & updateFileIds,const string & lastFileId)579 bool CloudMediaAssetManager::HasLocalAndCloudAssets(CloudMediaRetainType retainType,
580     std::vector<std::string> &updateFileIds, const string &lastFileId)
581 {
582     updateFileIds.clear();
583     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
584     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "HasLocalAndCloudAssets failed. rdbStore is null.");
585 
586     AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
587     predicates.GreaterThan(MediaColumn::MEDIA_ID, lastFileId);
588     predicates.BeginWrap();
589     predicates.EqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::LOCAL_AND_CLOUD));
590     predicates.Or();
591     predicates.BeginWrap();
592     predicates.EqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::LOCAL));
593     predicates.BeginWrap();
594     predicates.IsNotNull(PhotoColumn::PHOTO_CLOUD_ID);
595     predicates.Or();
596     predicates.NotEqualTo(PhotoColumn::PHOTO_CLOUD_VERSION, 0);
597     predicates.Or();
598     predicates.NotEqualTo(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
599     predicates.EndWrap();
600     predicates.EndWrap();
601     predicates.EndWrap();
602     predicates.OrderByAsc(MediaColumn::MEDIA_ID);
603     predicates.Limit(BATCH_UPDATE_LIMIT_COUNT);
604 
605     std::vector<std::string> columns = { MediaColumn::MEDIA_ID };
606     auto resultSet = rdbStore->Query(predicates, columns);
607     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false,
608         "HasLocalAndCloudAssets failed. resultSet is null.");
609 
610     updateFileIds.reserve(BATCH_UPDATE_LIMIT_COUNT);
611     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
612         std::string fileId = GetStringVal(MediaColumn::MEDIA_ID, resultSet);
613         updateFileIds.emplace_back(fileId);
614     }
615     resultSet->Close();
616     CHECK_AND_RETURN_RET_LOG(updateFileIds.size() > 0, false, "the size of updateFileIds 0.");
617     return true;
618 }
619 
UpdateLocalAndCloudAssets(const std::vector<std::string> & updateFileIds)620 int32_t CloudMediaAssetManager::UpdateLocalAndCloudAssets(const std::vector<std::string> &updateFileIds)
621 {
622     MediaLibraryTracer tracer;
623     tracer.Start("UpdateLocalAndCloudAssets");
624     CHECK_AND_RETURN_RET_LOG(!updateFileIds.empty(), E_ERR, "updateFileIds is null.");
625     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
626     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "UpdateLocalAndCloudAssets failed. rdbStore is null.");
627     AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
628     predicates.In(MediaColumn::MEDIA_ID, updateFileIds);
629 
630     ValuesBucket values;
631     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
632     values.PutLong(PhotoColumn::PHOTO_CLOUD_VERSION, 0);
633     values.PutNull(PhotoColumn::PHOTO_CLOUD_ID);
634     values.PutInt(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::LOCAL));
635 
636     int32_t changedRows = -1;
637     int32_t ret = rdbStore->Update(changedRows, values, predicates);
638     CHECK_AND_RETURN_RET_LOG((ret == E_OK && changedRows >= 0), E_ERR,
639         "Failed to UpdateLocalAndCloudAssets, ret: %{public}d, updateRows: %{public}d", ret, changedRows);
640     MEDIA_INFO_LOG("UpdateLocalAndCloudAssets successfully. ret: %{public}d, updateRows: %{public}d", ret, changedRows);
641     return E_OK;
642 }
643 
ClearDeletedDbData()644 int32_t CloudMediaAssetManager::ClearDeletedDbData()
645 {
646     MEDIA_INFO_LOG("start ClearDeletedDbData.");
647     MediaLibraryTracer tracer;
648     tracer.Start("ClearDeletedDbData");
649 
650     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
651     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "ClearDeletedDbData failed. rdbStore is null.");
652 
653     AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
654     predicates.EqualTo(PhotoColumn::PHOTO_DIRTY, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
655 
656     int32_t deletedRows = -1;
657     auto ret = rdbStore->Delete(deletedRows, predicates);
658     CHECK_AND_RETURN_RET_LOG((ret == E_OK && deletedRows >= 0), E_ERR,
659         "Failed to ClearDeletedDbData, ret: %{public}d, deletedRows: %{public}d", ret, deletedRows);
660     MEDIA_INFO_LOG("ClearDeletedDbData successfully. ret: %{public}d, deletedRows: %{public}d", ret, deletedRows);
661     return E_OK;
662 }
663 
UpdateBothLocalAndCloudAssets(CloudMediaRetainType retainType)664 int32_t CloudMediaAssetManager::UpdateBothLocalAndCloudAssets(CloudMediaRetainType retainType)
665 {
666     MEDIA_INFO_LOG("start UpdateBothLocalAndCloudAssets.");
667     MediaLibraryTracer tracer;
668     tracer.Start("UpdateBothLocalAndCloudAssets");
669 
670     int32_t deleteRet = ClearDeletedDbData();
671     CHECK_AND_PRINT_LOG(deleteRet == E_OK, "ClearDeletedDbData failed. ret %{public}d.", deleteRet);
672 
673     int32_t cycleNumber = 0;
674     std::string lastFileId = START_QUERY_ZERO;
675     std::vector<std::string> updateFileIds;
676     while (HasLocalAndCloudAssets(retainType, updateFileIds, lastFileId) && cycleNumber <= CYCLE_NUMBER) {
677         int32_t ret = UpdateLocalAndCloudAssets(updateFileIds);
678         CHECK_AND_BREAK_ERR_LOG(ret == E_OK, "UpdateBothLocalAndCloudAssets failed, ret: %{public}d", ret);
679         lastFileId = updateFileIds.back();
680         cycleNumber++;
681     }
682     MEDIA_INFO_LOG("end UpdateBothLocalAndCloudAssets.");
683     return E_OK;
684 }
685 
UpdateLocalAlbums()686 int32_t CloudMediaAssetManager::UpdateLocalAlbums()
687 {
688     MEDIA_INFO_LOG("start UpdateLocalAlbums.");
689     MediaLibraryTracer tracer;
690     tracer.Start("UpdateLocalAlbums");
691     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
692     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "UpdateLocalAlbums failed. rdbStore is null");
693 
694     AbsRdbPredicates predicates = AbsRdbPredicates(PhotoAlbumColumns::TABLE);
695     ValuesBucket values;
696     values.PutInt(PhotoAlbumColumns::ALBUM_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
697     values.PutNull(PhotoAlbumColumns::ALBUM_CLOUD_ID);
698 
699     int32_t changedRows = E_HAS_DB_ERROR;
700     int32_t ret = rdbStore->Update(changedRows, values, predicates);
701     CHECK_AND_RETURN_RET_LOG((ret == E_OK && changedRows >= 0), E_ERR,
702         "Failed to UpdateLocalAlbums, ret: %{public}d, changedRows: %{public}d", ret, changedRows);
703     MEDIA_INFO_LOG("UpdateLocalAlbums successfully. ret %{public}d. changedRows %{public}d", ret, changedRows);
704     return E_OK;
705 }
706 
ForceRetainDownloadCloudMedia(CloudMediaRetainType retainType,bool needAvoidRepeatedDoing)707 int32_t CloudMediaAssetManager::ForceRetainDownloadCloudMedia(CloudMediaRetainType retainType,
708     bool needAvoidRepeatedDoing)
709 {
710     MediaLibraryTracer tracer;
711     auto retainTypeInt = static_cast<int32_t>(retainType);
712     tracer.Start(std::string("ForceRetainDownloadCloudMedia") + std::to_string(retainTypeInt));
713     MEDIA_INFO_LOG("enter. retainType: %{public}d", retainTypeInt);
714 
715     if (needAvoidRepeatedDoing && IsSouthDeviceSyncCleaning(retainType)) {
716         MEDIA_INFO_LOG("this south device is cleaning, retainType: %{public}d", retainTypeInt);
717         return E_OK;
718     }
719 
720     // 判断是不是已经有个南向设备端在cleaning, 如果有也直接返回
721     bool isCloudCleaning = IsSouthDeviceSyncCleaning(CloudMediaRetainType::RETAIN_FORCE);
722     bool isHdcCleaning = IsSouthDeviceSyncCleaning(CloudMediaRetainType::HDC_RETAIN_FORCE);
723     SetSouthDeviceCleanStatus(retainType, CloudSyncStatus::CLOUD_CLEANING);
724     if (needAvoidRepeatedDoing && (isCloudCleaning || isHdcCleaning)) {
725         MEDIA_INFO_LOG("some south device is cleaning. cloud: %{public}d, hdc: %{public}d",
726             isCloudCleaning, isHdcCleaning);
727         return E_OK;
728     }
729     SetSouthDeviceSyncSwitchStatus(CloudSyncStatus::CLOUD_CLEANING);
730 
731     // 主动停止端云同步
732     MEDIA_INFO_LOG("ForceRetainDownloadCloudMedia StopSync bundleName:%{public}s", BUNDLE_NAME.c_str());
733     CloudSyncManager::GetInstance().StopSync(BUNDLE_NAME);
734 
735     // 备份/恢复需要特殊处理,等待备份和恢复完成再清除;
736     WaitIfBackUpingOrRestoring();
737 
738     auto ret = ForceRetainDownloadCloudMediaEx(retainType);
739     MEDIA_INFO_LOG("ForceRetainDownloadCloudMediaEx ret: %{public}d", ret);
740     SetSouthDeviceCleanStatus(retainType, CloudSyncStatus::SYNC_SWITCHED_OFF);
741     isCloudCleaning = IsSouthDeviceSyncCleaning(CloudMediaRetainType::RETAIN_FORCE);
742     isHdcCleaning = IsSouthDeviceSyncCleaning(CloudMediaRetainType::HDC_RETAIN_FORCE);
743 
744     if (isCloudCleaning) {
745         ret |= ForceRetainDownloadCloudMediaEx(CloudMediaRetainType::RETAIN_FORCE);
746         SetSouthDeviceCleanStatus(CloudMediaRetainType::RETAIN_FORCE, CloudSyncStatus::SYNC_SWITCHED_OFF);
747         CHECK_AND_PRINT_LOG(ret == E_OK, "cloud force retain. ret %{public}d.", ret);
748     }
749 
750     if (isHdcCleaning) {
751         ret |= ForceRetainDownloadCloudMediaEx(CloudMediaRetainType::HDC_RETAIN_FORCE);
752         SetSouthDeviceCleanStatus(CloudMediaRetainType::HDC_RETAIN_FORCE, CloudSyncStatus::SYNC_SWITCHED_OFF);
753         CHECK_AND_PRINT_LOG(ret == E_OK, "hdc force retain. ret %{public}d.", ret);
754     }
755     SetSouthDeviceSyncSwitchStatus(CloudSyncStatus::SYNC_SWITCHED_OFF);
756 
757     TryToStartSync();
758 
759     MEDIA_INFO_LOG("exit. retainType: %{public}d", retainTypeInt);
760     return ret;
761 }
762 
ForceRetainDownloadCloudMediaEx(CloudMediaRetainType retainType)763 int32_t CloudMediaAssetManager::ForceRetainDownloadCloudMediaEx(CloudMediaRetainType retainType)
764 {
765     auto retainTypeInt = static_cast<int32_t>(retainType);
766     MEDIA_INFO_LOG("enter ForceRetainDownloadCloudMediaEx. retainType: %{public}d", retainTypeInt);
767 
768     std::unique_lock<std::mutex> lock(updateMutex_, std::defer_lock);
769     CHECK_AND_RETURN_RET_WARN_LOG(lock.try_lock(), E_ERR, // 此处的作用貌似和避免重复的逻辑一致
770         "retainType: %{public}d, data is cleaning, skipping this operation", retainTypeInt);
771 
772     MediaLibraryTracer tracer;
773     tracer.Start(std::string("ForceRetainDownloadCloudMediaEx, retainType:") + std::to_string(retainTypeInt));
774     // 停止后台异步清理云图任务,待本次云上信息标记完后重新开启
775     doDeleteTask_.store(TaskDeleteState::IDLE);
776 
777     int32_t updateRet = UpdateCloudMediaAssets(retainType);
778     CHECK_AND_PRINT_LOG(updateRet == E_OK, "UpdateCloudMediaAssets failed. ret %{public}d.", updateRet);
779     int32_t ret = DeleteEmptyCloudAlbums();
780     CHECK_AND_PRINT_LOG(ret == E_OK, "DeleteEmptyCloudAlbums failed. ret %{public}d.", ret);
781     auto watch = MediaLibraryNotify::GetInstance();
782     if (watch != nullptr) {
783         MEDIA_INFO_LOG("begin to notify album update.");
784         watch->Notify(PhotoAlbumColumns::ALBUM_URI_PREFIX, NotifyType::NOTIFY_UPDATE);
785     }
786 
787     ret = UpdateBothLocalAndCloudAssets(retainType);
788     CHECK_AND_PRINT_LOG(ret == E_OK, "UpdateBothLocalAndCloudAssets failed. ret %{public}d.", ret);
789     ret = UpdateLocalAlbums();
790     CHECK_AND_PRINT_LOG(ret == E_OK, "UpdateLocalAlbums failed. ret %{public}d.", ret);
791 
792     MEDIA_INFO_LOG("start delete cloud media assets task.");
793     doDeleteTask_.store(TaskDeleteState::ACTIVE_DELETE);
794     DeleteAllCloudMediaAssetsAsync();
795 
796     CHECK_AND_RETURN_RET_WARN_LOG(updateRet == E_OK, updateRet,
797         "exit ForceRetainDownloadCloudMediaEx, Type: %{public}d, updateRet: %{public}d.", retainTypeInt, updateRet);
798     MEDIA_INFO_LOG("exit ForceRetainDownloadCloudMediaEx, retainType: %{public}d", retainTypeInt);
799     return ret;
800 }
801 
GetCloudMediaAssetTaskStatus()802 std::string CloudMediaAssetManager::GetCloudMediaAssetTaskStatus()
803 {
804     if (operation_ == nullptr || operation_->GetTaskStatus() == CloudMediaAssetTaskStatus::IDLE) {
805         MEDIA_ERR_LOG("cloud media download task not exit.");
806         return to_string(static_cast<int32_t>(CloudMediaAssetTaskStatus::IDLE)) + ",0,0,0,0,0";
807     }
808     return to_string(static_cast<int32_t>(operation_->GetTaskStatus())) + "," + operation_->GetTaskInfo() + "," +
809         to_string(static_cast<int32_t>(operation_->GetTaskPauseCause()));
810 }
811 
HandleCloudMediaAssetUpdateOperations(MediaLibraryCommand & cmd)812 int32_t CloudMediaAssetManager::HandleCloudMediaAssetUpdateOperations(MediaLibraryCommand &cmd)
813 {
814     switch (cmd.GetOprnType()) {
815         case OperationType::CLOUD_MEDIA_ASSET_TASK_START_FORCE: {
816             return StartDownloadCloudAsset(CloudMediaDownloadType::DOWNLOAD_FORCE);
817         }
818         case OperationType::CLOUD_MEDIA_ASSET_TASK_START_GENTLE: {
819             return StartDownloadCloudAsset(CloudMediaDownloadType::DOWNLOAD_GENTLE);
820         }
821         case OperationType::CLOUD_MEDIA_ASSET_TASK_PAUSE: {
822             return PauseDownloadCloudAsset(CloudMediaTaskPauseCause::USER_PAUSED);
823         }
824         case OperationType::CLOUD_MEDIA_ASSET_TASK_CANCEL: {
825             return CancelDownloadCloudAsset();
826         }
827         case OperationType::CLOUD_MEDIA_ASSET_TASK_RETAIN_FORCE: {
828             return ForceRetainDownloadCloudMedia(CloudMediaRetainType::RETAIN_FORCE);
829         }
830         default: {
831             MEDIA_ERR_LOG("OprnType is not exit.");
832             return E_ERR;
833         }
834     }
835 }
836 
HandleCloudMediaAssetGetTypeOperations(MediaLibraryCommand & cmd)837 string CloudMediaAssetManager::HandleCloudMediaAssetGetTypeOperations(MediaLibraryCommand &cmd)
838 {
839     switch (cmd.GetOprnType()) {
840         case OperationType::CLOUD_MEDIA_ASSET_TASK_STATUS_QUERY: {
841             return GetCloudMediaAssetTaskStatus();
842         }
843         default: {
844             MEDIA_ERR_LOG("OprnType is not exit.");
845             return "";
846         }
847     }
848 }
849 
SetIsThumbnailUpdate()850 bool CloudMediaAssetManager::SetIsThumbnailUpdate()
851 {
852     if (operation_ == nullptr || operation_->GetTaskStatus() == CloudMediaAssetTaskStatus::IDLE) {
853         return false;
854     }
855     if (!operation_->isThumbnailUpdate_) {
856         MEDIA_INFO_LOG("Success set isThumbnailUpdate.");
857         operation_->isThumbnailUpdate_ = true;
858     }
859     MEDIA_INFO_LOG("Update count and size of download cloud media asset.");
860     if (operation_->InitDownloadTaskInfo() != E_OK) {
861         MEDIA_INFO_LOG("remainCount of download cloud media assets is 0.");
862         operation_->CancelDownloadTask();
863     }
864     return true;
865 }
866 
GetTaskStatus()867 int32_t CloudMediaAssetManager::GetTaskStatus()
868 {
869     CHECK_AND_RETURN_RET(operation_ != nullptr, static_cast<int32_t>(CloudMediaAssetTaskStatus::IDLE));
870     return static_cast<int32_t>(operation_->GetTaskStatus());
871 }
872 
GetDownloadType()873 int32_t CloudMediaAssetManager::GetDownloadType()
874 {
875     if (operation_ == nullptr) {
876         MEDIA_INFO_LOG("cloud media download task not exit.");
877         return E_ERR;
878     }
879     return static_cast<int32_t>(operation_->GetDownloadType());
880 }
881 
SetBgDownloadPermission(const bool & flag)882 bool CloudMediaAssetManager::SetBgDownloadPermission(const bool &flag)
883 {
884     bool cond = (operation_ == nullptr || operation_->GetTaskStatus() == CloudMediaAssetTaskStatus::IDLE);
885     CHECK_AND_RETURN_RET(!cond, false);
886     MEDIA_INFO_LOG("Success set isBgDownloadPermission, flag: %{public}d.", static_cast<int32_t>(flag));
887     operation_->isBgDownloadPermission_ = flag;
888     return true;
889 }
890 
RestartForceRetainCloudAssets()891 void CloudMediaAssetManager::RestartForceRetainCloudAssets()
892 {
893     std::thread([&] {
894         MEDIA_INFO_LOG("enter RestartForceRetainCloudAssets.");
895         auto isCleaning = IsSouthDeviceSyncCleaning(CloudMediaRetainType::RETAIN_FORCE, false);
896         isCleaning = isCleaning || IsSouthDeviceSyncCleaning(CloudMediaRetainType::HDC_RETAIN_FORCE, false);
897         if (isCleaning) {
898             MEDIA_WARN_LOG("restart continue retain force, given the current design, any of hdc/cloud can be chosen");
899             ForceRetainDownloadCloudMedia(CloudMediaRetainType::RETAIN_FORCE, false);
900         }
901     }).detach();
902 }
903 
TryToStartSync()904 void CloudMediaAssetManager::TryToStartSync()
905 {
906     if (!CloudSyncHelper::GetInstance()->IsSyncSwitchOpen()) {
907         MEDIA_INFO_LOG("syncSwitch is not open");
908         return;
909     }
910     MEDIA_INFO_LOG("cloud sync manager start sync");
911     int32_t ret = CloudSyncManager::GetInstance().StartSync(BUNDLE_NAME);
912     CHECK_AND_PRINT_LOG(ret == E_OK, "cloud sync manager start sync err %{public}d", ret);
913     MEDIA_INFO_LOG("cloud sync manager end sync");
914 }
915 } // namespace Media
916 } // namespace OHOS