• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #define MLOG_TAG "BackgroundCloudFileProcessor"
17 
18 #include "background_cloud_file_processor.h"
19 
20 #include <sys/statvfs.h>
21 
22 #include "abs_rdb_predicates.h"
23 #include "cloud_sync_manager.h"
24 #include "common_timer_errors.h"
25 #include "media_column.h"
26 #include "media_file_utils.h"
27 #include "media_log.h"
28 #include "medialibrary_errno.h"
29 #include "medialibrary_db_const.h"
30 #include "medialibrary_rdb_utils.h"
31 #include "medialibrary_rdbstore.h"
32 #include "medialibrary_subscriber.h"
33 #include "medialibrary_unistore_manager.h"
34 #include "metadata_extractor.h"
35 #include "mimetype_utils.h"
36 #include "rdb_store.h"
37 #include "rdb_utils.h"
38 #include "result_set_utils.h"
39 #include "userfile_manager_types.h"
40 #include "values_bucket.h"
41 #include "preferences.h"
42 #include "preferences_helper.h"
43 #include "cloud_sync_utils.h"
44 #include "power_efficiency_manager.h"
45 #include "cloud_media_photos_dao.h"
46 #include "result_set_reader.h"
47 #include "photos_po_writer.h"
48 
49 namespace OHOS {
50 namespace Media {
51 using namespace FileManagement::CloudSync;
52 using namespace OHOS::Media::ORM;
53 
54 static constexpr int32_t UPDATE_BATCH_CLOUD_SIZE = 2;
55 static constexpr int32_t UPDATE_BATCH_LOCAL_VIDEO_SIZE = 50;
56 static constexpr int32_t UPDATE_BATCH_LOCAL_IMAGE_SIZE = 200;
57 static constexpr int32_t MAX_RETRY_COUNT = 2;
58 static constexpr int32_t MIMETYPE_REPAIR_INTERVAL = 20000;
59 static constexpr int32_t CACHE_PHOTO_NUM = 100;
60 
61 // The task can be performed only when the ratio of available storage capacity reaches this value
62 static constexpr double DEVICE_STORAGE_FREE_RATIO_HIGH = 0.15;
63 static constexpr double DEVICE_STORAGE_FREE_RATIO_LOW = 0.05;
64 
65 static constexpr int64_t ONEDAY_TO_SEC = 60 * 60 * 24;
66 static constexpr int64_t SEC_TO_MSEC = 1e3;
67 static constexpr int64_t DOWNLOAD_NUM_FREE_RATIO_HIGH = 1000;
68 static constexpr int64_t DOWNLOAD_DAY_FREE_RATIO_HIGH = 30;
69 static constexpr int64_t DOWNLOAD_NUM_FREE_RATIO_LOW = 250;
70 static constexpr int64_t DOWNLOAD_DAY_FREE_RATIO_LOW = 7;
71 
72 static const int64_t DOWNLOAD_ID_DEFAULT = -1;
73 
74 int32_t BackgroundCloudFileProcessor::processInterval_ = PROCESS_INTERVAL;  // 5 minute
75 int32_t BackgroundCloudFileProcessor::downloadInterval_ = DOWNLOAD_INTERVAL;  // 1 minute
76 int32_t BackgroundCloudFileProcessor::downloadDuration_ = DOWNLOAD_DURATION; // 10 seconds
77 recursive_mutex BackgroundCloudFileProcessor::mutex_;
78 Utils::Timer BackgroundCloudFileProcessor::timer_("background_cloud_file_processor");
79 uint32_t BackgroundCloudFileProcessor::cloudDataTimerId_ = 0;
80 uint32_t BackgroundCloudFileProcessor::startTimerId_ = 0;
81 uint32_t BackgroundCloudFileProcessor::stopTimerId_ = 0;
82 bool BackgroundCloudFileProcessor::isUpdating_ = true;
83 int32_t BackgroundCloudFileProcessor::cloudUpdateOffset_ = 0;
84 int32_t BackgroundCloudFileProcessor::localImageUpdateOffset_ = 0;
85 int32_t BackgroundCloudFileProcessor::localVideoUpdateOffset_ = 0;
86 int32_t BackgroundCloudFileProcessor::cloudRetryCount_ = 0;
87 std::mutex BackgroundCloudFileProcessor::downloadResultMutex_;
88 std::mutex BackgroundCloudFileProcessor::repairMimeTypeMutex_;
89 std::unordered_map<std::string, BackgroundCloudFileProcessor::DownloadStatus>
90     BackgroundCloudFileProcessor::downloadResult_;
91 int64_t BackgroundCloudFileProcessor::downloadId_ = DOWNLOAD_ID_DEFAULT;
92 
93 const std::string BACKGROUND_CLOUD_FILE_CONFIG = "/data/storage/el2/base/preferences/background_cloud_file_config.xml";
94 const std::string DOWNLOAD_CNT_CONFIG = "/data/storage/el2/base/preferences/download_count_config.xml";
95 
96 const std::string DOWNLOAD_LATEST_FINISHED = "download_latest_finished";
97 const std::string LAST_DOWNLOAD_MILLISECOND = "last_download_millisecond";
98 const std::string LAST_LOCAL_MIMETYPE_REPAIR = "last_mimetype_repair";
99 // when kernel hibernates, the timer expires longer, and the number of download images needs to be compensated
100 const int32_t MIN_DOWNLOAD_NUM = 1;
101 const int32_t MAX_DOWNLOAD_NUM = 30;
102 const double HALF = 0.5;
103 
104 // LCOV_EXCL_START
SetDownloadLatestFinished(bool downloadLatestFinished)105 void BackgroundCloudFileProcessor::SetDownloadLatestFinished(bool downloadLatestFinished)
106 {
107     int32_t errCode;
108     shared_ptr<NativePreferences::Preferences> prefs =
109         NativePreferences::PreferencesHelper::GetPreferences(BACKGROUND_CLOUD_FILE_CONFIG, errCode);
110     CHECK_AND_RETURN_LOG(prefs, "get preferences error: %{public}d", errCode);
111 
112     prefs->PutBool(DOWNLOAD_LATEST_FINISHED, downloadLatestFinished);
113     prefs->FlushSync();
114     MEDIA_INFO_LOG("set preferences %{public}d", downloadLatestFinished);
115 }
116 
GetDownloadLatestFinished()117 bool BackgroundCloudFileProcessor::GetDownloadLatestFinished()
118 {
119     int32_t errCode;
120     bool downloadLatestFinished = false;
121     shared_ptr<NativePreferences::Preferences> prefs =
122         NativePreferences::PreferencesHelper::GetPreferences(BACKGROUND_CLOUD_FILE_CONFIG, errCode);
123     CHECK_AND_RETURN_RET_LOG(prefs, false,
124         "get preferences error: %{public}d", errCode);
125     return prefs->GetBool(DOWNLOAD_LATEST_FINISHED, downloadLatestFinished);
126 }
127 
SetLastDownloadMilliSecond(int64_t lastDownloadMilliSecond)128 void BackgroundCloudFileProcessor::SetLastDownloadMilliSecond(int64_t lastDownloadMilliSecond)
129 {
130     int32_t errCode;
131     shared_ptr<NativePreferences::Preferences> prefs =
132         NativePreferences::PreferencesHelper::GetPreferences(BACKGROUND_CLOUD_FILE_CONFIG, errCode);
133     CHECK_AND_RETURN_LOG(prefs, "get preferences error: %{public}d", errCode);
134 
135     prefs->PutLong(LAST_DOWNLOAD_MILLISECOND, lastDownloadMilliSecond);
136     prefs->FlushSync();
137 }
138 
GetLastDownloadMilliSecond()139 int64_t BackgroundCloudFileProcessor::GetLastDownloadMilliSecond()
140 {
141     int32_t errCode;
142     int64_t lastDownloadMilliSecond = 0;
143     shared_ptr<NativePreferences::Preferences> prefs =
144         NativePreferences::PreferencesHelper::GetPreferences(BACKGROUND_CLOUD_FILE_CONFIG, errCode);
145     CHECK_AND_RETURN_RET_LOG(prefs, false,
146         "get preferences error: %{public}d", errCode);
147     return prefs->GetLong(LAST_DOWNLOAD_MILLISECOND, lastDownloadMilliSecond);
148 }
149 
ClearDownloadCnt()150 void BackgroundCloudFileProcessor::ClearDownloadCnt()
151 {
152     int32_t errCode;
153     shared_ptr<NativePreferences::Preferences> prefs =
154         NativePreferences::PreferencesHelper::GetPreferences(DOWNLOAD_CNT_CONFIG, errCode);
155     CHECK_AND_RETURN_LOG(prefs, "get preferences error: %{public}d", errCode);
156     prefs->Clear();
157     prefs->FlushSync();
158 }
159 
UpdateDownloadCnt(std::string uri,int64_t cnt)160 void BackgroundCloudFileProcessor::UpdateDownloadCnt(std::string uri, int64_t cnt)
161 {
162     int32_t errCode;
163     shared_ptr<NativePreferences::Preferences> prefs =
164         NativePreferences::PreferencesHelper::GetPreferences(DOWNLOAD_CNT_CONFIG, errCode);
165     CHECK_AND_RETURN_LOG(prefs, "get preferences error: %{public}d", errCode);
166     prefs->PutLong(uri, cnt);
167     prefs->FlushSync();
168 }
169 
GetDownloadCnt(std::string uri)170 int64_t BackgroundCloudFileProcessor::GetDownloadCnt(std::string uri)
171 {
172     int32_t errCode;
173     int64_t defaultCnt = 0;
174     shared_ptr<NativePreferences::Preferences> prefs =
175         NativePreferences::PreferencesHelper::GetPreferences(DOWNLOAD_CNT_CONFIG, errCode);
176     CHECK_AND_RETURN_RET_LOG(prefs, defaultCnt, "get preferences error: %{public}d", errCode);
177     return prefs->GetLong(uri, defaultCnt);
178 }
179 
DownloadCloudFiles()180 void BackgroundCloudFileProcessor::DownloadCloudFiles()
181 {
182     CHECK_AND_RETURN_LOG(CloudSyncUtils::IsCloudSyncSwitchOn(),
183         "Cloud sync switch off, skip DownloadCloudFiles");
184     MEDIA_DEBUG_LOG("Start downloading cloud files task");
185 
186     double freeRatio = 0.0;
187     CHECK_AND_RETURN_LOG(GetStorageFreeRatio(freeRatio),
188         "GetStorageFreeRatio failed, stop downloading cloud files");
189     auto resultSet = QueryCloudFiles(freeRatio);
190     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to query cloud files!");
191 
192     DownloadFiles downloadFiles;
193     ParseDownloadFiles(resultSet, downloadFiles);
194     CHECK_AND_RETURN_LOG(!downloadFiles.uris.empty(), "No cloud files need to be downloaded");
195     if (resultSet != nullptr) {
196         resultSet->Close();
197     }
198     int32_t ret = AddDownloadTask(downloadFiles);
199     CHECK_AND_PRINT_LOG(ret == E_OK, "Failed to add download task! err: %{public}d", ret);
200 }
201 
UpdateCloudData()202 void BackgroundCloudFileProcessor::UpdateCloudData()
203 {
204     MEDIA_DEBUG_LOG("Start update cloud data task");
205     std::vector<QueryOption> queryList = {{false, true}, {false, false}, {true, true}};
206     int32_t count = 0;
207     UpdateData updateData;
208     for (auto option : queryList) {
209         std::shared_ptr<NativeRdb::ResultSet> resultSet = QueryUpdateData(option.isCloud, option.isVideo);
210         if (resultSet == nullptr || resultSet->GetRowCount(count) != NativeRdb::E_OK) {
211             MEDIA_ERR_LOG("Failed to query data, %{public}d, %{public}d", option.isCloud, option.isVideo);
212             continue;
213         }
214         if (count == 0) {
215             MEDIA_DEBUG_LOG("no need to update, %{public}d, %{public}d", option.isCloud, option.isVideo);
216             continue;
217         }
218         ParseUpdateData(resultSet, updateData, option.isCloud, option.isVideo);
219         break;
220     }
221 
222     if (updateData.abnormalData.empty()) {
223         MEDIA_DEBUG_LOG("No data need to update");
224         return;
225     }
226     int32_t ret = AddUpdateDataTask(updateData);
227     if (ret != E_OK) {
228         MEDIA_ERR_LOG("Failed to add update task! err: %{public}d", ret);
229     }
230 }
231 
UpdateMimeTypeByFileId(const string & mimetype,int32_t fileId)232 void UpdateMimeTypeByFileId(const string &mimetype, int32_t fileId)
233 {
234     NativeRdb::ValuesBucket values;
235     values.PutString(MediaColumn::MEDIA_MIME_TYPE, mimetype);
236     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
237     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
238     int32_t changedRows = 0;
239     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
240     int32_t result = rdbStore->Update(changedRows, values, predicates);
241     bool cond = (result != NativeRdb::E_OK || changedRows <= 0);
242     CHECK_AND_RETURN_LOG(!cond, "Update operation failed. Result %{public}d. Updated %{public}d",
243         result, changedRows);
244 }
245 
GetRepairMimeTypeData(const int32_t & lastRecord)246 std::vector<PhotosPo> GetRepairMimeTypeData(const int32_t &lastRecord)
247 {
248     MEDIA_INFO_LOG("GetRepairMimeTypeData begin");
249     std::vector<PhotosPo> photosPoVec;
250     const std::vector<std::string> columns = { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH,
251         MediaColumn::MEDIA_TYPE, MediaColumn::MEDIA_MIME_TYPE, PhotoColumn::PHOTO_POSITION };
252     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
253     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, photosPoVec, "Failed to get rdbStore.");
254     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
255     predicates.GreaterThan(MediaColumn::MEDIA_ID, lastRecord);
256     predicates.OrderByAsc(MediaColumn::MEDIA_ID);
257     predicates.Limit(CACHE_PHOTO_NUM);
258 
259     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
260     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, photosPoVec, "Failed to query.");
261 
262     ResultSetReader<PhotosPoWriter, PhotosPo>(resultSet).ReadRecords(photosPoVec);
263     return photosPoVec;
264 }
265 
HandleRepairMimeType(const int32_t & lastRecord)266 void BackgroundCloudFileProcessor::HandleRepairMimeType(const int32_t &lastRecord)
267 {
268     std::unique_lock<std::mutex> lock(repairMimeTypeMutex_, std::defer_lock);
269     CHECK_AND_RETURN_WARN_LOG(lock.try_lock(), "Repairing mimetype has started, skipping this operation");
270     MEDIA_INFO_LOG("Start repair mimetype from %{public}d", lastRecord);
271     bool terminate = false;
272     int32_t repairRecord = lastRecord;
273     std::vector<PhotosPo> photosPoVec = GetRepairMimeTypeData(repairRecord);
274     do {
275         for (PhotosPo photosPo : photosPoVec) {
276             std::string path = photosPo.data.value_or("");
277             int32_t fileId = photosPo.fileId.value_or(0);
278             std::string mimeType = photosPo.mimeType.value_or("");
279             int32_t position = photosPo.position.value_or(0);
280             if (path == "" || fileId <= 0 || position <= 0) {
281                 continue;
282             }
283             if (position == static_cast<int32_t>(POSITION_CLOUD) && !MedialibrarySubscriber::IsWifiConnected()) {
284                 MEDIA_INFO_LOG("Break repair cause wifi not connect");
285                 terminate = true;
286                 break;
287             }
288             string mimeTypeNew = MimeTypeUtils::GetMimeTypeFromContent(path);
289             if (mimeTypeNew != mimeType) {
290                 MEDIA_INFO_LOG("Update mimetype from: %{public}s to: %{public}s",
291                     mimeType.c_str(), mimeTypeNew.c_str());
292                 UpdateMimeTypeByFileId(mimeTypeNew, fileId);
293             }
294             repairRecord = fileId;
295 
296             // reduce repair frequency
297             this_thread::sleep_for(chrono::milliseconds(MIMETYPE_REPAIR_INTERVAL));
298             if (!PowerEfficiencyManager::IsChargingAndScreenOff()) {
299                 MEDIA_INFO_LOG("Break repair cause invalid status");
300                 terminate = true;
301                 break;
302             }
303         }
304         int32_t errCode = 0;
305         shared_ptr<NativePreferences::Preferences> prefs =
306             NativePreferences::PreferencesHelper::GetPreferences(BACKGROUND_CLOUD_FILE_CONFIG, errCode);
307         prefs->PutInt(LAST_LOCAL_MIMETYPE_REPAIR, repairRecord);
308         prefs->FlushSync();
309         MEDIA_INFO_LOG("repair mimetype to %{public}d", repairRecord);
310         photosPoVec = GetRepairMimeTypeData(repairRecord);
311     } while (photosPoVec.size() > 0 && !terminate);
312 }
313 
RepairMimeType()314 void BackgroundCloudFileProcessor::RepairMimeType()
315 {
316     int32_t errCode = 0;
317     int64_t defaultCnt = 0;
318     shared_ptr<NativePreferences::Preferences> prefs =
319         NativePreferences::PreferencesHelper::GetPreferences(BACKGROUND_CLOUD_FILE_CONFIG, errCode);
320     CHECK_AND_RETURN_LOG(prefs, "get preferences error: %{public}d", errCode);
321     int32_t localRepairRecord = prefs->GetInt(LAST_LOCAL_MIMETYPE_REPAIR, defaultCnt);
322 
323     std::vector<PhotosPo> photosPoVec = GetRepairMimeTypeData(localRepairRecord);
324     CHECK_AND_RETURN_LOG(photosPoVec.size() > 0, "no data for repair");
325     MEDIA_INFO_LOG("need repair count %{public}d", static_cast<int>(photosPoVec.size()));
326     std::thread([localRepairRecord]() {
327         HandleRepairMimeType(localRepairRecord);
328     }).detach();
329 }
330 
ProcessCloudData()331 void BackgroundCloudFileProcessor::ProcessCloudData()
332 {
333     UpdateCloudData();
334 }
335 
GetStorageFreeRatio(double & freeRatio)336 bool BackgroundCloudFileProcessor::GetStorageFreeRatio(double &freeRatio)
337 {
338     struct statvfs diskInfo;
339     int ret = statvfs("/data/storage/el2/database", &diskInfo);
340     CHECK_AND_RETURN_RET_LOG(ret == 0, false, "Get file system status information failed, err: %{public}d", ret);
341 
342     double totalSize = static_cast<double>(diskInfo.f_bsize) * static_cast<double>(diskInfo.f_blocks);
343     CHECK_AND_RETURN_RET_LOG(totalSize >= 1e-9, false,
344         "Get file system total size failed, totalSize=%{public}f", totalSize);
345 
346     double freeSize = static_cast<double>(diskInfo.f_bsize) * static_cast<double>(diskInfo.f_bfree);
347     freeRatio = freeSize / totalSize;
348     return true;
349 }
350 
QueryCloudFiles(double freeRatio)351 std::shared_ptr<NativeRdb::ResultSet> BackgroundCloudFileProcessor::QueryCloudFiles(double freeRatio)
352 {
353     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
354     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, nullptr, "uniStore is nullptr!");
355 
356     int64_t downloadNum;
357     int64_t downloadMilliSecond;
358 
359     if (freeRatio >= DEVICE_STORAGE_FREE_RATIO_HIGH) {
360         downloadNum = DOWNLOAD_NUM_FREE_RATIO_HIGH;
361         downloadMilliSecond = DOWNLOAD_DAY_FREE_RATIO_HIGH * ONEDAY_TO_SEC * SEC_TO_MSEC;
362     } else if ((freeRatio >= DEVICE_STORAGE_FREE_RATIO_LOW) && (freeRatio < DEVICE_STORAGE_FREE_RATIO_HIGH)) {
363         downloadNum = DOWNLOAD_NUM_FREE_RATIO_LOW;
364         downloadMilliSecond = DOWNLOAD_DAY_FREE_RATIO_LOW * ONEDAY_TO_SEC * SEC_TO_MSEC;
365         MEDIA_INFO_LOG("freeRatio is %{public}.2f, available disk is low", freeRatio);
366     } else {
367         MEDIA_WARN_LOG("freeRatio is %{public}.2f less than %{public}.2f, stop downloading cloud files",
368                        freeRatio, DEVICE_STORAGE_FREE_RATIO_LOW);
369         return nullptr;
370     }
371 
372     auto currentMilliSecond = MediaFileUtils::UTCTimeMilliSeconds();
373 
374     string sql = "SELECT " + PhotoColumn::MEDIA_FILE_PATH + ", " + PhotoColumn::PHOTO_POSITION + ", " +
375         PhotoColumn::MEDIA_ID + ", " + PhotoColumn::MEDIA_NAME +
376         " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
377         PhotoColumn::PHOTO_CLEAN_FLAG + " = " + std::to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) +
378         " AND " + PhotoColumn::MEDIA_FILE_PATH + " IS NOT NULL AND " + PhotoColumn::MEDIA_FILE_PATH + " != '' AND " +
379         MediaColumn::MEDIA_SIZE + " > 0 AND " + PhotoColumn::MEDIA_TYPE + " = " + std::to_string(MEDIA_TYPE_IMAGE) +
380         " AND " + MediaColumn::MEDIA_DATE_TAKEN + " > " + std::to_string(currentMilliSecond - downloadMilliSecond) +
381         " ORDER BY " + MediaColumn::MEDIA_DATE_TAKEN + " DESC, " + PhotoColumn::MEDIA_ID + " DESC LIMIT " +
382         std::to_string(downloadNum);
383     MEDIA_DEBUG_LOG("ParseDownloadFiles SQL limit downloadNum: %{public}" PRId64, downloadNum);
384     return uniStore->QuerySql(sql);
385 }
386 
CheckAndUpdateDownloadCnt(std::string uri,int64_t cnt)387 void BackgroundCloudFileProcessor::CheckAndUpdateDownloadCnt(std::string uri, int64_t cnt)
388 {
389     bool updateDownloadCntFlag = true;
390     unique_lock<mutex> downloadLock(downloadResultMutex_);
391     if (downloadResult_.find(uri) != downloadResult_.end()) {
392         bool cond = ((downloadResult_[uri] == DownloadStatus::NETWORK_UNAVAILABLE) ||
393             (downloadResult_[uri] == DownloadStatus::STORAGE_FULL));
394         CHECK_AND_EXECUTE(!cond, updateDownloadCntFlag = false);
395     }
396     downloadLock.unlock();
397 
398     if (updateDownloadCntFlag) {
399         UpdateDownloadCnt(uri, cnt + 1);
400     }
401 }
402 
GetDownloadNum(int64_t & downloadNum)403 void BackgroundCloudFileProcessor::GetDownloadNum(int64_t &downloadNum)
404 {
405     int64_t currentMilliSecond = MediaFileUtils::UTCTimeMilliSeconds();
406     int64_t lastDownloadMilliSecond = GetLastDownloadMilliSecond();
407 
408     int64_t minutes = (currentMilliSecond - lastDownloadMilliSecond) / downloadInterval_;
409     if (minutes < MIN_DOWNLOAD_NUM) {
410         downloadNum = MIN_DOWNLOAD_NUM;
411     } else if (minutes >= MAX_DOWNLOAD_NUM) {
412         downloadNum = MAX_DOWNLOAD_NUM;
413     } else {
414         downloadNum = minutes;
415         bool cond = ((currentMilliSecond - lastDownloadMilliSecond) - (minutes * downloadInterval_)
416             > (HALF * downloadInterval_));
417         CHECK_AND_EXECUTE(!cond, downloadNum++);
418     }
419     MEDIA_DEBUG_LOG("GetDownloadNum downloadNum: %{public}" PRId64, downloadNum);
420 }
421 
DownloadLatestFinished()422 void BackgroundCloudFileProcessor::DownloadLatestFinished()
423 {
424     SetDownloadLatestFinished(true);
425     ClearDownloadCnt();
426 
427     unique_lock<mutex> downloadLock(downloadResultMutex_);
428     downloadResult_.clear();
429     downloadLock.unlock();
430 
431     lock_guard<recursive_mutex> lock(mutex_);
432     if (startTimerId_ > 0) {
433         timer_.Unregister(startTimerId_);
434         startTimerId_ = 0;
435     }
436     if (stopTimerId_ > 0) {
437         timer_.Unregister(stopTimerId_);
438         stopTimerId_ = 0;
439     }
440 }
441 
ParseDownloadFiles(std::shared_ptr<NativeRdb::ResultSet> & resultSet,DownloadFiles & downloadFiles)442 void BackgroundCloudFileProcessor::ParseDownloadFiles(std::shared_ptr<NativeRdb::ResultSet> &resultSet,
443     DownloadFiles &downloadFiles)
444 {
445     int64_t downloadNum;
446     GetDownloadNum(downloadNum);
447     auto currentMilliSecond = MediaFileUtils::UTCTimeMilliSeconds();
448     SetLastDownloadMilliSecond(currentMilliSecond);
449 
450     bool downloadLatestFinished = true;
451     downloadFiles.uris.clear();
452     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
453         std::string path =
454             get<std::string>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_FILE_PATH, resultSet, TYPE_STRING));
455         if (path.empty()) {
456             MEDIA_WARN_LOG("Failed to get cloud file path!");
457             continue;
458         }
459 
460         int32_t position =
461             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_POSITION, resultSet, TYPE_INT32));
462         if (position != static_cast<int32_t>(POSITION_CLOUD)) {
463             continue;
464         }
465         int32_t fileId = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_ID, resultSet, TYPE_INT32));
466         MEDIA_DEBUG_LOG("ParseDownloadFiles fileId: %{public}d", fileId);
467         std::string displayName =
468             get<std::string>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_NAME, resultSet, TYPE_STRING));
469         if (displayName.empty()) {
470             MEDIA_WARN_LOG("Failed to get cloud file displayName!");
471             continue;
472         }
473         std::string uri = "";
474         uri = MediaFileUri::GetPhotoUri(to_string(fileId), path, displayName);
475 
476         int64_t cnt = GetDownloadCnt(uri);
477         if (cnt < DOWNLOAD_FAIL_MAX_TIMES) {
478             downloadLatestFinished = false;
479             downloadFiles.uris.push_back(uri);
480             downloadFiles.mediaType = MEDIA_TYPE_IMAGE;
481             CheckAndUpdateDownloadCnt(uri, cnt);
482             if ((int64_t)downloadFiles.uris.size() >= downloadNum) {
483                 break;
484             }
485         }
486     }
487     if (downloadLatestFinished) {
488         DownloadLatestFinished();
489     }
490     MEDIA_DEBUG_LOG("ParseDownloadFiles downloadLatestFinished: %{public}d", downloadLatestFinished);
491 }
492 
removeFinishedResult(const std::vector<std::string> & downloadingPaths)493 void BackgroundCloudFileProcessor::removeFinishedResult(const std::vector<std::string>& downloadingPaths)
494 {
495     lock_guard<mutex> downloadLock(downloadResultMutex_);
496     for (auto it = downloadResult_.begin(); it != downloadResult_.end();) {
497         if (find(downloadingPaths.begin(), downloadingPaths.end(), it->first) == downloadingPaths.end()) {
498             it = downloadResult_.erase(it);
499         } else {
500             it++;
501         }
502     }
503 }
504 
AddDownloadTask(const DownloadFiles & downloadFiles)505 int32_t BackgroundCloudFileProcessor::AddDownloadTask(const DownloadFiles &downloadFiles)
506 {
507     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
508     CHECK_AND_RETURN_RET_LOG(asyncWorker != nullptr, E_FAIL, "Failed to get async worker instance!");
509 
510     auto *taskData = new (std::nothrow) DownloadCloudFilesData(downloadFiles);
511     CHECK_AND_RETURN_RET_LOG(taskData != nullptr, E_NO_MEMORY,
512         "Failed to alloc async data for downloading cloud files!");
513 
514     auto asyncTask = std::make_shared<MediaLibraryAsyncTask>(DownloadCloudFilesExecutor, taskData);
515     asyncWorker->AddTask(asyncTask, false);
516     return E_OK;
517 }
518 
DownloadCloudFilesExecutor(AsyncTaskData * data)519 void BackgroundCloudFileProcessor::DownloadCloudFilesExecutor(AsyncTaskData *data)
520 {
521     auto *taskData = static_cast<DownloadCloudFilesData *>(data);
522     auto downloadFiles = taskData->downloadFiles_;
523 
524     MEDIA_DEBUG_LOG("Try to download %{public}zu cloud files.", downloadFiles.uris.size());
525 
526     unique_lock<mutex> downloadLock(downloadResultMutex_);
527     for (const auto &uri : downloadFiles.uris) {
528         downloadResult_[uri] = DownloadStatus::INIT;
529         MEDIA_INFO_LOG("Start to download cloud file, uri: %{public}s", MediaFileUtils::DesensitizePath(uri).c_str());
530     }
531     downloadLock.unlock();
532 
533     removeFinishedResult(downloadFiles.uris);
534 
535     std::shared_ptr<BackgroundCloudFileDownloadCallback> downloadCallback = nullptr;
536     downloadCallback = std::make_shared<BackgroundCloudFileDownloadCallback>();
537     CHECK_AND_RETURN_LOG(downloadCallback != nullptr, "downloadCallback is null.");
538     int32_t ret = CloudSyncManager::GetInstance().StartFileCache(downloadFiles.uris, downloadId_,
539         FieldKey::FIELDKEY_CONTENT, downloadCallback);
540     if (ret != E_OK || downloadId_ == DOWNLOAD_ID_DEFAULT) {
541         MEDIA_ERR_LOG("failed to StartFileCache, ret: %{public}d, downloadId_: %{public}s.",
542             ret, to_string(downloadId_).c_str());
543         downloadId_ = DOWNLOAD_ID_DEFAULT;
544         return;
545     }
546 
547     MEDIA_INFO_LOG("Success, downloadId: %{public}d, downloadNum: %{public}d.",
548         static_cast<int32_t>(downloadId_), static_cast<int32_t>(downloadFiles.uris.size()));
549 
550     lock_guard<recursive_mutex> lock(mutex_);
551 
552     if (downloadFiles.mediaType == MEDIA_TYPE_VIDEO) {
553         if (stopTimerId_ > 0) {
554             timer_.Unregister(stopTimerId_);
555         }
556         stopTimerId_ = timer_.Register(StopDownloadFiles, downloadDuration_, true);
557     }
558 }
559 
StopDownloadFiles()560 void BackgroundCloudFileProcessor::StopDownloadFiles()
561 {
562     if (downloadId_ != DOWNLOAD_ID_DEFAULT) {
563         int32_t ret = CloudSyncManager::GetInstance().StopFileCache(downloadId_);
564         MEDIA_INFO_LOG("Stop downloading cloud file, err: %{public}d, downloadId_: %{public}d",
565             ret, static_cast<int32_t>(downloadId_));
566     }
567 }
568 
HandleSuccessCallback(const DownloadProgressObj & progress)569 void BackgroundCloudFileProcessor::HandleSuccessCallback(const DownloadProgressObj& progress)
570 {
571     lock_guard<mutex> downloadLock(downloadResultMutex_);
572     bool cond = (progress.downloadId != downloadId_ || downloadResult_.find(progress.path) == downloadResult_.end());
573     CHECK_AND_RETURN_WARN_LOG(!cond,
574         "downloadId or uri is err, uri: %{public}s, downloadId: %{public}s, downloadId_: %{public}s.",
575         MediaFileUtils::DesensitizePath(progress.path).c_str(), to_string(progress.downloadId).c_str(),
576         to_string(downloadId_).c_str());
577 
578     downloadResult_[progress.path] = DownloadStatus::SUCCESS;
579     MEDIA_INFO_LOG("download success, uri: %{public}s.", MediaFileUtils::DesensitizePath(progress.path).c_str());
580 }
581 
HandleFailedCallback(const DownloadProgressObj & progress)582 void BackgroundCloudFileProcessor::HandleFailedCallback(const DownloadProgressObj& progress)
583 {
584     lock_guard<mutex> downloadLock(downloadResultMutex_);
585     bool cond = (progress.downloadId != downloadId_ || downloadResult_.find(progress.path) == downloadResult_.end());
586     CHECK_AND_RETURN_WARN_LOG(!cond,
587         "downloadId or uri is err, uri: %{public}s, downloadId: %{public}s, downloadId_: %{public}s.",
588         MediaFileUtils::DesensitizePath(progress.path).c_str(), to_string(progress.downloadId).c_str(),
589         to_string(downloadId_).c_str());
590 
591     MEDIA_ERR_LOG("download failed, error type: %{public}d, uri: %{public}s.", progress.downloadErrorType,
592         MediaFileUtils::DesensitizePath(progress.path).c_str());
593     switch (progress.downloadErrorType) {
594         case static_cast<int32_t>(DownloadProgressObj::DownloadErrorType::NETWORK_UNAVAILABLE): {
595             downloadResult_[progress.path] = DownloadStatus::NETWORK_UNAVAILABLE;
596             break;
597         }
598         case static_cast<int32_t>(DownloadProgressObj::DownloadErrorType::LOCAL_STORAGE_FULL): {
599             downloadResult_[progress.path] = DownloadStatus::STORAGE_FULL;
600             break;
601         }
602         default: {
603             downloadResult_[progress.path] = DownloadStatus::UNKNOWN;
604             MEDIA_WARN_LOG("download error type not exit.");
605             break;
606         }
607     }
608 }
609 
HandleStoppedCallback(const DownloadProgressObj & progress)610 void BackgroundCloudFileProcessor::HandleStoppedCallback(const DownloadProgressObj& progress)
611 {
612     lock_guard<mutex> downloadLock(downloadResultMutex_);
613     bool cond = (progress.downloadId != downloadId_ || downloadResult_.find(progress.path) == downloadResult_.end());
614     CHECK_AND_RETURN_WARN_LOG(!cond,
615         "downloadId or uri is err, uri: %{public}s, downloadId: %{public}s, downloadId_: %{public}s.",
616         MediaFileUtils::DesensitizePath(progress.path).c_str(), to_string(progress.downloadId).c_str(),
617         to_string(downloadId_).c_str());
618 
619     downloadResult_[progress.path] = DownloadStatus::STOPPED;
620     UpdateDownloadCnt(progress.path, 0);
621     MEDIA_ERR_LOG("download stopped, uri: %{public}s.", MediaFileUtils::DesensitizePath(progress.path).c_str());
622 }
623 
SetPredicates(NativeRdb::RdbPredicates & predicates,bool isCloud,bool isVideo)624 void BackgroundCloudFileProcessor::SetPredicates(NativeRdb::RdbPredicates &predicates, bool isCloud, bool isVideo)
625 {
626     if (isCloud) {
627         predicates.EqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::CLOUD))
628             ->OrderByAsc(MediaColumn::MEDIA_ID)
629             ->Limit(cloudUpdateOffset_, UPDATE_BATCH_CLOUD_SIZE);
630     } else {
631         if (isVideo) {
632             predicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::CLOUD))->And()
633                 ->BeginWrap()
634                 ->EqualTo(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(MEDIA_TYPE_VIDEO))->And()
635                 ->BeginWrap()
636                 ->EqualTo(MediaColumn::MEDIA_DURATION, 0)->Or()
637                 ->IsNull(MediaColumn::MEDIA_DURATION)
638                 ->EndWrap()
639                 ->EndWrap()
640                 ->OrderByAsc(MediaColumn::MEDIA_ID)
641                 ->Limit(localVideoUpdateOffset_, UPDATE_BATCH_LOCAL_VIDEO_SIZE);
642         } else {
643             predicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::CLOUD))->And()
644                 ->NotEqualTo(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(MEDIA_TYPE_VIDEO))
645                 ->OrderByAsc(MediaColumn::MEDIA_ID)
646                 ->Limit(localImageUpdateOffset_, UPDATE_BATCH_LOCAL_IMAGE_SIZE);
647         }
648     }
649 }
650 
QueryUpdateData(bool isCloud,bool isVideo)651 std::shared_ptr<NativeRdb::ResultSet> BackgroundCloudFileProcessor::QueryUpdateData(bool isCloud, bool isVideo)
652 {
653     const std::vector<std::string> columns = { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH,
654         MediaColumn::MEDIA_TYPE, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_NAME,
655         PhotoColumn::PHOTO_WIDTH, PhotoColumn::PHOTO_HEIGHT,
656         MediaColumn::MEDIA_MIME_TYPE, MediaColumn::MEDIA_DURATION, PhotoColumn::PHOTO_MEDIA_SUFFIX };
657 
658     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
659     predicates.BeginWrap()
660         ->EqualTo(MediaColumn::MEDIA_SIZE, 0)
661         ->Or()
662         ->IsNull(MediaColumn::MEDIA_SIZE)
663         ->Or()
664         ->EqualTo(PhotoColumn::PHOTO_WIDTH, 0)
665         ->Or()
666         ->IsNull(PhotoColumn::PHOTO_WIDTH)
667         ->Or()
668         ->EqualTo(PhotoColumn::PHOTO_HEIGHT, 0)
669         ->Or()
670         ->IsNull(PhotoColumn::PHOTO_HEIGHT)
671         ->Or()
672         ->EqualTo(MediaColumn::MEDIA_MIME_TYPE, "")
673         ->Or()
674         ->IsNull(MediaColumn::MEDIA_MIME_TYPE)
675         ->Or()
676         ->EqualTo(PhotoColumn::PHOTO_MEDIA_SUFFIX, "")
677         ->Or()
678         ->IsNull(PhotoColumn::PHOTO_MEDIA_SUFFIX)
679         ->Or()
680         ->BeginWrap()
681         ->EqualTo(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(MEDIA_TYPE_VIDEO))
682         ->And()
683         ->BeginWrap()
684         ->EqualTo(MediaColumn::MEDIA_DURATION, 0)
685         ->Or()
686         ->IsNull(MediaColumn::MEDIA_DURATION)
687         ->EndWrap()
688         ->EndWrap()
689         ->EndWrap()
690         ->And()
691         ->EqualTo(MediaColumn::MEDIA_TIME_PENDING, 0)
692         ->And()
693         ->EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE))
694         ->And()
695         ->EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN))
696         ->And();
697     SetPredicates(predicates, isCloud, isVideo);
698     return MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
699 }
700 
ParseUpdateData(std::shared_ptr<NativeRdb::ResultSet> & resultSet,UpdateData & updateData,bool isCloud,bool isVideo)701 void BackgroundCloudFileProcessor::ParseUpdateData(std::shared_ptr<NativeRdb::ResultSet> &resultSet,
702     UpdateData &updateData, bool isCloud, bool isVideo)
703 {
704     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
705         int32_t fileId =
706             get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32));
707         int64_t size =
708             get<int64_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_SIZE, resultSet, TYPE_INT64));
709         int32_t width =
710             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_WIDTH, resultSet, TYPE_INT32));
711         int32_t height =
712             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_HEIGHT, resultSet, TYPE_INT32));
713         int32_t duration =
714             get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DURATION, resultSet, TYPE_INT32));
715         std::string path =
716             get<std::string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH, resultSet, TYPE_STRING));
717         std::string displayName =
718             get<std::string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_NAME, resultSet, TYPE_STRING));
719         if (path.empty()) {
720             MEDIA_WARN_LOG("Failed to get data path");
721             continue;
722         }
723         std::string mimeType =
724             get<std::string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_MIME_TYPE, resultSet, TYPE_STRING));
725         std::string suffix =
726             get<std::string>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_MEDIA_SUFFIX, resultSet, TYPE_STRING));
727         int32_t mediaType =
728             get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_TYPE, resultSet, TYPE_INT32));
729 
730         AbnormalData abnormalData;
731         abnormalData.fileId = fileId;
732         abnormalData.path = path;
733         abnormalData.displayName = displayName;
734         abnormalData.size = size;
735         abnormalData.width = width;
736         abnormalData.height = height;
737         abnormalData.duration = duration;
738         abnormalData.mimeType = mimeType;
739         abnormalData.mediaSuffix = suffix;
740         abnormalData.isCloud = isCloud;
741         abnormalData.isVideo = isVideo;
742 
743         if (isCloud && mediaType == static_cast<int32_t>(MEDIA_TYPE_VIDEO)) {
744             updateData.abnormalData.clear();
745             abnormalData.mediaType = MEDIA_TYPE_VIDEO;
746             updateData.abnormalData.push_back(abnormalData);
747             return;
748         }
749         abnormalData.mediaType = static_cast<MediaType>(mediaType);
750         updateData.abnormalData.push_back(abnormalData);
751     }
752 }
753 
AddUpdateDataTask(const UpdateData & updateData)754 int32_t BackgroundCloudFileProcessor::AddUpdateDataTask(const UpdateData &updateData)
755 {
756     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
757     CHECK_AND_RETURN_RET_LOG(asyncWorker != nullptr, E_FAIL, "Failed to get async worker instance!");
758 
759     auto *taskData = new (std::nothrow) UpdateAbnormalData(updateData);
760     CHECK_AND_RETURN_RET_LOG(taskData != nullptr, E_NO_MEMORY, "Failed to alloc async data for update cloud data!");
761 
762     auto asyncTask = std::make_shared<MediaLibraryAsyncTask>(UpdateCloudDataExecutor, taskData);
763     asyncWorker->AddTask(asyncTask, false);
764     return E_OK;
765 }
766 
UpdateCurrentOffset(bool isCloud,bool isVideo)767 void BackgroundCloudFileProcessor::UpdateCurrentOffset(bool isCloud, bool isVideo)
768 {
769     if (isCloud) {
770         if (cloudRetryCount_ >= MAX_RETRY_COUNT) {
771             cloudUpdateOffset_ += 1;
772             cloudRetryCount_ = 0;
773         } else {
774             cloudRetryCount_ += 1;
775         }
776         MEDIA_INFO_LOG("cloudUpdateOffset_ is %{public}d, cloudRetryCount_ is %{public}d",
777             cloudUpdateOffset_, cloudRetryCount_);
778         return;
779     }
780     if (isVideo) {
781         localVideoUpdateOffset_++;
782         MEDIA_INFO_LOG("localVideoUpdateOffset_ is %{public}d", localVideoUpdateOffset_);
783     } else {
784         localImageUpdateOffset_++;
785         MEDIA_INFO_LOG("localImageUpdateOffset_ is %{public}d", localImageUpdateOffset_);
786     }
787 }
788 
UpdateCloudDataExecutor(AsyncTaskData * data)789 void BackgroundCloudFileProcessor::UpdateCloudDataExecutor(AsyncTaskData *data)
790 {
791     auto *taskData = static_cast<UpdateAbnormalData *>(data);
792     auto updateData = taskData->updateData_;
793 
794     MEDIA_INFO_LOG("start update %{public}zu cloud files.", updateData.abnormalData.size());
795     for (const auto &abnormalData : updateData.abnormalData) {
796         CHECK_AND_RETURN_LOG(isUpdating_, "stop update data, isUpdating_ is %{public}d.", isUpdating_);
797         std::unique_ptr<Metadata> metadata = make_unique<Metadata>();
798         metadata->SetFilePath(abnormalData.path);
799         metadata->SetFileMediaType(abnormalData.mediaType);
800         metadata->SetFileId(abnormalData.fileId);
801         metadata->SetFileDuration(abnormalData.duration);
802         metadata->SetFileHeight(abnormalData.height);
803         metadata->SetFileWidth(abnormalData.width);
804         metadata->SetFileSize(abnormalData.size);
805         metadata->SetFileMimeType(abnormalData.mimeType);
806         GetSizeAndMimeType(metadata);
807         metadata->SetFileExtension(ScannerUtils::GetFileExtension(abnormalData.displayName));
808         if (abnormalData.size == 0 || abnormalData.mimeType.empty()) {
809             int64_t fileSize = metadata->GetFileSize();
810             string mimeType =  metadata->GetFileMimeType();
811             metadata->SetFileSize(fileSize == 0 ? -1: fileSize);
812             metadata->SetFileMimeType(mimeType.empty() ? DEFAULT_IMAGE_MIME_TYPE : mimeType);
813         }
814         if (abnormalData.width == 0 || abnormalData.height == 0
815             || (abnormalData.duration == 0 && abnormalData.mediaType == MEDIA_TYPE_VIDEO)) {
816             int32_t ret = GetExtractMetadata(metadata);
817             if (ret != E_OK && MediaFileUtils::IsFileExists(abnormalData.path)) {
818                 UpdateCurrentOffset(abnormalData.isCloud, abnormalData.isVideo);
819                 MEDIA_ERR_LOG("failed to get extract metadata! err: %{public}d.", ret);
820                 continue;
821             }
822             int32_t width = metadata->GetFileWidth();
823             int32_t height = metadata->GetFileHeight();
824             int32_t duration = metadata->GetFileDuration();
825             metadata->SetFileWidth(width == 0 ? -1: width);
826             metadata->SetFileHeight(height == 0 ? -1: height);
827             metadata->SetFileDuration((duration == 0 && abnormalData.mediaType == MEDIA_TYPE_VIDEO) ? -1: duration);
828         }
829         UpdateAbnormaldata(metadata, PhotoColumn::PHOTOS_TABLE);
830         if (abnormalData.isCloud) {
831             cloudRetryCount_ = 0;
832         }
833     }
834 }
835 
SetAbnormalValuesFromMetaData(std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & values)836 static void SetAbnormalValuesFromMetaData(std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &values)
837 {
838     values.PutLong(MediaColumn::MEDIA_SIZE, metadata->GetFileSize());
839     values.PutInt(MediaColumn::MEDIA_DURATION, metadata->GetFileDuration());
840     values.PutInt(PhotoColumn::PHOTO_HEIGHT, metadata->GetFileHeight());
841     values.PutInt(PhotoColumn::PHOTO_WIDTH, metadata->GetFileWidth());
842     values.PutString(MediaColumn::MEDIA_MIME_TYPE, metadata->GetFileMimeType());
843     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, metadata->GetFileExtension());
844 }
845 
UpdateAbnormaldata(std::unique_ptr<Metadata> & metadata,const std::string & tableName)846 void BackgroundCloudFileProcessor::UpdateAbnormaldata(std::unique_ptr<Metadata> &metadata, const std::string &tableName)
847 {
848     int32_t updateCount(0);
849     NativeRdb::ValuesBucket values;
850     string whereClause = MediaColumn::MEDIA_ID + " = ?";
851     vector<string> whereArgs = { to_string(metadata->GetFileId()) };
852     SetAbnormalValuesFromMetaData(metadata, values);
853 
854     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
855     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Update operation failed. rdbStore is null");
856     CHECK_AND_RETURN_LOG(isUpdating_, "stop update data,isUpdating_ is %{public}d.", isUpdating_);
857 
858     int32_t result = rdbStore->Update(updateCount, tableName, values, whereClause, whereArgs);
859     bool cond = (result != NativeRdb::E_OK || updateCount <= 0);
860     CHECK_AND_RETURN_LOG(!cond, "Update operation failed. Result %{public}d. Updated %{public}d",
861         result, updateCount);
862 }
863 
GetSizeAndMimeType(std::unique_ptr<Metadata> & metadata)864 void BackgroundCloudFileProcessor::GetSizeAndMimeType(std::unique_ptr<Metadata> &metadata)
865 {
866     std::string path = metadata->GetFilePath();
867     struct stat statInfo {};
868     if (stat(path.c_str(), &statInfo) != 0) {
869         MEDIA_ERR_LOG("stat syscall err %{public}d", errno);
870         metadata->SetFileSize(static_cast<int64_t>(0));
871     } else {
872         metadata->SetFileSize(statInfo.st_size);
873     }
874     string extension = ScannerUtils::GetFileExtension(path);
875     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension);
876     metadata->SetFileExtension(extension);
877     metadata->SetFileMimeType(mimeType);
878 }
879 
GetExtractMetadata(std::unique_ptr<Metadata> & metadata)880 int32_t BackgroundCloudFileProcessor::GetExtractMetadata(std::unique_ptr<Metadata> &metadata)
881 {
882     int32_t err = 0;
883     if (metadata->GetFileMediaType() == MEDIA_TYPE_IMAGE) {
884         err = MetadataExtractor::ExtractImageMetadata(metadata);
885     } else {
886         err = MetadataExtractor::ExtractAVMetadata(metadata);
887     }
888 
889     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "failed to extract data");
890     return E_OK;
891 }
892 
StopUpdateData()893 void BackgroundCloudFileProcessor::StopUpdateData()
894 {
895     isUpdating_ = false;
896 }
897 
StartTimer()898 void BackgroundCloudFileProcessor::StartTimer()
899 {
900     lock_guard<recursive_mutex> lock(mutex_);
901     MEDIA_INFO_LOG("Turn on the background download cloud file timer");
902     CHECK_AND_EXECUTE(cloudDataTimerId_ <= 0, timer_.Unregister(cloudDataTimerId_));
903     CHECK_AND_EXECUTE(startTimerId_ <= 0, timer_.Unregister(startTimerId_));
904     uint32_t ret = timer_.Setup();
905     CHECK_AND_PRINT_LOG(ret == Utils::TIMER_ERR_OK,
906         "Failed to start background download cloud files timer, err: %{public}d", ret);
907     isUpdating_ = true;
908     cloudDataTimerId_ = timer_.Register(ProcessCloudData, processInterval_);
909     if (!GetDownloadLatestFinished()) {
910         auto currentMilliSecond = MediaFileUtils::UTCTimeMilliSeconds();
911         SetLastDownloadMilliSecond(currentMilliSecond);
912         startTimerId_ = timer_.Register(DownloadCloudFiles, downloadInterval_);
913     }
914 }
915 
StopTimer()916 void BackgroundCloudFileProcessor::StopTimer()
917 {
918     lock_guard<recursive_mutex> lock(mutex_);
919     MEDIA_INFO_LOG("Turn off the background download cloud file timer");
920 
921     timer_.Unregister(cloudDataTimerId_);
922     timer_.Unregister(startTimerId_);
923     timer_.Unregister(stopTimerId_);
924     timer_.Shutdown();
925     cloudDataTimerId_ = 0;
926     startTimerId_ = 0;
927     stopTimerId_ = 0;
928     StopUpdateData();
929     StopDownloadFiles();
930 }
931 // LCOV_EXCL_STOP
932 } // namespace Media
933 } // namespace OHOS
934