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_unistore_manager.h"
33 #include "metadata_extractor.h"
34 #include "mimetype_utils.h"
35 #include "rdb_store.h"
36 #include "rdb_utils.h"
37 #include "result_set_utils.h"
38 #include "userfile_manager_types.h"
39 #include "values_bucket.h"
40
41 namespace OHOS {
42 namespace Media {
43 using namespace FileManagement::CloudSync;
44
45 static constexpr int32_t DOWNLOAD_BATCH_SIZE = 2;
46 static constexpr int32_t UPDATE_BATCH_CLOUD_SIZE = 2;
47 static constexpr int32_t UPDATE_BATCH_LOCAL_VIDEO_SIZE = 50;
48 static constexpr int32_t UPDATE_BATCH_LOCAL_IMAGE_SIZE = 200;
49 static constexpr int32_t MAX_RETRY_COUNT = 2;
50
51 // The task can be performed only when the ratio of available storage capacity reaches this value
52 static constexpr double PROPER_DEVICE_STORAGE_CAPACITY_RATIO = 0.55;
53
54 int32_t BackgroundCloudFileProcessor::processInterval_ = PROCESS_INTERVAL; // 5 minute
55 int32_t BackgroundCloudFileProcessor::downloadDuration_ = DOWNLOAD_DURATION; // 10 seconds
56 recursive_mutex BackgroundCloudFileProcessor::mutex_;
57 Utils::Timer BackgroundCloudFileProcessor::timer_("background_cloud_file_processor");
58 uint32_t BackgroundCloudFileProcessor::startTimerId_ = 0;
59 uint32_t BackgroundCloudFileProcessor::stopTimerId_ = 0;
60 std::vector<std::string> BackgroundCloudFileProcessor::curDownloadPaths_;
61 bool BackgroundCloudFileProcessor::isUpdating_ = true;
62 int32_t BackgroundCloudFileProcessor::cloudUpdateOffset_ = 0;
63 int32_t BackgroundCloudFileProcessor::localImageUpdateOffset_ = 0;
64 int32_t BackgroundCloudFileProcessor::localVideoUpdateOffset_ = 0;
65 int32_t BackgroundCloudFileProcessor::cloudRetryCount_ = 0;
66 bool BackgroundCloudFileProcessor::isDownload_ = false;
67
DownloadCloudFiles()68 void BackgroundCloudFileProcessor::DownloadCloudFiles()
69 {
70 if (!isDownload_) {
71 MEDIA_DEBUG_LOG("download task is closed");
72 return;
73 }
74 MEDIA_DEBUG_LOG("Start downloading cloud files task");
75 if (IsStorageInsufficient()) {
76 MEDIA_WARN_LOG("Insufficient storage space, stop downloading cloud files");
77 return;
78 }
79
80 auto resultSet = QueryCloudFiles();
81 if (resultSet == nullptr) {
82 MEDIA_ERR_LOG("Failed to query cloud files!");
83 return;
84 }
85
86 DownloadFiles downloadFiles;
87 ParseDownloadFiles(resultSet, downloadFiles);
88 if (downloadFiles.paths.empty()) {
89 MEDIA_DEBUG_LOG("No cloud files need to be downloaded");
90 return;
91 }
92
93 int32_t ret = AddDownloadTask(downloadFiles);
94 if (ret != E_OK) {
95 MEDIA_ERR_LOG("Failed to add download task! err: %{public}d", ret);
96 }
97 }
98
UpdateCloudData()99 void BackgroundCloudFileProcessor::UpdateCloudData()
100 {
101 MEDIA_DEBUG_LOG("Start update cloud data task");
102 std::vector<QueryOption> queryList = {{false, true}, {false, false}, {true, true}};
103 std::shared_ptr<NativeRdb::ResultSet> resultSet;
104 int32_t count = 0;
105 UpdateData updateData;
106 for (auto option : queryList) {
107 resultSet = QueryUpdateData(option.isCloud, option.isVideo);
108 if (resultSet == nullptr || resultSet->GetRowCount(count) != NativeRdb::E_OK) {
109 MEDIA_ERR_LOG("Failed to query data, %{public}d, %{public}d", option.isCloud, option.isVideo);
110 continue;
111 }
112 if (count == 0) {
113 MEDIA_DEBUG_LOG("no need to update, %{public}d, %{public}d", option.isCloud, option.isVideo);
114 continue;
115 }
116 ParseUpdateData(resultSet, updateData, option.isCloud, option.isVideo);
117 break;
118 }
119
120 if (updateData.abnormalData.empty()) {
121 MEDIA_DEBUG_LOG("No data need to update");
122 return;
123 }
124 int32_t ret = AddUpdateDataTask(updateData);
125 if (ret != E_OK) {
126 MEDIA_ERR_LOG("Failed to add update task! err: %{public}d", ret);
127 }
128 }
129
ProcessCloudData()130 void BackgroundCloudFileProcessor::ProcessCloudData()
131 {
132 UpdateCloudData();
133 DownloadCloudFiles();
134 }
135
IsStorageInsufficient()136 bool BackgroundCloudFileProcessor::IsStorageInsufficient()
137 {
138 struct statvfs diskInfo;
139 int ret = statvfs("/data", &diskInfo);
140 if (ret != 0) {
141 MEDIA_ERR_LOG("Get file system status information failed, err: %{public}d", ret);
142 return true;
143 }
144
145 double totalSize = static_cast<double>(diskInfo.f_bsize) * static_cast<double>(diskInfo.f_blocks);
146 if (totalSize < 1e-9) {
147 MEDIA_ERR_LOG("Get file system total size failed, totalSize=%{public}f", totalSize);
148 return true;
149 }
150
151 double freeSize = static_cast<double>(diskInfo.f_bsize) * static_cast<double>(diskInfo.f_bfree);
152 double freeRatio = freeSize / totalSize;
153
154 return freeRatio < PROPER_DEVICE_STORAGE_CAPACITY_RATIO;
155 }
156
QueryCloudFiles()157 std::shared_ptr<NativeRdb::ResultSet> BackgroundCloudFileProcessor::QueryCloudFiles()
158 {
159 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
160 if (uniStore == nullptr) {
161 MEDIA_ERR_LOG("uniStore is nullptr!");
162 return nullptr;
163 }
164
165 const string sql = "SELECT " + PhotoColumn::MEDIA_FILE_PATH + ", " + PhotoColumn::MEDIA_TYPE +
166 " FROM(SELECT COUNT(*) AS count, " + PhotoColumn::MEDIA_FILE_PATH + ", " + PhotoColumn::MEDIA_TYPE + ", " +
167 MediaColumn::MEDIA_DATE_MODIFIED + " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
168 PhotoColumn::PHOTO_CLEAN_FLAG + " = " + std::to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) +
169 " AND " + PhotoColumn::PHOTO_POSITION + " = " + std::to_string(POSITION_CLOUD) + " AND " +
170 PhotoColumn::MEDIA_FILE_PATH + " IS NOT NULL AND " + PhotoColumn::MEDIA_FILE_PATH + " != '' AND " +
171 MediaColumn::MEDIA_SIZE + " > 0 AND(" + PhotoColumn::MEDIA_TYPE + " = " + std::to_string(MEDIA_TYPE_IMAGE) +
172 " OR " + PhotoColumn::MEDIA_TYPE + " = " + std::to_string(MEDIA_TYPE_VIDEO) + ") GROUP BY " +
173 PhotoColumn::MEDIA_FILE_PATH + " HAVING count = 1) ORDER BY " + PhotoColumn::MEDIA_TYPE + " DESC, " +
174 MediaColumn::MEDIA_DATE_MODIFIED + " DESC LIMIT " + std::to_string(DOWNLOAD_BATCH_SIZE);
175
176 return uniStore->QuerySql(sql);
177 }
178
ParseDownloadFiles(std::shared_ptr<NativeRdb::ResultSet> & resultSet,DownloadFiles & downloadFiles)179 void BackgroundCloudFileProcessor::ParseDownloadFiles(std::shared_ptr<NativeRdb::ResultSet> &resultSet,
180 DownloadFiles &downloadFiles)
181 {
182 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
183 std::string path =
184 get<std::string>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_FILE_PATH, resultSet, TYPE_STRING));
185 if (path.empty()) {
186 MEDIA_WARN_LOG("Failed to get cloud file uri!");
187 continue;
188 }
189 int32_t mediaType =
190 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_TYPE, resultSet, TYPE_INT32));
191 if (mediaType == static_cast<int32_t>(MEDIA_TYPE_VIDEO)) {
192 downloadFiles.paths.clear();
193 downloadFiles.paths.push_back(path);
194 downloadFiles.mediaType = MEDIA_TYPE_VIDEO;
195 return;
196 }
197 downloadFiles.paths.push_back(path);
198 }
199 downloadFiles.mediaType = MEDIA_TYPE_IMAGE;
200 }
201
AddDownloadTask(const DownloadFiles & downloadFiles)202 int32_t BackgroundCloudFileProcessor::AddDownloadTask(const DownloadFiles &downloadFiles)
203 {
204 auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
205 if (asyncWorker == nullptr) {
206 MEDIA_ERR_LOG("Failed to get async worker instance!");
207 return E_FAIL;
208 }
209
210 auto *taskData = new (std::nothrow) DownloadCloudFilesData(downloadFiles);
211 if (taskData == nullptr) {
212 MEDIA_ERR_LOG("Failed to alloc async data for downloading cloud files!");
213 return E_NO_MEMORY;
214 }
215
216 auto asyncTask = std::make_shared<MediaLibraryAsyncTask>(DownloadCloudFilesExecutor, taskData);
217 asyncWorker->AddTask(asyncTask, false);
218 return E_OK;
219 }
220
DownloadCloudFilesExecutor(AsyncTaskData * data)221 void BackgroundCloudFileProcessor::DownloadCloudFilesExecutor(AsyncTaskData *data)
222 {
223 auto *taskData = static_cast<DownloadCloudFilesData *>(data);
224 auto downloadFiles = taskData->downloadFiles_;
225
226 MEDIA_DEBUG_LOG("Try to download %{public}zu cloud files.", downloadFiles.paths.size());
227 for (const auto &path : downloadFiles.paths) {
228 int32_t ret = CloudSyncManager::GetInstance().StartDownloadFile(path);
229 if (ret != E_OK) {
230 MEDIA_ERR_LOG("Failed to download cloud file, err: %{public}d, path: %{public}s", ret, path.c_str());
231 }
232 }
233
234 lock_guard<recursive_mutex> lock(mutex_);
235 curDownloadPaths_ = downloadFiles.paths;
236 if (downloadFiles.mediaType == MEDIA_TYPE_VIDEO) {
237 if (stopTimerId_ > 0) {
238 timer_.Unregister(stopTimerId_);
239 }
240 stopTimerId_ = timer_.Register(StopDownloadFiles, downloadDuration_, true);
241 }
242 }
243
StopDownloadFiles()244 void BackgroundCloudFileProcessor::StopDownloadFiles()
245 {
246 for (const auto &path : curDownloadPaths_) {
247 MEDIA_INFO_LOG("Try to Stop downloading cloud file, the path is %{public}s", path.c_str());
248 int32_t ret = CloudSyncManager::GetInstance().StopDownloadFile(path);
249 if (ret != E_OK) {
250 MEDIA_ERR_LOG("Stop downloading cloud file failed, err: %{public}d, path: %{public}s", ret, path.c_str());
251 }
252 }
253 curDownloadPaths_.clear();
254 }
255
SetPredicates(NativeRdb::RdbPredicates & predicates,bool isCloud,bool isVideo)256 void BackgroundCloudFileProcessor::SetPredicates(NativeRdb::RdbPredicates &predicates, bool isCloud, bool isVideo)
257 {
258 if (isCloud) {
259 predicates.EqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::CLOUD))
260 ->OrderByAsc(MediaColumn::MEDIA_ID)
261 ->Limit(cloudUpdateOffset_, UPDATE_BATCH_CLOUD_SIZE);
262 } else {
263 if (isVideo) {
264 predicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::CLOUD))->And()
265 ->BeginWrap()
266 ->EqualTo(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(MEDIA_TYPE_VIDEO))->And()
267 ->BeginWrap()
268 ->EqualTo(MediaColumn::MEDIA_DURATION, 0)->Or()
269 ->IsNull(MediaColumn::MEDIA_DURATION)
270 ->EndWrap()
271 ->EndWrap()
272 ->OrderByAsc(MediaColumn::MEDIA_ID)
273 ->Limit(localVideoUpdateOffset_, UPDATE_BATCH_LOCAL_VIDEO_SIZE);
274 } else {
275 predicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::CLOUD))->And()
276 ->NotEqualTo(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(MEDIA_TYPE_VIDEO))
277 ->OrderByAsc(MediaColumn::MEDIA_ID)
278 ->Limit(localImageUpdateOffset_, UPDATE_BATCH_LOCAL_IMAGE_SIZE);
279 }
280 }
281 }
282
QueryUpdateData(bool isCloud,bool isVideo)283 std::shared_ptr<NativeRdb::ResultSet> BackgroundCloudFileProcessor::QueryUpdateData(bool isCloud, bool isVideo)
284 {
285 const std::vector<std::string> columns = { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH,
286 MediaColumn::MEDIA_TYPE, MediaColumn::MEDIA_SIZE,
287 PhotoColumn::PHOTO_WIDTH, PhotoColumn::PHOTO_HEIGHT,
288 MediaColumn::MEDIA_MIME_TYPE, MediaColumn::MEDIA_DURATION };
289
290 NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
291 predicates.BeginWrap()
292 ->EqualTo(MediaColumn::MEDIA_SIZE, 0)
293 ->Or()
294 ->IsNull(MediaColumn::MEDIA_SIZE)
295 ->Or()
296 ->EqualTo(PhotoColumn::PHOTO_WIDTH, 0)
297 ->Or()
298 ->IsNull(PhotoColumn::PHOTO_WIDTH)
299 ->Or()
300 ->EqualTo(PhotoColumn::PHOTO_HEIGHT, 0)
301 ->Or()
302 ->IsNull(PhotoColumn::PHOTO_HEIGHT)
303 ->Or()
304 ->EqualTo(MediaColumn::MEDIA_MIME_TYPE, "")
305 ->Or()
306 ->IsNull(MediaColumn::MEDIA_MIME_TYPE)
307 ->Or()
308 ->BeginWrap()
309 ->EqualTo(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(MEDIA_TYPE_VIDEO))
310 ->And()
311 ->BeginWrap()
312 ->EqualTo(MediaColumn::MEDIA_DURATION, 0)
313 ->Or()
314 ->IsNull(MediaColumn::MEDIA_DURATION)
315 ->EndWrap()
316 ->EndWrap()
317 ->EndWrap()
318 ->And()
319 ->EqualTo(MediaColumn::MEDIA_TIME_PENDING, 0)
320 ->And()
321 ->EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE))
322 ->And()
323 ->EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN))
324 ->And();
325 SetPredicates(predicates, isCloud, isVideo);
326 return MediaLibraryRdbStore::Query(predicates, columns);
327 }
328
ParseUpdateData(std::shared_ptr<NativeRdb::ResultSet> & resultSet,UpdateData & updateData,bool isCloud,bool isVideo)329 void BackgroundCloudFileProcessor::ParseUpdateData(std::shared_ptr<NativeRdb::ResultSet> &resultSet,
330 UpdateData &updateData, bool isCloud, bool isVideo)
331 {
332 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
333 int32_t fileId =
334 get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32));
335 int64_t size =
336 get<int64_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_SIZE, resultSet, TYPE_INT64));
337 int32_t width =
338 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_WIDTH, resultSet, TYPE_INT32));
339 int32_t height =
340 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_HEIGHT, resultSet, TYPE_INT32));
341 int32_t duration =
342 get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DURATION, resultSet, TYPE_INT32));
343 std::string path =
344 get<std::string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH, resultSet, TYPE_STRING));
345 if (path.empty()) {
346 MEDIA_WARN_LOG("Failed to get data path");
347 continue;
348 }
349 std::string mimeType =
350 get<std::string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_MIME_TYPE, resultSet, TYPE_STRING));
351 int32_t mediaType =
352 get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_TYPE, resultSet, TYPE_INT32));
353
354 AbnormalData abnormalData;
355 abnormalData.fileId = fileId;
356 abnormalData.path = path;
357 abnormalData.size = size;
358 abnormalData.width = width;
359 abnormalData.height = height;
360 abnormalData.duration = duration;
361 abnormalData.mimeType = mimeType;
362 abnormalData.isCloud = isCloud;
363 abnormalData.isVideo = isVideo;
364
365 if (isCloud && mediaType == static_cast<int32_t>(MEDIA_TYPE_VIDEO)) {
366 updateData.abnormalData.clear();
367 abnormalData.mediaType = MEDIA_TYPE_VIDEO;
368 updateData.abnormalData.push_back(abnormalData);
369 return;
370 }
371 abnormalData.mediaType = static_cast<MediaType>(mediaType);
372 updateData.abnormalData.push_back(abnormalData);
373 }
374 }
375
AddUpdateDataTask(const UpdateData & updateData)376 int32_t BackgroundCloudFileProcessor::AddUpdateDataTask(const UpdateData &updateData)
377 {
378 auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
379 if (asyncWorker == nullptr) {
380 MEDIA_ERR_LOG("Failed to get async worker instance!");
381 return E_FAIL;
382 }
383
384 auto *taskData = new (std::nothrow) UpdateAbnormalData(updateData);
385 if (taskData == nullptr) {
386 MEDIA_ERR_LOG("Failed to alloc async data for update cloud data!");
387 return E_NO_MEMORY;
388 }
389
390 auto asyncTask = std::make_shared<MediaLibraryAsyncTask>(UpdateCloudDataExecutor, taskData);
391 asyncWorker->AddTask(asyncTask, false);
392 return E_OK;
393 }
394
UpdateCurrentOffset(bool isCloud,bool isVideo)395 void BackgroundCloudFileProcessor::UpdateCurrentOffset(bool isCloud, bool isVideo)
396 {
397 if (isCloud) {
398 if (cloudRetryCount_ >= MAX_RETRY_COUNT) {
399 cloudUpdateOffset_ += 1;
400 cloudRetryCount_ = 0;
401 } else {
402 cloudRetryCount_ += 1;
403 }
404 MEDIA_INFO_LOG("cloudUpdateOffset_ is %{public}d, cloudRetryCount_ is %{public}d",
405 cloudUpdateOffset_, cloudRetryCount_);
406 return;
407 }
408 if (isVideo) {
409 localVideoUpdateOffset_++;
410 MEDIA_INFO_LOG("localVideoUpdateOffset_ is %{public}d", localVideoUpdateOffset_);
411 } else {
412 localImageUpdateOffset_++;
413 MEDIA_INFO_LOG("localImageUpdateOffset_ is %{public}d", localImageUpdateOffset_);
414 }
415 }
416
UpdateCloudDataExecutor(AsyncTaskData * data)417 void BackgroundCloudFileProcessor::UpdateCloudDataExecutor(AsyncTaskData *data)
418 {
419 auto *taskData = static_cast<UpdateAbnormalData *>(data);
420 auto updateData = taskData->updateData_;
421
422 MEDIA_INFO_LOG("start update %{public}zu cloud files.", updateData.abnormalData.size());
423 for (const auto &abnormalData : updateData.abnormalData) {
424 if (!isUpdating_) {
425 MEDIA_INFO_LOG("stop update data, isUpdating_ is %{public}d.", isUpdating_);
426 return;
427 }
428 std::unique_ptr<Metadata> metadata = make_unique<Metadata>();
429 metadata->SetFilePath(abnormalData.path);
430 metadata->SetFileMediaType(abnormalData.mediaType);
431 metadata->SetFileId(abnormalData.fileId);
432 metadata->SetFileDuration(abnormalData.duration);
433 metadata->SetFileHeight(abnormalData.height);
434 metadata->SetFileWidth(abnormalData.width);
435 metadata->SetFileSize(abnormalData.size);
436 metadata->SetFileMimeType(abnormalData.mimeType);
437 GetSizeAndMimeType(metadata);
438 if (abnormalData.size == 0 || abnormalData.mimeType.empty()) {
439 int64_t fileSize = metadata->GetFileSize();
440 string mimeType = metadata->GetFileMimeType();
441 metadata->SetFileSize(fileSize == 0 ? -1: fileSize);
442 metadata->SetFileMimeType(mimeType.empty() ? DEFAULT_IMAGE_MIME_TYPE : mimeType);
443 }
444 if (abnormalData.width == 0 || abnormalData.height == 0
445 || (abnormalData.duration == 0 && abnormalData.mediaType == MEDIA_TYPE_VIDEO)) {
446 int32_t ret = GetExtractMetadata(metadata);
447 if (ret != E_OK && MediaFileUtils::IsFileExists(abnormalData.path)) {
448 UpdateCurrentOffset(abnormalData.isCloud, abnormalData.isVideo);
449 MEDIA_ERR_LOG("failed to get extract metadata! err: %{public}d.", ret);
450 continue;
451 }
452 int32_t width = metadata->GetFileWidth();
453 int32_t height = metadata->GetFileHeight();
454 int32_t duration = metadata->GetFileDuration();
455 metadata->SetFileWidth(width == 0 ? -1: width);
456 metadata->SetFileHeight(height == 0 ? -1: height);
457 metadata->SetFileDuration((duration == 0 && abnormalData.mediaType == MEDIA_TYPE_VIDEO) ? -1: duration);
458 }
459 UpdateAbnormaldata(metadata, PhotoColumn::PHOTOS_TABLE);
460 if (abnormalData.isCloud) {
461 cloudRetryCount_ = 0;
462 }
463 }
464 }
465
SetAbnormalValuesFromMetaData(std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & values)466 static void SetAbnormalValuesFromMetaData(std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &values)
467 {
468 values.PutLong(MediaColumn::MEDIA_SIZE, metadata->GetFileSize());
469 values.PutInt(MediaColumn::MEDIA_DURATION, metadata->GetFileDuration());
470 values.PutInt(PhotoColumn::PHOTO_HEIGHT, metadata->GetFileHeight());
471 values.PutInt(PhotoColumn::PHOTO_WIDTH, metadata->GetFileWidth());
472 values.PutString(MediaColumn::MEDIA_MIME_TYPE, metadata->GetFileMimeType());
473 }
474
UpdateAbnormaldata(std::unique_ptr<Metadata> & metadata,const std::string & tableName)475 void BackgroundCloudFileProcessor::UpdateAbnormaldata(std::unique_ptr<Metadata> &metadata, const std::string &tableName)
476 {
477 int32_t updateCount(0);
478 NativeRdb::ValuesBucket values;
479 string whereClause = MediaColumn::MEDIA_ID + " = ?";
480 vector<string> whereArgs = { to_string(metadata->GetFileId()) };
481 SetAbnormalValuesFromMetaData(metadata, values);
482 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
483 if (rdbStore == nullptr) {
484 MEDIA_ERR_LOG("Update operation failed. rdbStore is null");
485 return ;
486 }
487 if (!isUpdating_) {
488 MEDIA_INFO_LOG("stop update data,isUpdating_ is %{public}d.", isUpdating_);
489 return;
490 }
491 int32_t result = rdbStore->Update(updateCount, tableName, values, whereClause, whereArgs);
492 if (result != NativeRdb::E_OK || updateCount <= 0) {
493 MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
494 return ;
495 }
496 MEDIA_INFO_LOG("id:%{public}d, duration:%{public}d, height:%{public}d, width:%{public}d, size:%{public}" PRId64,
497 metadata->GetFileId(), metadata->GetFileDuration(), metadata->GetFileHeight(), metadata->GetFileWidth(),
498 metadata->GetFileSize());
499 }
500
GetSizeAndMimeType(std::unique_ptr<Metadata> & metadata)501 void BackgroundCloudFileProcessor::GetSizeAndMimeType(std::unique_ptr<Metadata> &metadata)
502 {
503 std::string path = metadata->GetFilePath();
504 struct stat statInfo {};
505 if (stat(path.c_str(), &statInfo) != 0) {
506 MEDIA_ERR_LOG("stat syscall err %{public}d", errno);
507 metadata->SetFileSize(static_cast<int64_t>(0));
508 } else {
509 metadata->SetFileSize(statInfo.st_size);
510 }
511 string extension = ScannerUtils::GetFileExtension(path);
512 string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension);
513 metadata->SetFileExtension(extension);
514 metadata->SetFileMimeType(mimeType);
515 }
516
GetExtractMetadata(std::unique_ptr<Metadata> & metadata)517 int32_t BackgroundCloudFileProcessor::GetExtractMetadata(std::unique_ptr<Metadata> &metadata)
518 {
519 int32_t err = 0;
520 if (metadata->GetFileMediaType() == MEDIA_TYPE_IMAGE) {
521 err = MetadataExtractor::ExtractImageMetadata(metadata);
522 } else {
523 err = MetadataExtractor::ExtractAVMetadata(metadata);
524 }
525 if (err != E_OK) {
526 MEDIA_ERR_LOG("failed to extract data");
527 return err;
528 }
529 return E_OK;
530 }
531
StopUpdateData()532 void BackgroundCloudFileProcessor::StopUpdateData()
533 {
534 isUpdating_ = false;
535 }
536
StartTimer()537 void BackgroundCloudFileProcessor::StartTimer()
538 {
539 lock_guard<recursive_mutex> lock(mutex_);
540 MEDIA_INFO_LOG("Turn on the background download cloud file timer");
541
542 if (startTimerId_ > 0) {
543 timer_.Unregister(startTimerId_);
544 }
545 uint32_t ret = timer_.Setup();
546 if (ret != Utils::TIMER_ERR_OK) {
547 MEDIA_ERR_LOG("Failed to start background download cloud files timer, err: %{public}d", ret);
548 }
549 isUpdating_ = true;
550 startTimerId_ = timer_.Register(ProcessCloudData, processInterval_);
551 }
552
StopTimer()553 void BackgroundCloudFileProcessor::StopTimer()
554 {
555 lock_guard<recursive_mutex> lock(mutex_);
556 MEDIA_INFO_LOG("Turn off the background download cloud file timer");
557
558 timer_.Unregister(startTimerId_);
559 timer_.Unregister(stopTimerId_);
560 timer_.Shutdown();
561 startTimerId_ = 0;
562 stopTimerId_ = 0;
563 StopUpdateData();
564 StopDownloadFiles();
565 }
566 } // namespace Media
567 } // namespace OHOS
568