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