1 /*
2 * Copyright (C) 2023-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define MLOG_TAG "MediaLibraryBaseRestore"
17
18 #include "base_restore.h"
19
20 #include <sstream>
21 #include <cinttypes>
22 #include "application_context.h"
23 #include "background_task_mgr_helper.h"
24 #include "backup_database_utils.h"
25 #include "backup_dfx_utils.h"
26 #include "backup_file_utils.h"
27 #include "backup_log_utils.h"
28 #include "cloud_sync_manager.h"
29 #include "cloud_sync_utils.h"
30 #include "directory_ex.h"
31 #include "extension_context.h"
32 #include "media_column.h"
33 #include "media_log.h"
34 #include "media_file_utils.h"
35 #include "media_image_framework_utils.h"
36 #include "media_scanner_manager.h"
37 #include "medialibrary_asset_operations.h"
38 #include "medialibrary_business_code.h"
39 #include "medialibrary_data_manager.h"
40 #include "medialibrary_object_utils.h"
41 #include "medialibrary_rdb_utils.h"
42 #include "medialibrary_type_const.h"
43 #include "medialibrary_errno.h"
44 #include "moving_photo_file_utils.h"
45 #include <nlohmann/json.hpp>
46 #include "parameters.h"
47 #include "photo_album_column.h"
48 #include "result_set_utils.h"
49 #include "resource_type.h"
50 #include "userfilemgr_uri.h"
51 #include "user_define_ipc_client.h"
52 #include "medialibrary_notify.h"
53 #include "upgrade_restore_task_report.h"
54 #include "medialibrary_rdb_transaction.h"
55 #include "database_report.h"
56 #include "ohos_account_kits.h"
57
58
59 namespace OHOS {
60 namespace Media {
61 const std::string DATABASE_PATH = "/data/storage/el2/database/rdb/media_library.db";
62 const std::string SINGLE_DIR_NAME = "A";
63 const std::string CLONE_FLAG = "multimedia.medialibrary.cloneFlag";
64 const std::string RESTORE_FLAG = "multimedia.medialibrary.restoreFlag";
65 const std::string BACKUP_FLAG = "multimedia.medialibrary.backupFlag";
66 // 同步服务模块使用: 时间戳|0,时间戳表征任务正在清理中,0表示无清理任务
67 const std::string CLOUDSYNC_SWITCH_STATUS_KEY = "persist.kernel.cloudsync.switch_status"; // ms
68 const std::string THM_SAVE_WITHOUT_ROTATE_PATH = "/THM_EX";
69 const std::string THUMB_EX_SUFFIX = "THM_EX/THM";
70 const std::string LCD_EX_SUFFIX = "THM_EX/LCD";
71 const int64_t THUMB_DENTRY_SIZE = 2 * 1024 * 1024;
72 const int32_t ORIETATION_ZERO = 0;
73 const int32_t MIGRATE_CLOUD_THM_TYPE = 0;
74 const int32_t MIGRATE_CLOUD_LCD_TYPE = 1;
75 const int32_t APP_MAIN_DATA_USER_ID = 0;
76 const int32_t APP_TWIN_DATA_USER_ID_START = 128;
77 const int32_t APP_TWIN_DATA_USER_ID_END = 147;
78 const int32_t SINGLE_LEN_EXTRADATA = 20;
79 const double DOUBLE_EPSILON = 1e-15;
80
81 static constexpr int64_t RESTORE_OR_BACKUP_WAIT_FORCE_RETAIN_CLOUD_MEDIA_TIMEOUT_MILLISECOND = 60 * 60 * 1000;
82 static constexpr int64_t RESTORE_OR_BACKUP_WAIT_FORCE_RETAIN_CLOUD_MEDIA_SLEEP_TIME_MILLISECOND = 5000;
83
GetRestoreModeFromRestoreInfo(const string & restoreInfo)84 static int32_t GetRestoreModeFromRestoreInfo(const string &restoreInfo)
85 {
86 int32_t restoreMode = RESTORE_MODE_PROC_ALL_DATA;
87 nlohmann::json jsonObj = nlohmann::json::parse(restoreInfo, nullptr, false);
88 CHECK_AND_RETURN_RET_LOG(!jsonObj.is_discarded(), restoreMode, "parse json failed");
89
90 for (auto &obj : jsonObj) {
91 bool cond = (!obj.contains("type") || obj.at("type") != "appTwinDataRestoreState" || !obj.contains("detail"));
92 CHECK_AND_CONTINUE(!cond);
93
94 std::string curMode = obj.at("detail");
95 if (curMode == "0" || curMode == "1" || curMode == "2" || curMode == "3") {
96 restoreMode = std::stoi(curMode);
97 } else {
98 MEDIA_ERR_LOG("invalid restore mode:%{public}s", curMode.c_str());
99 }
100 }
101 return restoreMode;
102 }
103
GetRestoreMode()104 int32_t BaseRestore::GetRestoreMode()
105 {
106 return restoreMode_;
107 }
108
GetAccountValid()109 void BaseRestore::GetAccountValid()
110 {
111 if (sceneCode_ == UPGRADE_RESTORE_ID) {
112 isAccountValid_ = true;
113 return;
114 }
115 string oldId = "";
116 string newId = "";
117 nlohmann::json json_arr = nlohmann::json::parse(restoreInfo_, nullptr, false);
118 CHECK_AND_RETURN_LOG(!json_arr.is_discarded(), "cloud account parse failed.");
119
120 for (const auto& item : json_arr) {
121 if (!item.contains("type") || !item.contains("detail") || item["type"] != "dualAccountId") {
122 continue;
123 } else {
124 oldId = item["detail"];
125 MEDIA_INFO_LOG("the old is %{public}s", oldId.c_str());
126 break;
127 }
128 }
129 std::pair<bool, OHOS::AccountSA::OhosAccountInfo> ret =
130 OHOS::AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
131 if (ret.first) {
132 OHOS::AccountSA::OhosAccountInfo& resultInfo = ret.second;
133 newId = resultInfo.uid_;
134 } else {
135 MEDIA_ERR_LOG("new account logins failed.");
136 return;
137 }
138 MEDIA_INFO_LOG("the old id is %{public}s, new id is %{public}s",
139 BackupFileUtils::GarbleFilePath(oldId, sceneCode_).c_str(),
140 BackupFileUtils::GarbleFilePath(newId, sceneCode_).c_str());
141 isAccountValid_ = ((oldId != "") && (oldId == newId));
142 }
143
GetSyncSwitchOn()144 void BaseRestore::GetSyncSwitchOn()
145 {
146 syncSwitchType_ = BackupFileUtils::IsCloneCloudSyncSwitchOn(sceneCode_);
147 isSyncSwitchOn_ = (syncSwitchType_ == CheckSwitchType::SUCCESS_ON ||
148 syncSwitchType_ == CheckSwitchType::UPGRADE_FAILED_ON);
149 }
150
GetSourceDeviceInfo()151 void BaseRestore::GetSourceDeviceInfo()
152 {
153 nlohmann::json jsonArray = nlohmann::json::parse(restoreInfo_, nullptr, false);
154 CHECK_AND_RETURN_LOG(!jsonArray.is_discarded(), "GetSourceDeviceInfo parse restoreInfo_ fail.");
155
156 for (const auto& item : jsonArray) {
157 bool cond = (!item.contains("type") || !item.contains("detail"));
158 CHECK_AND_CONTINUE(!cond);
159 CHECK_AND_EXECUTE(item["type"] != "dualOdid", albumOdid_ = item["detail"]);
160 if (item["type"] == "dualDeviceSoftName") {
161 dualDeviceSoftName_ = item["detail"];
162 MEDIA_INFO_LOG("get dualDeviceSoftName, %{public}s", dualDeviceSoftName_.c_str());
163 }
164 }
165 }
166
IsRestorePhoto()167 bool BaseRestore::IsRestorePhoto()
168 {
169 if (sceneCode_ == UPGRADE_RESTORE_ID) {
170 return true;
171 }
172 nlohmann::json jsonArray = nlohmann::json::parse(restoreInfo_, nullptr, false);
173 CHECK_AND_RETURN_RET_LOG(!jsonArray.is_discarded(), true, "IsRestorePhoto parse restoreInfo_ fail.");
174
175 for (const auto& item : jsonArray) {
176 bool cond = (!item.contains("type") || !item.contains("detail") || item["type"] != STAT_KEY_BACKUP_INFO);
177 CHECK_AND_CONTINUE(!cond);
178 for (const auto& backupInfo : item["detail"]) {
179 bool conds = (backupInfo == STAT_TYPE_PHOTO || backupInfo == STAT_TYPE_VIDEO||
180 backupInfo == STAT_TYPE_GALLERY_DATA);
181 CHECK_AND_RETURN_RET(!conds, true);
182 }
183 MEDIA_INFO_LOG("not restore photo or video");
184 return false;
185 }
186 return true;
187 }
188
StartRestore(const std::string & backupRetoreDir,const std::string & upgradePath)189 void BaseRestore::StartRestore(const std::string &backupRetoreDir, const std::string &upgradePath)
190 {
191 MEDIA_INFO_LOG("enter StartRestore");
192 if (WaitSouthDeviceExitTimeout()) {
193 MEDIA_ERR_LOG("baseRestore, wait south device cleaning data timeout.");
194 SetErrorCode(RestoreError::RETAIN_FORCE_TIMEOUT);
195 ErrorInfo errorInfo(RestoreError::RETAIN_FORCE_TIMEOUT, 0, "",
196 "baseRestore, wait south device cleaning data timeout.");
197 UpgradeRestoreTaskReport(sceneCode_, taskId_).ReportError(errorInfo);
198 return;
199 }
200 MEDIA_INFO_LOG("StartRestore begin");
201
202 backupRestoreDir_ = backupRetoreDir;
203 upgradeRestoreDir_ = upgradePath;
204 int32_t errorCode = Init(backupRetoreDir, upgradePath, true);
205 GetAccountValid();
206 GetSyncSwitchOn();
207 GetSourceDeviceInfo();
208 if (errorCode == E_OK) {
209 RestorePhoto();
210 RestoreAudio();
211 MEDIA_INFO_LOG("migrate database number: %{public}lld, file number: %{public}lld (%{public}lld + "
212 "%{public}lld), duplicate number: %{public}lld + %{public}lld, audio database number:%{public}lld, "
213 "audio file number:%{public}lld, duplicate audio number: %{public}lld, map number: %{public}lld",
214 (long long)migrateDatabaseNumber_, (long long)migrateFileNumber_,
215 (long long)(migrateFileNumber_ - migrateVideoFileNumber_), (long long)migrateVideoFileNumber_,
216 (long long)migratePhotoDuplicateNumber_, (long long)migrateVideoDuplicateNumber_,
217 (long long)migrateAudioDatabaseNumber_, (long long)migrateAudioFileNumber_,
218 (long long)migrateAudioDuplicateNumber_, (long long) migrateDatabaseMapNumber_);
219 UpdateDatabase();
220 } else {
221 CHECK_AND_EXECUTE(errorCode == EXTERNAL_DB_NOT_EXIST, SetErrorCode(RestoreError::INIT_FAILED));
222 ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, errorCode);
223 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
224 }
225 HandleRestData();
226 }
227
Init(void)228 int32_t BaseRestore::Init(void)
229 {
230 if (mediaLibraryRdb_ != nullptr) {
231 return E_OK;
232 }
233 auto context = AbilityRuntime::Context::GetApplicationContext();
234 if (context == nullptr) {
235 ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "", "Failed to get context");
236 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
237 MEDIA_ERR_LOG("Failed to get context");
238 return E_FAIL;
239 }
240
241 int32_t err = BackupDatabaseUtils::InitDb(mediaLibraryRdb_, MEDIA_DATA_ABILITY_DB_NAME, DATABASE_PATH, BUNDLE_NAME,
242 true, context->GetArea());
243 if (err != E_OK) {
244 ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "", "medialibrary rdb fail, err = " + std::to_string(err));
245 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
246 MEDIA_ERR_LOG("medialibrary rdb fail, err = %{public}d", err);
247 return E_FAIL;
248 }
249
250 int32_t sceneCode = 0;
251 int32_t errCode = MediaLibraryDataManager::GetInstance()->InitMediaLibraryMgr(context, nullptr, sceneCode, false);
252 if (errCode != E_OK) {
253 ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "",
254 "When restore, InitMediaLibraryMgr fail, errcode = " + std::to_string(errCode));
255 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
256 MEDIA_ERR_LOG("When restore, InitMediaLibraryMgr fail, errcode = %{public}d", errCode);
257 return errCode;
258 }
259
260 migrateDatabaseNumber_ = 0;
261 migrateFileNumber_ = 0;
262 migrateVideoFileNumber_ = 0;
263 migrateAudioDatabaseNumber_ = 0;
264 migrateAudioFileNumber_ = 0;
265 imageNumber_ = BackupDatabaseUtils::QueryUniqueNumber(mediaLibraryRdb_, IMAGE_ASSET_TYPE);
266 videoNumber_ = BackupDatabaseUtils::QueryUniqueNumber(mediaLibraryRdb_, VIDEO_ASSET_TYPE);
267 audioNumber_ = BackupDatabaseUtils::QueryUniqueNumber(mediaLibraryRdb_, AUDIO_ASSET_TYPE);
268 MEDIA_INFO_LOG("imageNumber: %{public}d", (int)imageNumber_);
269 MEDIA_INFO_LOG("videoNumber: %{public}d", (int)videoNumber_);
270 MEDIA_INFO_LOG("audioNumber: %{public}d", (int)audioNumber_);
271 photosDataHandler_.OnStart(sceneCode_, taskId_, mediaLibraryRdb_);
272 photosDataHandler_.HandleDirtyFiles();
273 return E_OK;
274 }
275
ConvertPathToRealPath(const std::string & srcPath,const std::string & prefix,std::string & newPath,std::string & relativePath)276 bool BaseRestore::ConvertPathToRealPath(const std::string &srcPath, const std::string &prefix,
277 std::string &newPath, std::string &relativePath)
278 {
279 size_t pos = 0;
280 int32_t count = 0;
281 constexpr int32_t prefixLevel = 4;
282 for (size_t i = 0; i < srcPath.length(); i++) {
283 if (srcPath[i] == '/') {
284 count++;
285 if (count == prefixLevel) {
286 pos = i;
287 break;
288 }
289 }
290 }
291 CHECK_AND_RETURN_RET(count >= prefixLevel, false);
292 relativePath = srcPath.substr(pos);
293 if (!dualDirName_.empty() && relativePath.find(dualDirName_) != string::npos) {
294 std::size_t posStart = relativePath.find_first_of("/");
295 std::size_t posEnd = relativePath.find_first_of("/", posStart + 1);
296 if (posEnd != string::npos) {
297 string temp = relativePath.substr(posStart + 1, posEnd - posStart -1);
298 if (temp == dualDirName_) {
299 relativePath.replace(relativePath.find(dualDirName_), dualDirName_.length(), SINGLE_DIR_NAME);
300 }
301 }
302 }
303 std::string extraPrefix = BackupFileUtils::GetExtraPrefixForRealPath(sceneCode_, srcPath);
304 newPath = prefix + extraPrefix + relativePath;
305 return true;
306 }
307
QuerySql(const string & sql,const vector<string> & selectionArgs) const308 shared_ptr<NativeRdb::ResultSet> BaseRestore::QuerySql(const string &sql, const vector<string> &selectionArgs) const
309 {
310 CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, nullptr,
311 "Pointer rdb_ is nullptr. Maybe it didn't init successfully.");
312 return mediaLibraryRdb_->QuerySql(sql, selectionArgs);
313 }
314
MoveFile(const std::string & srcFile,const std::string & dstFile) const315 int32_t BaseRestore::MoveFile(const std::string &srcFile, const std::string &dstFile) const
316 {
317 if (MediaFileUtils::MoveFile(srcFile, dstFile)) {
318 return E_OK;
319 }
320 if (this->CopyFile(srcFile, dstFile) != E_OK) {
321 return E_FAIL;
322 }
323 (void)MediaFileUtils::DeleteFile(srcFile);
324 return E_OK;
325 }
326
CopyFile(const std::string & srcFile,const std::string & dstFile) const327 int32_t BaseRestore::CopyFile(const std::string &srcFile, const std::string &dstFile) const
328 {
329 if (!MediaFileUtils::CopyFileUtil(srcFile, dstFile)) {
330 MEDIA_ERR_LOG("CopyFile failed, filePath: %{private}s, errmsg: %{public}s", srcFile.c_str(),
331 strerror(errno));
332 return E_FAIL;
333 }
334 return E_OK;
335 }
336
IsFileValid(FileInfo & fileInfo,const int32_t sceneCode)337 int32_t BaseRestore::IsFileValid(FileInfo &fileInfo, const int32_t sceneCode)
338 {
339 int32_t errCode = BackupFileUtils::IsFileValid(fileInfo.filePath, DUAL_FRAME_CLONE_RESTORE_ID,
340 fileInfo.relativePath, hasLowQualityImage_);
341 if (errCode != E_OK) {
342 MEDIA_ERR_LOG("File is not valid: %{public}s, errno=%{public}d.",
343 BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode).c_str(), errno);
344 return errCode;
345 }
346
347 if (BackupFileUtils::IsLivePhoto(fileInfo)) {
348 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileValid(fileInfo.movingPhotoVideoPath), E_FAIL,
349 "Moving photo video is not valid: %{public}s, errno=%{public}d.",
350 BackupFileUtils::GarbleFilePath(fileInfo.movingPhotoVideoPath, sceneCode).c_str(), errno);
351
352 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileValid(fileInfo.extraDataPath), E_FAIL,
353 "Media extra data is not valid: %{public}s, errno=%{public}d.",
354 BackupFileUtils::GarbleFilePath(fileInfo.extraDataPath, sceneCode).c_str(), errno);
355 }
356 return E_OK;
357 }
358
RemoveDuplicateDualCloneFiles(const FileInfo & fileInfo)359 static void RemoveDuplicateDualCloneFiles(const FileInfo &fileInfo)
360 {
361 (void)MediaFileUtils::DeleteFile(fileInfo.filePath);
362 if (BackupFileUtils::IsLivePhoto(fileInfo)) {
363 (void)MediaFileUtils::DeleteFile(fileInfo.movingPhotoVideoPath);
364 (void)MediaFileUtils::DeleteFile(fileInfo.extraDataPath);
365 }
366 }
367
NeedReportError(int32_t restoreMode,int32_t userId)368 static bool NeedReportError(int32_t restoreMode, int32_t userId)
369 {
370 if (restoreMode == RESTORE_MODE_PROC_MAIN_DATA) {
371 return userId == APP_MAIN_DATA_USER_ID;
372 } else if (restoreMode == RESTORE_MODE_PROC_TWIN_DATA) {
373 return userId >= APP_TWIN_DATA_USER_ID_START && userId <= APP_TWIN_DATA_USER_ID_END;
374 }
375
376 return true;
377 }
378
GetInsertValues(const int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)379 vector<NativeRdb::ValuesBucket> BaseRestore::GetInsertValues(const int32_t sceneCode, std::vector<FileInfo> &fileInfos,
380 int32_t sourceType)
381 {
382 vector<NativeRdb::ValuesBucket> values;
383 int64_t prepareCost = 0;
384 int64_t parseCost = 0;
385 int64_t duplicateCost = 0;
386 for (size_t i = 0; i < fileInfos.size(); i++) {
387 int64_t startPrepare = MediaFileUtils::UTCTimeMilliSeconds();
388 NativeRdb::ValuesBucket value;
389 CHECK_AND_CONTINUE(PrepareInsertValue(sceneCode, fileInfos[i], sourceType, value));
390 int64_t startMetaData = MediaFileUtils::UTCTimeMilliSeconds();
391 SetValueFromMetaData(fileInfos[i], value);
392 int64_t startDuplicate = MediaFileUtils::UTCTimeMilliSeconds();
393 if ((sceneCode == DUAL_FRAME_CLONE_RESTORE_ID || sceneCode == OTHERS_PHONE_CLONE_RESTORE ||
394 sceneCode == LITE_PHONE_CLONE_RESTORE || sceneCode == I_PHONE_CLONE_RESTORE ||
395 sceneCode == UPGRADE_RESTORE_ID || sceneCode == CLOUD_BACKUP_RESTORE_ID) &&
396 this->HasSameFileForDualClone(fileInfos[i])) {
397 fileInfos[i].needMove = false;
398 RemoveDuplicateDualCloneFiles(fileInfos[i]);
399 MEDIA_WARN_LOG("File %{public}s already exists.",
400 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
401 UpdateDuplicateNumber(fileInfos[i].fileType);
402 continue;
403 }
404 CHECK_AND_EXECUTE(!fileInfos[i].isNew, values.emplace_back(value));
405 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
406 prepareCost += startMetaData - startPrepare;
407 parseCost += startDuplicate - startMetaData;
408 duplicateCost += end - startDuplicate;
409 }
410 MEDIA_INFO_LOG("TimeCost: batch Prepare cost: %{public}" PRId64 ", SetValueFromMetaData cost: %{public}" PRId64
411 ", DuplicateDualCloneFile cost: %{public}" PRId64, prepareCost, parseCost, duplicateCost);
412 return values;
413 }
414
PrepareInsertValue(const int32_t sceneCode,FileInfo & fileInfo,int32_t sourceType,NativeRdb::ValuesBucket & value)415 bool BaseRestore::PrepareInsertValue(const int32_t sceneCode, FileInfo &fileInfo, int32_t sourceType,
416 NativeRdb::ValuesBucket &value)
417 {
418 int32_t errCode = IsFileValid(fileInfo, sceneCode);
419 if (errCode != E_OK) {
420 fileInfo.needMove = false;
421 if (!NeedReportError(restoreMode_, fileInfo.userId)) {
422 MEDIA_WARN_LOG("file not found but no need report, file name:%{public}s",
423 BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode).c_str());
424 notFoundNumber_++;
425 return false;
426 }
427 std::string fileDbCheckInfo = CheckInvalidFile(fileInfo, errCode);
428 ErrorInfo errorInfo(RestoreError::FILE_INVALID, 1, std::to_string(errCode),
429 BackupLogUtils::FileInfoToString(sceneCode, fileInfo, { fileDbCheckInfo }));
430 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
431 return false;
432 }
433 std::string cloudPath;
434 int32_t uniqueId = GetUniqueId(fileInfo.fileType);
435 errCode = BackupFileUtils::CreateAssetPathById(uniqueId, fileInfo.fileType,
436 MediaFileUtils::GetExtensionFromPath(fileInfo.displayName), cloudPath);
437 if (errCode != E_OK) {
438 fileInfo.needMove = false;
439 ErrorInfo errorInfo(RestoreError::CREATE_PATH_FAILED, 1, std::to_string(errCode),
440 BackupLogUtils::FileInfoToString(sceneCode, fileInfo));
441 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
442 return false;
443 }
444 fileInfo.cloudPath = cloudPath;
445 value = GetInsertValue(fileInfo, cloudPath, sourceType);
446 return true;
447 }
448
InsertDateTaken(std::unique_ptr<Metadata> & metadata,FileInfo & fileInfo,NativeRdb::ValuesBucket & value)449 static void InsertDateTaken(std::unique_ptr<Metadata> &metadata, FileInfo &fileInfo, NativeRdb::ValuesBucket &value)
450 {
451 int64_t dateTaken = metadata->GetDateTaken();
452 if (dateTaken > 0) {
453 bool hasDateTaken = value.HasColumn(PhotoColumn::MEDIA_DATE_TAKEN);
454 if (hasDateTaken) {
455 value.Delete(PhotoColumn::MEDIA_DATE_TAKEN);
456 }
457 value.PutLong(MediaColumn::MEDIA_DATE_TAKEN, dateTaken);
458 fileInfo.dateTaken = dateTaken;
459 return;
460 }
461
462 int64_t dateAdded = metadata->GetFileDateAdded();
463 if (dateAdded <= 0) {
464 int64_t dateModified = metadata->GetFileDateModified();
465 if (dateModified <= 0) {
466 dateTaken = MediaFileUtils::UTCTimeMilliSeconds();
467 } else {
468 dateTaken = dateModified;
469 }
470 } else {
471 dateTaken = dateAdded;
472 }
473 bool hasDateTaken = value.HasColumn(PhotoColumn::MEDIA_DATE_TAKEN);
474 if (hasDateTaken) {
475 value.Delete(PhotoColumn::MEDIA_DATE_TAKEN);
476 }
477 value.PutLong(MediaColumn::MEDIA_DATE_TAKEN, dateTaken);
478 fileInfo.dateTaken = dateTaken;
479 }
480
GetCloudInsertValues(const int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)481 vector<NativeRdb::ValuesBucket> BaseRestore::GetCloudInsertValues(const int32_t sceneCode,
482 std::vector<FileInfo> &fileInfos, int32_t sourceType)
483 {
484 MEDIA_INFO_LOG("START STEP 3 GET INSERT VALUES");
485 int64_t prepareCost = 0;
486 int64_t parseCost = 0;
487 int64_t duplicateCost = 0;
488 vector<NativeRdb::ValuesBucket> values;
489 for (size_t i = 0; i < fileInfos.size(); i++) {
490 int64_t startPrepare = MediaFileUtils::UTCTimeMilliSeconds();
491 std::string cloudPath;
492 int32_t uniqueId = GetUniqueId(fileInfos[i].fileType);
493 int32_t errCode = BackupFileUtils::CreateAssetPathById(uniqueId, fileInfos[i].fileType,
494 MediaFileUtils::GetExtensionFromPath(fileInfos[i].displayName), cloudPath);
495 if (errCode != E_OK) {
496 fileInfos[i].needMove = false;
497 ErrorInfo errorInfo(RestoreError::CREATE_PATH_FAILED, 1, std::to_string(errCode),
498 BackupLogUtils::FileInfoToString(sceneCode, fileInfos[i]));
499 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
500 continue;
501 }
502 fileInfos[i].cloudPath = cloudPath;
503 NativeRdb::ValuesBucket value = GetInsertValue(fileInfos[i], cloudPath, sourceType);
504 int64_t startMetaData = MediaFileUtils::UTCTimeMilliSeconds();
505 SetValueFromMetaData(fileInfos[i], value);
506 int64_t startDuplicate = MediaFileUtils::UTCTimeMilliSeconds();
507 if ((sceneCode == DUAL_FRAME_CLONE_RESTORE_ID || sceneCode == UPGRADE_RESTORE_ID) &&
508 this->HasSameFileForDualClone(fileInfos[i])) {
509 fileInfos[i].needMove = false;
510 RemoveDuplicateDualCloneFiles(fileInfos[i]);
511 MEDIA_WARN_LOG("Cloud File %{public}s already exists.",
512 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
513 UpdateDuplicateNumber(fileInfos[i].fileType);
514 continue;
515 }
516 values.emplace_back(value);
517 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
518 prepareCost += startMetaData - startPrepare;
519 parseCost += startDuplicate - startMetaData;
520 duplicateCost += end - startDuplicate;
521 }
522 MEDIA_DEBUG_LOG("END STEP 3 GET INSERT VALUES");
523 MEDIA_INFO_LOG("TimeCost: cloud Prepare cost: %{public}" PRId64 ", SetValueFromMetaData cost: %{public}" PRId64
524 ", DuplicateDualCloneFile cost: %{public}" PRId64, prepareCost, parseCost, duplicateCost);
525 return values;
526 }
527
InsertDateAdded(std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & value)528 static void InsertDateAdded(std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &value)
529 {
530 int64_t dateAdded = metadata->GetFileDateAdded();
531 if (dateAdded != 0) {
532 value.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
533 return;
534 }
535
536 int64_t dateTaken = metadata->GetDateTaken();
537 if (dateTaken == 0) {
538 int64_t dateModified = metadata->GetFileDateModified();
539 if (dateModified == 0) {
540 dateAdded = MediaFileUtils::UTCTimeMilliSeconds();
541 } else {
542 dateAdded = dateModified;
543 }
544 } else {
545 dateAdded = dateTaken;
546 }
547 value.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
548 }
549
InsertUserComment(std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & value,FileInfo & fileInfo)550 static void InsertUserComment(std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &value,
551 FileInfo &fileInfo)
552 {
553 if (fileInfo.userComment.empty()) {
554 fileInfo.userComment = metadata->GetUserComment();
555 }
556
557 bool hasUserComment = value.HasColumn(PhotoColumn::PHOTO_USER_COMMENT);
558 if (hasUserComment) {
559 value.Delete(PhotoColumn::PHOTO_USER_COMMENT);
560 }
561 value.PutString(PhotoColumn::PHOTO_USER_COMMENT, fileInfo.userComment);
562 }
563
InsertDetailTime(NativeRdb::ValuesBucket & value,FileInfo & fileInfo)564 void BaseRestore::InsertDetailTime(NativeRdb::ValuesBucket &value, FileInfo &fileInfo)
565 {
566 if (fileInfo.detailTime.empty()) {
567 fileInfo.detailTime =
568 MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DETAIL_TIME_FORMAT, fileInfo.dateTaken / MSEC_TO_SEC);
569 }
570
571 value.Put(PhotoColumn::PHOTO_DETAIL_TIME, fileInfo.detailTime);
572
573 auto const [dateYear, dateMonth, dateDay] = PhotoFileUtils::ExtractYearMonthDay(fileInfo.detailTime);
574 value.Put(PhotoColumn::PHOTO_DATE_YEAR, dateYear);
575 value.Put(PhotoColumn::PHOTO_DATE_MONTH, dateMonth);
576 value.Put(PhotoColumn::PHOTO_DATE_DAY, dateDay);
577 }
578
CheckAndDelete(NativeRdb::ValuesBucket & value,const std::string & column)579 void BaseRestore::CheckAndDelete(NativeRdb::ValuesBucket &value, const std::string &column)
580 {
581 bool hasColumn = value.HasColumn(column);
582 if (hasColumn) {
583 value.Delete(column);
584 }
585 }
586
InsertFileDuration(const std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & value,FileInfo & fileInfo)587 void BaseRestore::InsertFileDuration(const std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &value,
588 FileInfo &fileInfo)
589 {
590 int32_t duration = metadata->GetFileDuration();
591 if (duration != 0) {
592 CheckAndDelete(value, MediaColumn::MEDIA_DURATION);
593 }
594 value.PutInt(MediaColumn::MEDIA_DURATION, duration);
595 }
596
SetCoverPosition(const FileInfo & fileInfo,NativeRdb::ValuesBucket & value)597 void BaseRestore::SetCoverPosition(const FileInfo &fileInfo, NativeRdb::ValuesBucket &value)
598 {
599 uint64_t coverPosition = 0;
600 if (BackupFileUtils::IsLivePhoto(fileInfo)) {
601 uint32_t version = 0;
602 uint32_t frameIndex = 0;
603 bool hasCinemagraphInfo = false;
604 string absExtraDataPath;
605 if (!PathToRealPath(fileInfo.extraDataPath, absExtraDataPath)) {
606 MEDIA_ERR_LOG("file is not real path: %{private}s, errno: %{public}d",
607 fileInfo.extraDataPath.c_str(), errno);
608 value.PutLong(PhotoColumn::PHOTO_COVER_POSITION, static_cast<int64_t>(coverPosition));
609 return;
610 }
611 UniqueFd extraDataFd(open(absExtraDataPath.c_str(), O_RDONLY));
612 (void)MovingPhotoFileUtils::GetVersionAndFrameNum(extraDataFd.Get(), version, frameIndex, hasCinemagraphInfo);
613 (void)MovingPhotoFileUtils::GetCoverPosition(fileInfo.movingPhotoVideoPath,
614 frameIndex, coverPosition, Scene::AV_META_SCENE_CLONE);
615 }
616 value.PutLong(PhotoColumn::PHOTO_COVER_POSITION, static_cast<int64_t>(coverPosition));
617 }
618
SetMetaDataValue(const FileInfo & fileInfo,std::unique_ptr<Metadata> & data)619 void BaseRestore::SetMetaDataValue(const FileInfo &fileInfo, std::unique_ptr<Metadata> &data)
620 {
621 data->SetFilePath(fileInfo.filePath);
622 data->SetFileMediaType(fileInfo.fileType);
623 data->SetFileDateModified(fileInfo.dateModified);
624 data->SetFileName(fileInfo.displayName);
625 BackupFileUtils::FillMetadata(data);
626 }
627
GetDataLongitude(const FileInfo & fileInfo,std::unique_ptr<Metadata> & data)628 double BaseRestore::GetDataLongitude(const FileInfo &fileInfo, std::unique_ptr<Metadata> &data)
629 {
630 if (sceneCode_ == I_PHONE_CLONE_RESTORE && (!(std::fabs(fileInfo.longitude - DEFAULT_LONGITUDE) < DOUBLE_EPSILON)
631 || !(std::fabs(fileInfo.latitude - DEFAULT_LATITUDE) < DOUBLE_EPSILON))) {
632 return fileInfo.longitude;
633 }
634 return data->GetLongitude();
635 }
636
GetDataLatitude(const FileInfo & fileInfo,std::unique_ptr<Metadata> & data)637 double BaseRestore::GetDataLatitude(const FileInfo &fileInfo, std::unique_ptr<Metadata> &data)
638 {
639 if (sceneCode_ == I_PHONE_CLONE_RESTORE && (!(std::fabs(fileInfo.longitude - DEFAULT_LONGITUDE) < DOUBLE_EPSILON)
640 || !(std::fabs(fileInfo.latitude - DEFAULT_LATITUDE) < DOUBLE_EPSILON))) {
641 return fileInfo.latitude;
642 }
643 return data->GetLatitude();
644 }
645
SetValueFromMetaData(FileInfo & fileInfo,NativeRdb::ValuesBucket & value)646 void BaseRestore::SetValueFromMetaData(FileInfo &fileInfo, NativeRdb::ValuesBucket &value)
647 {
648 std::unique_ptr<Metadata> data = make_unique<Metadata>();
649 SetMetaDataValue(fileInfo, data);
650
651 value.PutString(MediaColumn::MEDIA_FILE_PATH, data->GetFilePath());
652 value.PutString(MediaColumn::MEDIA_MIME_TYPE, data->GetFileMimeType());
653 value.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, data->GetFileExtension());
654 value.PutInt(MediaColumn::MEDIA_TYPE, data->GetFileMediaType());
655 value.PutString(MediaColumn::MEDIA_TITLE, data->GetFileTitle());
656 if (fileInfo.fileSize != 0) {
657 value.PutLong(MediaColumn::MEDIA_SIZE, fileInfo.fileSize);
658 } else {
659 MEDIA_WARN_LOG("DB file size is zero!");
660 value.PutLong(MediaColumn::MEDIA_SIZE, data->GetFileSize());
661 fileInfo.fileSize = data->GetFileSize();
662 }
663 value.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, data->GetFileDateModified());
664 InsertFileDuration(data, value, fileInfo);
665 if (fileInfo.dateTaken <= 0) {
666 InsertDateTaken(data, fileInfo, value);
667 }
668 InsertDetailTime(value, fileInfo);
669 value.PutLong(MediaColumn::MEDIA_TIME_PENDING, 0);
670 value.PutInt(PhotoColumn::PHOTO_HEIGHT, data->GetFileHeight());
671 value.PutInt(PhotoColumn::PHOTO_WIDTH, data->GetFileWidth());
672 value.PutDouble(PhotoColumn::PHOTO_LONGITUDE, GetDataLongitude(fileInfo, data));
673 value.PutDouble(PhotoColumn::PHOTO_LATITUDE, GetDataLatitude(fileInfo, data));
674 value.PutString(PhotoColumn::PHOTO_ALL_EXIF, data->GetAllExif());
675 value.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, data->GetShootingMode());
676 value.PutString(PhotoColumn::PHOTO_SHOOTING_MODE_TAG, data->GetShootingModeTag());
677 value.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, data->GetLastVisitTime());
678 value.PutString(PhotoColumn::PHOTO_FRONT_CAMERA, data->GetFrontCamera());
679 value.PutInt(PhotoColumn::PHOTO_DYNAMIC_RANGE_TYPE, data->GetDynamicRangeType());
680 InsertDateAdded(data, value);
681 SetOrientationAndExifRotate(fileInfo, value, data);
682 InsertUserComment(data, value, fileInfo);
683 int64_t dateAdded = 0;
684 NativeRdb::ValueObject valueObject;
685 if (value.GetObject(MediaColumn::MEDIA_DATE_ADDED, valueObject)) {
686 valueObject.GetLong(dateAdded);
687 }
688 fileInfo.dateAdded = dateAdded;
689 SetCoverPosition(fileInfo, value);
690 }
691
CreateDir(std::string & dir)692 void BaseRestore::CreateDir(std::string &dir)
693 {
694 if (!MediaFileUtils::IsFileExists(dir)) {
695 MediaFileUtils::CreateDirectory(dir);
696 }
697 }
698
RecursiveCreateDir(std::string & relativePath,std::string & suffix)699 void BaseRestore::RecursiveCreateDir(std::string &relativePath, std::string &suffix)
700 {
701 CreateDir(relativePath);
702 size_t pos = suffix.find('/');
703 CHECK_AND_RETURN_LOG(pos != std::string::npos, "Can not find slash");
704 std::string prefix = suffix.substr(0, pos + 1);
705 std::string suffixTmp = suffix.erase(0, prefix.length());
706 prefix = relativePath + prefix;
707 RecursiveCreateDir(prefix, suffixTmp);
708 }
709
InsertAudio(int32_t sceneCode,std::vector<FileInfo> & fileInfos)710 void BaseRestore::InsertAudio(int32_t sceneCode, std::vector<FileInfo> &fileInfos)
711 {
712 if (fileInfos.empty()) {
713 MEDIA_ERR_LOG("fileInfos are empty");
714 return;
715 }
716 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
717 int32_t fileMoveCount = 0;
718 for (size_t i = 0; i < fileInfos.size(); i++) {
719 if (!MediaFileUtils::IsFileExists(fileInfos[i].filePath)) {
720 MEDIA_ERR_LOG("File is not exist: filePath: %{public}s, size: %{public}lld",
721 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str(),
722 (long long)fileInfos[i].fileSize);
723 continue;
724 }
725 string relativePath0 = RESTORE_MUSIC_LOCAL_DIR;
726 string relativePath1 = fileInfos[i].relativePath;
727 if (relativePath1[0] == '/') {
728 relativePath1.erase(0, 1);
729 }
730 string dstPath = RESTORE_MUSIC_LOCAL_DIR + relativePath1;
731 RecursiveCreateDir(relativePath0, relativePath1);
732 if (MediaFileUtils::IsFileExists(dstPath)) {
733 MEDIA_INFO_LOG("dstPath %{public}s already exists.",
734 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
735 UpdateDuplicateNumber(fileInfos[i].fileType);
736 continue;
737 }
738 int32_t moveErrCode = BackupFileUtils::MoveFile(fileInfos[i].filePath, dstPath, sceneCode);
739 if (moveErrCode != E_SUCCESS) {
740 MEDIA_ERR_LOG("MoveFile failed, filePath: %{public}s, errCode: %{public}d, errno: %{public}d",
741 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str(), moveErrCode, errno);
742 UpdateFailedFiles(fileInfos[i].fileType, fileInfos[i], RestoreError::MOVE_FAILED);
743 continue;
744 }
745 BackupFileUtils::ModifyFile(dstPath, fileInfos[i].dateModified / MSEC_TO_SEC);
746 fileMoveCount++;
747 }
748 migrateAudioFileNumber_ += fileMoveCount;
749 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
750 MEDIA_INFO_LOG("move %{public}ld file cost %{public}ld.", (long)fileMoveCount, (long)(end - startMove));
751 }
752
MoveExtraData(const FileInfo & fileInfo,int32_t sceneCode)753 static bool MoveExtraData(const FileInfo &fileInfo, int32_t sceneCode)
754 {
755 string localExtraDataDir = BackupFileUtils::GetReplacedPathByPrefixType(
756 PrefixType::CLOUD, PrefixType::LOCAL, MovingPhotoFileUtils::GetMovingPhotoExtraDataDir(fileInfo.cloudPath));
757 if (localExtraDataDir.empty()) {
758 MEDIA_WARN_LOG("Failed to get local extra data dir");
759 return false;
760 }
761 if (!MediaFileUtils::IsFileExists(localExtraDataDir) && !MediaFileUtils::CreateDirectory(localExtraDataDir)) {
762 MEDIA_WARN_LOG("Failed to create local extra data dir, errno:%{public}d", errno);
763 return false;
764 }
765
766 string localExtraDataPath = BackupFileUtils::GetReplacedPathByPrefixType(
767 PrefixType::CLOUD, PrefixType::LOCAL, MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(fileInfo.cloudPath));
768 if (localExtraDataPath.empty()) {
769 MEDIA_WARN_LOG("Failed to get local extra data path");
770 return false;
771 }
772 int32_t errCode = BackupFileUtils::MoveFile(fileInfo.extraDataPath, localExtraDataPath, sceneCode);
773 if (errCode != E_OK) {
774 MEDIA_WARN_LOG("MoveFile failed, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
775 BackupFileUtils::GarbleFilePath(fileInfo.extraDataPath, sceneCode).c_str(),
776 BackupFileUtils::GarbleFilePath(localExtraDataPath, sceneCode).c_str(), errCode, errno);
777 return false;
778 }
779 return true;
780 }
781
SaveIosExtraData(const FileInfo & fileInfo,std::string movingPhotoVideoPath,int32_t sceneCode)782 static bool SaveIosExtraData(const FileInfo &fileInfo, std::string movingPhotoVideoPath, int32_t sceneCode)
783 {
784 string localExtraDataDir = BackupFileUtils::GetReplacedPathByPrefixType(
785 PrefixType::CLOUD, PrefixType::LOCAL, MovingPhotoFileUtils::GetMovingPhotoExtraDataDir(fileInfo.cloudPath));
786 if (localExtraDataDir.empty()) {
787 MEDIA_WARN_LOG("Failed to get local extra data dir");
788 return false;
789 }
790 if (!MediaFileUtils::IsFileExists(localExtraDataDir) && !MediaFileUtils::CreateDirectory(localExtraDataDir)) {
791 MEDIA_WARN_LOG("Failed to create local extra data dir, errno:%{public}d", errno);
792 return false;
793 }
794
795 string localExtraDataPath = BackupFileUtils::GetReplacedPathByPrefixType(
796 PrefixType::CLOUD, PrefixType::LOCAL, MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(fileInfo.cloudPath));
797 if (localExtraDataPath.empty()) {
798 MEDIA_WARN_LOG("Failed to get local extra data path");
799 return false;
800 }
801
802 size_t videoSize = 0;
803 MediaFileUtils::GetFileSize(movingPhotoVideoPath, videoSize);
804
805 std::string versionAndFrame = "v7_f0";
806 versionAndFrame.resize(SINGLE_LEN_EXTRADATA, ' ');
807 std::string startEndPosition = "0:0";
808 startEndPosition.resize(SINGLE_LEN_EXTRADATA, ' ');
809 std::string videoLengthStr = "LIVE_" + std::to_string(videoSize + SINGLE_LEN_EXTRADATA);
810 videoLengthStr.resize(SINGLE_LEN_EXTRADATA, ' ');
811 std::string extraData = versionAndFrame + startEndPosition + videoLengthStr;
812 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(localExtraDataPath) &&
813 MediaFileUtils::WriteStrToFile(localExtraDataPath, extraData), false,
814 "Write to %{public}s failed", BackupFileUtils::GarbleFilePath(localExtraDataPath, sceneCode).c_str());
815 return true;
816 }
817
MoveAndModifyFile(const FileInfo & fileInfo,int32_t sceneCode)818 static bool MoveAndModifyFile(const FileInfo &fileInfo, int32_t sceneCode)
819 {
820 string tmpPath = fileInfo.cloudPath;
821 string localPath = tmpPath.replace(0, RESTORE_CLOUD_DIR.length(), RESTORE_LOCAL_DIR);
822 int32_t errCode = BackupFileUtils::MoveFile(fileInfo.filePath, localPath, sceneCode);
823 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, false,
824 "MoveFile failed, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
825 BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode).c_str(),
826 BackupFileUtils::GarbleFilePath(localPath, sceneCode).c_str(), errCode, errno);
827 BackupFileUtils::ModifyFile(localPath, fileInfo.dateModified / MSEC_TO_SEC);
828
829 if (sceneCode == I_PHONE_CLONE_RESTORE && fileInfo.subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
830 string movSrcPath = fileInfo.filePath.substr(0, fileInfo.filePath.find_last_of(".")) + ".MOV";
831 string movTargetPath = localPath.substr(0, localPath.find_last_of(".")) + ".mp4";
832
833 errCode = BackupFileUtils::MoveFile(movSrcPath, movTargetPath, sceneCode);
834 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, false,
835 "Move moving photo video failed, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
836 BackupFileUtils::GarbleFilePath(movSrcPath, sceneCode).c_str(),
837 BackupFileUtils::GarbleFilePath(movTargetPath, sceneCode).c_str(), errCode, errno);
838 BackupFileUtils::ModifyFile(movTargetPath, fileInfo.dateModified / MSEC_TO_SEC);
839
840 CHECK_AND_RETURN_RET_LOG(SaveIosExtraData(fileInfo, movTargetPath, sceneCode), false,
841 "Save the extraData for ios moving photo failed, src:%{public}s, dest:%{public}s",
842 BackupFileUtils::GarbleFilePath(movSrcPath, sceneCode).c_str(),
843 BackupFileUtils::GarbleFilePath(movTargetPath, sceneCode).c_str());
844 return true;
845 }
846
847 if (BackupFileUtils::IsLivePhoto(fileInfo)) {
848 string tmpVideoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(fileInfo.cloudPath);
849 string localVideoPath = tmpVideoPath.replace(0, RESTORE_CLOUD_DIR.length(), RESTORE_LOCAL_DIR);
850 errCode = BackupFileUtils::MoveFile(fileInfo.movingPhotoVideoPath, localVideoPath, sceneCode);
851 if (errCode != E_OK) {
852 MEDIA_ERR_LOG(
853 "MoveFile failed for mov video, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
854 BackupFileUtils::GarbleFilePath(fileInfo.movingPhotoVideoPath, sceneCode).c_str(),
855 BackupFileUtils::GarbleFilePath(localVideoPath, sceneCode).c_str(), errCode, errno);
856 (void)MediaFileUtils::DeleteFile(localPath);
857 return false;
858 }
859 BackupFileUtils::ModifyFile(localVideoPath, fileInfo.dateModified / MSEC_TO_SEC);
860 return MoveExtraData(fileInfo, sceneCode);
861 }
862 return true;
863 }
864
GetThumbnailLocalPath(const string & path)865 static std::string GetThumbnailLocalPath(const string &path)
866 {
867 size_t cloudDirLength = RESTORE_FILES_CLOUD_DIR.length();
868 bool cond = (path.length() <= cloudDirLength ||
869 path.substr(0, cloudDirLength).compare(RESTORE_FILES_CLOUD_DIR) != 0);
870 CHECK_AND_RETURN_RET(!cond, "");
871
872 std::string suffixStr = path.substr(cloudDirLength);
873 return RESTORE_FILES_LOCAL_DIR + ".thumbs/" + suffixStr;
874 }
875
BatchCreateDentryFile(std::vector<FileInfo> & fileInfos,std::vector<std::string> & failCloudIds,std::string fileType)876 int32_t BaseRestore::BatchCreateDentryFile(std::vector<FileInfo> &fileInfos, std::vector<std::string> &failCloudIds,
877 std::string fileType)
878 {
879 MEDIA_INFO_LOG("START STEP 4 CREATE DENTRY");
880 bool cond = ((fileType != DENTRY_INFO_THM) && (fileType != DENTRY_INFO_LCD) && (fileType != DENTRY_INFO_ORIGIN));
881 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Invalid fileType: %{public}s", fileType.c_str());
882 std::vector<FileManagement::CloudSync::DentryFileInfo> dentryInfos;
883 for (size_t i = 0; i < fileInfos.size(); i++) {
884 CHECK_AND_CONTINUE(fileInfos[i].needMove);
885 FileManagement::CloudSync::DentryFileInfo dentryInfo;
886 dentryInfo.cloudId = fileInfos[i].uniqueId;
887 dentryInfo.modifiedTime = fileInfos[i].dateModified;
888 if (fileType == DENTRY_INFO_ORIGIN) {
889 dentryInfo.fileType = fileType;
890 dentryInfo.size = fileInfos[i].fileSize;
891 dentryInfo.path = fileInfos[i].cloudPath;
892 dentryInfo.fileName = fileInfos[i].displayName;
893 } else {
894 dentryInfo.size = THUMB_DENTRY_SIZE;
895 if (fileType == DENTRY_INFO_LCD) {
896 dentryInfo.fileType = (!HasExThumbnail(fileInfos[i])) ? fileType : LCD_EX_SUFFIX;
897 dentryInfo.fileName = "LCD.jpg";
898 } else {
899 dentryInfo.fileType = (!HasExThumbnail(fileInfos[i])) ? fileType : THUMB_EX_SUFFIX;
900 dentryInfo.fileName = "THM.jpg";
901 }
902 }
903 dentryInfos.push_back(dentryInfo);
904 }
905 if (dentryInfos.empty()) {
906 MEDIA_INFO_LOG("dentryInfos empty.");
907 return E_OK;
908 }
909 int32_t ret = FileManagement::CloudSync::CloudSyncManager::GetInstance().BatchDentryFileInsert(
910 dentryInfos, failCloudIds);
911 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "BatchDentryFileInsert failed, ret: %{public}d.", ret);
912 CHECK_AND_PRINT_LOG(failCloudIds.empty(), "failCloudIds size: %{public}zu, first one: %{public}s",
913 failCloudIds.size(), failCloudIds[0].c_str());
914 MEDIA_DEBUG_LOG("END STEP 4 CREATE DENTRY");
915 return ret;
916 }
917
RestoreLcdAndThumbFromCloud(const FileInfo & fileInfo,int32_t type,int32_t sceneCode)918 bool BaseRestore::RestoreLcdAndThumbFromCloud(const FileInfo &fileInfo, int32_t type, int32_t sceneCode)
919 {
920 std::string srcPath = GetThumbFile(fileInfo, type, sceneCode);
921 CHECK_AND_RETURN_RET(srcPath != "", false);
922 std::string saveNoRotatePath = !HasExThumbnail(fileInfo) ? "" : THM_SAVE_WITHOUT_ROTATE_PATH;
923 std::string dstDirPath = GetThumbnailLocalPath(fileInfo.cloudPath) + saveNoRotatePath;
924 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dstDirPath), false, "Prepare thumbnail dir path failed");
925
926 std::string tmpTargetFileName = type == MIGRATE_CLOUD_LCD_TYPE ? "/LCD" : "/THM";
927 std::string dstFilePath = dstDirPath + tmpTargetFileName + ".jpg";
928 bool cond = (MediaFileUtils::IsFileExists(dstFilePath) && !MediaFileUtils::DeleteFile(dstFilePath));
929 CHECK_AND_RETURN_RET_LOG(!cond, false, "Delete thumbnail new dir failed, errno: %{public}d", errno);
930
931 int32_t errCode = MediaFileUtils::ModifyAsset(srcPath, dstFilePath);
932 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, false,
933 "MoveFile failed, src: %{public}s, dest: %{public}s, err: %{public}d, errno: %{public}d",
934 BackupFileUtils::GarbleFilePath(srcPath, sceneCode).c_str(),
935 BackupFileUtils::GarbleFilePath(dstFilePath, sceneCode).c_str(), errCode, errno);
936 do {
937 CHECK_AND_BREAK(HasExThumbnail(fileInfo));
938 std::string rotateDirPath = dstDirPath.replace(dstDirPath.find(THM_SAVE_WITHOUT_ROTATE_PATH),
939 THM_SAVE_WITHOUT_ROTATE_PATH.length(), "");
940 if (type == MIGRATE_CLOUD_THM_TYPE &&
941 MediaFileUtils::IsFileExists(rotateDirPath + tmpTargetFileName + ".jpg")) {
942 rotateThmMigrateFileNumber_++;
943 break;
944 }
945 if (fileInfo.fileType == MediaType::MEDIA_TYPE_IMAGE) {
946 CHECK_AND_RETURN_RET_LOG(BackupFileUtils::HandleRotateImage(dstFilePath, rotateDirPath,
947 fileInfo.exifRotate, type == MIGRATE_CLOUD_LCD_TYPE), false, "Rotate image fail!");
948 } else {
949 std::string rotateDirFile = rotateDirPath + tmpTargetFileName + ".jpg";
950 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(dstFilePath, rotateDirFile),
951 false, "Copy file failed!");
952 }
953 type == MIGRATE_CLOUD_LCD_TYPE ? rotateLcdMigrateFileNumber_++ : rotateThmMigrateFileNumber_++;
954 } while (0);
955 if (fileInfo.localMediaId == -1) {
956 type == MIGRATE_CLOUD_LCD_TYPE ? cloudLcdCount_++ : cloudThumbnailCount_++;
957 } else {
958 type == MIGRATE_CLOUD_LCD_TYPE ? localLcdCount_++ : localThumbnailCount_++;
959 }
960 return true;
961 }
962
GetThumbFile(const FileInfo & fileInfo,int32_t type,int32_t sceneCode)963 std::string BaseRestore::GetThumbFile(const FileInfo &fileInfo, int32_t type, int32_t sceneCode)
964 {
965 std::string thumbPath = type == MIGRATE_CLOUD_LCD_TYPE ? fileInfo.localBigThumbPath : fileInfo.localThumbPath;
966 if (thumbPath != "") {
967 std::string prefixStr = sceneCode == DUAL_FRAME_CLONE_RESTORE_ID ? backupRestoreDir_ : upgradeRestoreDir_;
968 std::string srcPath = prefixStr + thumbPath;
969 CHECK_AND_RETURN_RET(!MediaFileUtils::IsFileExists(srcPath), srcPath);
970 }
971
972 CHECK_AND_RETURN_RET(!fileInfo.albumId.empty(), "");
973 CHECK_AND_RETURN_RET(!fileInfo.uniqueId.empty(), "");
974 std::string newPrefixStr = sceneCode == DUAL_FRAME_CLONE_RESTORE_ID ?
975 (backupRestoreDir_ + "/storage/emulated/0") : upgradeRestoreDir_;
976 std::string tmpStr = type == MIGRATE_CLOUD_LCD_TYPE ? "lcd/" : "thumb/";
977 std::string newSrcPath = newPrefixStr + "/.photoShare/thumb/" + tmpStr + fileInfo.albumId +
978 "/" + fileInfo.uniqueId + ".jpg";
979 CHECK_AND_RETURN_RET(!MediaFileUtils::IsFileExists(newSrcPath), newSrcPath);
980 MEDIA_DEBUG_LOG("GetThumbFile fail: %{public}s, %{public}s, %{public}s, %{public}d",
981 BackupFileUtils::GarbleFilePath(fileInfo.localBigThumbPath, sceneCode).c_str(),
982 BackupFileUtils::GarbleFilePath(fileInfo.localThumbPath, sceneCode).c_str(),
983 BackupFileUtils::GarbleFilePath(newSrcPath, sceneCode).c_str(),
984 fileInfo.localMediaId);
985 return "";
986 }
987
RestoreLcdAndThumbFromKvdb(const FileInfo & fileInfo,int32_t type,int32_t sceneCode)988 bool BaseRestore::RestoreLcdAndThumbFromKvdb(const FileInfo &fileInfo, int32_t type, int32_t sceneCode)
989 {
990 return false;
991 }
992
NeedMoveLocalThumbnail(FileInfo & fileInfo)993 bool NeedMoveLocalThumbnail(FileInfo &fileInfo)
994 {
995 return fileInfo.fileType == MediaType::MEDIA_TYPE_IMAGE ||
996 !ExifRotateUtils::IsExifRotateWithFlip(fileInfo.exifRotate);
997 }
998
MoveMigrateFile(std::vector<FileInfo> & fileInfos,int32_t & fileMoveCount,int32_t & videoFileMoveCount,int32_t sceneCode)999 void BaseRestore::MoveMigrateFile(std::vector<FileInfo> &fileInfos, int32_t &fileMoveCount, int32_t &videoFileMoveCount,
1000 int32_t sceneCode)
1001 {
1002 vector<std::string> moveFailedData;
1003 int64_t startMoveAndModifyFile = MediaFileUtils::UTCTimeMilliSeconds();
1004 for (size_t i = 0; i < fileInfos.size(); i++) {
1005 CHECK_AND_CONTINUE(fileInfos[i].needMove);
1006 CHECK_AND_CONTINUE(IsFileValid(fileInfos[i], sceneCode) == E_OK);
1007 if (!MoveAndModifyFile(fileInfos[i], sceneCode)) {
1008 fileInfos[i].needUpdate = false;
1009 fileInfos[i].needVisible = false;
1010 UpdateFailedFiles(fileInfos[i].fileType, fileInfos[i], RestoreError::MOVE_FAILED);
1011 ErrorInfo errorInfo(RestoreError::MOVE_FAILED, 1, "",
1012 BackupLogUtils::FileInfoToString(sceneCode, fileInfos[i]));
1013 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1014 moveFailedData.push_back(fileInfos[i].cloudPath);
1015 continue;
1016 }
1017
1018 if (NeedMoveLocalThumbnail(fileInfos[i])) {
1019 CHECK_AND_EXECUTE(RestoreLcdAndThumbFromCloud(fileInfos[i], MIGRATE_CLOUD_LCD_TYPE, sceneCode),
1020 RestoreLcdAndThumbFromKvdb(fileInfos[i], MIGRATE_CLOUD_LCD_TYPE, sceneCode));
1021 CHECK_AND_EXECUTE(RestoreLcdAndThumbFromCloud(fileInfos[i], MIGRATE_CLOUD_THM_TYPE, sceneCode),
1022 RestoreLcdAndThumbFromKvdb(fileInfos[i], MIGRATE_CLOUD_THM_TYPE, sceneCode));
1023 }
1024 fileMoveCount++;
1025 videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
1026 }
1027 int64_t startDeleteMoveFailedData = MediaFileUtils::UTCTimeMilliSeconds();
1028 DeleteMoveFailedData(moveFailedData);
1029 int64_t startSetVisiblePhoto = MediaFileUtils::UTCTimeMilliSeconds();
1030 SetVisiblePhoto(fileInfos);
1031 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1032 migrateFileNumber_ += fileMoveCount;
1033 migrateVideoFileNumber_ += videoFileMoveCount;
1034 MEDIA_INFO_LOG("TimeCost: MoveAndModifyFile cost: %{public}" PRId64
1035 ", DeleteMoveFailedData cost: %{public}" PRId64
1036 ", SetVisiblePhoto cost: %{public}" PRId64, startDeleteMoveFailedData - startMoveAndModifyFile,
1037 startSetVisiblePhoto - startDeleteMoveFailedData, end - startSetVisiblePhoto);
1038 }
1039
MoveMigrateCloudFile(std::vector<FileInfo> & fileInfos,int32_t & fileMoveCount,int32_t & videoFileMoveCount,int32_t sceneCode)1040 void BaseRestore::MoveMigrateCloudFile(std::vector<FileInfo> &fileInfos, int32_t &fileMoveCount,
1041 int32_t &videoFileMoveCount, int32_t sceneCode)
1042 {
1043 MEDIA_INFO_LOG("START STEP 6 MOVE");
1044 vector<std::string> moveFailedData;
1045 std::vector<FileInfo> LCDNotFound;
1046 std::vector<FileInfo> THMNotFound;
1047 for (size_t i = 0; i < fileInfos.size(); i++) {
1048 CHECK_AND_CONTINUE(fileInfos[i].needMove);
1049 bool cond = ((!RestoreLcdAndThumbFromCloud(fileInfos[i], MIGRATE_CLOUD_LCD_TYPE, sceneCode)) &&
1050 (!RestoreLcdAndThumbFromKvdb(fileInfos[i], MIGRATE_CLOUD_LCD_TYPE, sceneCode)));
1051 CHECK_AND_EXECUTE(!cond, LCDNotFound.push_back(fileInfos[i]));
1052
1053 cond = ((!RestoreLcdAndThumbFromCloud(fileInfos[i], MIGRATE_CLOUD_THM_TYPE, sceneCode)) &&
1054 (!RestoreLcdAndThumbFromKvdb(fileInfos[i], MIGRATE_CLOUD_THM_TYPE, sceneCode)));
1055 CHECK_AND_EXECUTE(!cond, THMNotFound.push_back(fileInfos[i]));
1056 videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
1057 }
1058 std::vector<std::string> dentryFailedLCD;
1059 std::vector<std::string> dentryFailedThumb;
1060 CHECK_AND_EXECUTE(BatchCreateDentryFile(LCDNotFound, dentryFailedLCD, DENTRY_INFO_LCD) != E_OK,
1061 HandleFailData(fileInfos, dentryFailedLCD, DENTRY_INFO_LCD));
1062 CHECK_AND_EXECUTE(BatchCreateDentryFile(THMNotFound, dentryFailedThumb, DENTRY_INFO_THM) != E_OK,
1063 HandleFailData(fileInfos, dentryFailedThumb, DENTRY_INFO_THM));
1064 fileMoveCount = SetVisiblePhoto(fileInfos);
1065 successCloudMetaNumber_ += fileMoveCount;
1066 migrateFileNumber_ += fileMoveCount;
1067 migrateVideoFileNumber_ += videoFileMoveCount;
1068 MEDIA_DEBUG_LOG("END STEP 6 MOVE");
1069 }
1070
UpdateLcdVisibleColumn(const FileInfo & fileInfo)1071 void BaseRestore::UpdateLcdVisibleColumn(const FileInfo &fileInfo)
1072 {
1073 NativeRdb::ValuesBucket updatePostBucket;
1074 updatePostBucket.Put(PhotoColumn::PHOTO_LCD_VISIT_TIME, RESTORE_LCD_VISIT_TIME_SUCCESS);
1075 std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
1076 make_unique<NativeRdb::AbsRdbPredicates>(PhotoColumn::PHOTOS_TABLE);
1077 predicates->EqualTo(MediaColumn::MEDIA_NAME, fileInfo.displayName);
1078 int changeRows = 0;
1079 int32_t ret = BackupDatabaseUtils::Update(mediaLibraryRdb_, changeRows, updatePostBucket, predicates);
1080 bool cond = (changeRows < 0 || ret < 0);
1081 CHECK_AND_PRINT_LOG(!cond, "Failed to update LCD visible column, ret: %{public}d", ret);
1082 }
1083
HandleFailData(std::vector<FileInfo> & fileInfos,std::vector<std::string> & failCloudIds,std::string fileType)1084 void BaseRestore::HandleFailData(std::vector<FileInfo> &fileInfos, std::vector<std::string> &failCloudIds,
1085 std::string fileType)
1086 {
1087 MEDIA_INFO_LOG("START STEP 5 HANDLE FAIL, fileInfos size: %{public}zu", fileInfos.size());
1088 CHECK_AND_RETURN_INFO_LOG(!failCloudIds.empty(), "HandleFailData failCloudIds empty.");
1089 vector<std::string> dentryFailedData;
1090 bool cond = ((fileType != DENTRY_INFO_ORIGIN) && (fileType != DENTRY_INFO_LCD) && (fileType != DENTRY_INFO_THM));
1091 CHECK_AND_RETURN_LOG(!cond, "Invalid fileType: %{public}s", fileType.c_str());
1092
1093 auto iteration = fileInfos.begin();
1094 while (iteration != fileInfos.end()) {
1095 if (find(failCloudIds.begin(), failCloudIds.end(), iteration->uniqueId) != failCloudIds.end()) {
1096 dentryFailedData.push_back(iteration->cloudPath);
1097 iteration->needVisible = false;
1098 UpdateFailedFiles(iteration->fileType, *iteration, RestoreError::INSERT_FAILED);
1099 if (fileType == DENTRY_INFO_ORIGIN) {
1100 iteration = fileInfos.erase(iteration);
1101 } else if (fileType == DENTRY_INFO_LCD) {
1102 MediaFileUtils::DeleteFile(iteration->cloudPath);
1103 ++iteration;
1104 } else {
1105 MediaFileUtils::DeleteFile(iteration->cloudPath);
1106
1107 std::string LCDFilePath = GetThumbnailLocalPath(iteration->cloudPath) + "/LCD.jpg";
1108 MediaFileUtils::DeleteFile(LCDFilePath);
1109 ++iteration;
1110 }
1111 } else {
1112 ++iteration;
1113 }
1114 }
1115 DeleteMoveFailedData(dentryFailedData);
1116 MEDIA_DEBUG_LOG("END STEP 5 HANDLE FAIL");
1117 }
1118
InsertPhoto(int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)1119 int BaseRestore::InsertPhoto(int32_t sceneCode, std::vector<FileInfo> &fileInfos, int32_t sourceType)
1120 {
1121 MEDIA_INFO_LOG("Start insert %{public}zu photos", fileInfos.size());
1122 CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, E_OK, "mediaLibraryRdb_ is null");
1123 CHECK_AND_RETURN_RET_LOG(!fileInfos.empty(), E_OK, "fileInfos are empty");
1124
1125 int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
1126 vector<NativeRdb::ValuesBucket> values = GetInsertValues(sceneCode, fileInfos, sourceType);
1127 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
1128 int64_t rowNum = 0;
1129 int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, rowNum);
1130 if (errCode != E_OK) {
1131 if (needReportFailed_) {
1132 UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
1133 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(fileInfos.size()), errCode);
1134 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1135 }
1136 return errCode;
1137 }
1138
1139 int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
1140 InsertPhotoRelated(fileInfos, sourceType);
1141 BatchQueryPhoto(fileInfos);
1142 AddToPhotoInfoMap(fileInfos);
1143
1144 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
1145 migrateDatabaseNumber_ += rowNum;
1146 int32_t fileMoveCount = 0;
1147 int32_t videoFileMoveCount = 0;
1148 MoveMigrateFile(fileInfos, fileMoveCount, videoFileMoveCount, sceneCode);
1149 int64_t startRestore = MediaFileUtils::UTCTimeMilliSeconds();
1150 this->tabOldPhotosRestore_.Restore(this->mediaLibraryRdb_, fileInfos);
1151 int64_t startUpdate = MediaFileUtils::UTCTimeMilliSeconds();
1152 UpdatePhotosByFileInfoMap(mediaLibraryRdb_, fileInfos);
1153 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1154 MEDIA_INFO_LOG("generate values cost %{public}" PRId64 ", insert %{public}" PRId64 " assets cost %{public}" PRId64
1155 ", insert photo related cost %{public}" PRId64 ", move %{public}d files (%{public}d + %{public}d) cost "
1156 "%{public}" PRId64 ", old photos restore cost %{public}" PRId64 ", update cost %{public}" PRId64,
1157 startInsert - startGenerate, rowNum, startInsertRelated - startInsert,
1158 startMove - startInsertRelated, fileMoveCount, fileMoveCount - videoFileMoveCount, videoFileMoveCount,
1159 startRestore - startMove, startUpdate - startRestore, end - startUpdate);
1160 return E_OK;
1161 }
1162
SetVisiblePhoto(std::vector<FileInfo> & fileInfos)1163 int32_t BaseRestore::SetVisiblePhoto(std::vector<FileInfo> &fileInfos)
1164 {
1165 MEDIA_INFO_LOG("START STEP 7 SET VISIBLE");
1166 std::vector<std::string> visibleIds;
1167 for (auto info : fileInfos) {
1168 if (info.needVisible && info.needMove) {
1169 visibleIds.push_back(info.cloudPath);
1170 }
1171 }
1172 if (visibleIds.empty()) {
1173 return 0;
1174 }
1175
1176 NativeRdb::ValuesBucket updatePostBucket;
1177 updatePostBucket.Put(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
1178 std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
1179 make_unique<NativeRdb::AbsRdbPredicates>(PhotoColumn::PHOTOS_TABLE);
1180 predicates->In(MediaColumn::MEDIA_FILE_PATH, visibleIds);
1181 int32_t changeRows = 0;
1182 int32_t ret = BackupDatabaseUtils::Update(mediaLibraryRdb_, changeRows, updatePostBucket, predicates);
1183 if (changeRows < 0 || ret < 0) {
1184 MEDIA_ERR_LOG("Failed to update visible column, changeRows: %{public}d, ret: %{public}d", changeRows, ret);
1185 changeRows = 0;
1186 }
1187 MEDIA_DEBUG_LOG("END STEP 7 SET VISIBLE: visibleIds: %{public}zu, changeRows: %{public}d",
1188 visibleIds.size(), changeRows);
1189 return changeRows;
1190 }
1191
InsertCloudPhoto(int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)1192 int BaseRestore::InsertCloudPhoto(int32_t sceneCode, std::vector<FileInfo> &fileInfos, int32_t sourceType)
1193 {
1194 MEDIA_INFO_LOG("Start insert cloud %{public}zu photos", fileInfos.size());
1195 CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, E_OK, "mediaLibraryRdb_ is null in cloud clone");
1196 CHECK_AND_RETURN_RET_LOG(!fileInfos.empty(), E_OK, "fileInfos are empty in cloud clone");
1197
1198 int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
1199 vector<NativeRdb::ValuesBucket> values = GetCloudInsertValues(sceneCode, fileInfos, sourceType);
1200 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
1201 int64_t rowNum = 0;
1202 int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, rowNum);
1203 MEDIA_INFO_LOG("the insert result in insertCloudPhoto is %{public}d, the rowNum is %{public}" PRId64,
1204 errCode, rowNum);
1205 totalCloudMetaNumber_ += rowNum;
1206 if (errCode != E_OK) {
1207 if (needReportFailed_) {
1208 UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
1209 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(fileInfos.size()), errCode);
1210 UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1211 }
1212 return errCode;
1213 }
1214
1215 int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
1216 InsertPhotoRelated(fileInfos, sourceType);
1217 BatchQueryPhoto(fileInfos);
1218 AddToPhotoInfoMap(fileInfos);
1219
1220 // create dentry file for cloud origin, save failed cloud id
1221 std::vector<std::string> dentryFailedOrigin;
1222 CHECK_AND_EXECUTE(BatchCreateDentryFile(fileInfos, dentryFailedOrigin, DENTRY_INFO_ORIGIN) != E_OK,
1223 HandleFailData(fileInfos, dentryFailedOrigin, DENTRY_INFO_ORIGIN));
1224
1225 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
1226 migrateDatabaseNumber_ += rowNum;
1227 int32_t fileMoveCount = 0;
1228 int32_t videoFileMoveCount = 0;
1229 MoveMigrateCloudFile(fileInfos, fileMoveCount, videoFileMoveCount, sceneCode);
1230 int64_t startRestore = MediaFileUtils::UTCTimeMilliSeconds();
1231 this->tabOldPhotosRestore_.Restore(this->mediaLibraryRdb_, fileInfos);
1232 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1233 MEDIA_INFO_LOG("generate values cost %{public}" PRId64 ", insert %{public}" PRId64 " assets cost %{public}" PRId64
1234 ", insert photo related cost %{public}" PRId64 ", move %{public}d files (%{public}d + %{public}d) cost "
1235 "%{public}" PRId64 ", old photos restore cost %{public}" PRId64,
1236 startInsert - startGenerate, rowNum, startInsertRelated - startInsert,
1237 startMove - startInsertRelated, fileMoveCount, fileMoveCount - videoFileMoveCount, videoFileMoveCount,
1238 startRestore - startMove, end - startRestore);
1239 MEDIA_DEBUG_LOG("END STEP 2 INSERT CLOUD");
1240 return E_OK;
1241 }
1242
DeleteMoveFailedData(std::vector<std::string> & moveFailedData)1243 void BaseRestore::DeleteMoveFailedData(std::vector<std::string> &moveFailedData)
1244 {
1245 CHECK_AND_RETURN_INFO_LOG(!moveFailedData.empty(), "No move failed");
1246 MEDIA_INFO_LOG("%{public}d file move failed", static_cast<int>(moveFailedData.size()));
1247 NativeRdb::AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1248 predicates.In(MediaColumn::MEDIA_FILE_PATH, moveFailedData);
1249 int32_t changedRows = 0;
1250 int deleteRes = BackupDatabaseUtils::Delete(predicates, changedRows, mediaLibraryRdb_);
1251 MEDIA_INFO_LOG("changeRows:%{public}d, deleteRes:%{public}d", changedRows, deleteRes);
1252 }
1253
BatchInsertWithRetry(const std::string & tableName,std::vector<NativeRdb::ValuesBucket> & values,int64_t & rowNum)1254 int32_t BaseRestore::BatchInsertWithRetry(const std::string &tableName, std::vector<NativeRdb::ValuesBucket> &values,
1255 int64_t &rowNum)
1256 {
1257 if (values.empty()) {
1258 return 0;
1259 }
1260
1261 int32_t errCode = E_ERR;
1262 TransactionOperations trans{ __func__ };
1263 trans.SetBackupRdbStore(mediaLibraryRdb_);
1264 std::function<int(void)> func = [&]()->int {
1265 errCode = trans.BatchInsert(rowNum, tableName, values);
1266 CHECK_AND_PRINT_LOG(errCode == E_OK,
1267 "InsertSql failed, errCode: %{public}d, rowNum: %{public}ld.", errCode, (long)rowNum);
1268 return errCode;
1269 };
1270 errCode = trans.RetryTrans(func, true);
1271 CHECK_AND_PRINT_LOG(errCode == E_OK, "BatchInsertWithRetry: tans finish fail!, ret:%{public}d", errCode);
1272 return errCode;
1273 }
1274
MoveDirectory(const std::string & srcDir,const std::string & dstDir,bool deleteOriginalFile) const1275 int32_t BaseRestore::MoveDirectory(const std::string &srcDir, const std::string &dstDir, bool deleteOriginalFile) const
1276 {
1277 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dstDir), E_FAIL,
1278 "Create dstDir %{public}s failed", BackupFileUtils::GarbleFilePath(dstDir, DEFAULT_RESTORE_ID).c_str());
1279 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(srcDir), E_OK,
1280 "%{public}s doesn't exist, skip.", srcDir.c_str());
1281 for (const auto &dirEntry : std::filesystem::directory_iterator{ srcDir }) {
1282 std::string srcFilePath = dirEntry.path();
1283 std::string tmpFilePath = srcFilePath;
1284 std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
1285 int32_t opRet = E_FAIL;
1286 if (deleteOriginalFile) {
1287 opRet = this->MoveFile(srcFilePath, dstFilePath);
1288 } else {
1289 opRet = this->CopyFile(srcFilePath, dstFilePath);
1290 }
1291 CHECK_AND_RETURN_RET_LOG(opRet == E_OK, E_FAIL,
1292 "Move file from %{public}s to %{public}s failed, deleteOriginalFile=%{public}d",
1293 BackupFileUtils::GarbleFilePath(srcFilePath, sceneCode_).c_str(),
1294 BackupFileUtils::GarbleFilePath(dstFilePath, DEFAULT_RESTORE_ID).c_str(), deleteOriginalFile);
1295 }
1296 return E_OK;
1297 }
1298
IsSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & tableName,FileInfo & fileInfo)1299 bool BaseRestore::IsSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore, const std::string &tableName,
1300 FileInfo &fileInfo)
1301 {
1302 string srcPath = fileInfo.filePath;
1303 string dstPath = BackupFileUtils::GetFullPathByPrefixType(PrefixType::LOCAL, fileInfo.relativePath);
1304 struct stat srcStatInfo {};
1305 struct stat dstStatInfo {};
1306
1307 if (access(dstPath.c_str(), F_OK)) {
1308 return false;
1309 }
1310 if (stat(srcPath.c_str(), &srcStatInfo) != 0) {
1311 MEDIA_ERR_LOG("Failed to get file %{private}s StatInfo, err=%{public}d", srcPath.c_str(), errno);
1312 return false;
1313 }
1314 if (stat(dstPath.c_str(), &dstStatInfo) != 0) {
1315 MEDIA_ERR_LOG("Failed to get file %{private}s StatInfo, err=%{public}d", dstPath.c_str(), errno);
1316 return false;
1317 }
1318 if ((srcStatInfo.st_size != dstStatInfo.st_size || srcStatInfo.st_mtime != dstStatInfo.st_mtime) &&
1319 !HasSameAudioFile(rdbStore, tableName, fileInfo)) { /* file size & last modify time */
1320 MEDIA_INFO_LOG("Size (%{public}lld -> %{public}lld) or mtime (%{public}lld -> %{public}lld) differs",
1321 (long long)srcStatInfo.st_size, (long long)dstStatInfo.st_size, (long long)srcStatInfo.st_mtime,
1322 (long long)dstStatInfo.st_mtime);
1323 return false;
1324 }
1325 fileInfo.isNew = false;
1326 return true;
1327 }
1328
HasSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & tableName,FileInfo & fileInfo)1329 bool BaseRestore::HasSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore, const std::string &tableName,
1330 FileInfo &fileInfo)
1331 {
1332 string querySql = "SELECT " + MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + " FROM " +
1333 tableName + " WHERE " + MediaColumn::MEDIA_NAME + " = '" + fileInfo.displayName + "' AND " +
1334 MediaColumn::MEDIA_SIZE + " = " + to_string(fileInfo.fileSize) + " AND " +
1335 MediaColumn::MEDIA_DATE_MODIFIED + " = " + to_string(fileInfo.dateModified);
1336 querySql += " LIMIT 1";
1337 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(rdbStore, querySql);
1338 bool cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
1339 CHECK_AND_RETURN_RET(resultSet != nullptr, false);
1340 if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1341 resultSet->Close();
1342 return false;
1343 }
1344 int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
1345 string cloudPath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
1346 cond = (fileId <= 0 || cloudPath.empty());
1347 CHECK_AND_RETURN_RET(!cond, false);
1348 fileInfo.fileIdNew = fileId;
1349 fileInfo.cloudPath = cloudPath;
1350 resultSet->Close();
1351 return true;
1352 }
1353
InsertPhotoMap(std::vector<FileInfo> & fileInfos,int64_t & mapRowNum)1354 void BaseRestore::InsertPhotoMap(std::vector<FileInfo> &fileInfos, int64_t &mapRowNum)
1355 {
1356 BatchInsertMap(fileInfos, mapRowNum);
1357 migrateDatabaseMapNumber_ += mapRowNum;
1358 }
1359
BatchQueryPhoto(vector<FileInfo> & fileInfos,bool isFull,const NeedQueryMap & needQueryMap)1360 void BaseRestore::BatchQueryPhoto(vector<FileInfo> &fileInfos, bool isFull, const NeedQueryMap &needQueryMap)
1361 {
1362 string querySql = "SELECT " + MediaColumn::MEDIA_ID + " , " + MediaColumn::MEDIA_FILE_PATH + " FROM " +
1363 PhotoColumn::PHOTOS_TABLE + " WHERE ";
1364 bool firstSql = false;
1365 std::vector<std::string> cloudPathArgs;
1366 for (auto &fileInfo : fileInfos) {
1367 if (!isFull && !NeedQuery(fileInfo, needQueryMap)) {
1368 continue;
1369 }
1370 if (firstSql) {
1371 querySql += " OR ";
1372 } else {
1373 firstSql = true;
1374 }
1375 querySql += MediaColumn::MEDIA_FILE_PATH + " = ? ";
1376 cloudPathArgs.push_back(fileInfo.cloudPath);
1377 }
1378 auto result = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql, cloudPathArgs);
1379 if (result == nullptr) {
1380 MEDIA_ERR_LOG("Query resultSql is null.");
1381 return;
1382 }
1383 while (result->GoToNextRow() == NativeRdb::E_OK) {
1384 int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, result);
1385 std::string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, result);
1386 auto pathMatch = [path {path}](const auto &fileInfo) {
1387 return fileInfo.cloudPath == path;
1388 };
1389 auto it = std::find_if(fileInfos.begin(), fileInfos.end(), pathMatch);
1390 bool cond = (it != fileInfos.end() && fileId > 0);
1391 CHECK_AND_EXECUTE(!cond, it->fileIdNew = fileId);
1392 }
1393 }
1394
BatchQueryPhoto(std::vector<FileInfo> & fileInfos)1395 void BaseRestore::BatchQueryPhoto(std::vector<FileInfo> &fileInfos)
1396 {
1397 std::stringstream querySql;
1398 querySql << "SELECT file_id, data FROM Photos WHERE data IN (";
1399 std::vector<NativeRdb::ValueObject> params;
1400 int32_t count = 0;
1401 for (const auto &fileInfo : fileInfos) {
1402 CHECK_AND_CONTINUE(fileInfo.fileIdNew <= 0);
1403 querySql << (count++ > 0 ? "," : "");
1404 querySql << "?";
1405 params.push_back(fileInfo.cloudPath);
1406 }
1407 querySql << ")";
1408 CHECK_AND_RETURN(!params.empty());
1409 auto resultSet = BackupDatabaseUtils::QuerySql(mediaLibraryRdb_, querySql.str(), params);
1410 CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr");
1411
1412 std::vector<NativeRdb::ValuesBucket> values;
1413 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1414 int32_t fileId = GetInt32Val("file_id", resultSet);
1415 std::string data = GetStringVal("data", resultSet);
1416 auto it = std::find_if(fileInfos.begin(), fileInfos.end(),
1417 [data](const FileInfo &info) {
1418 return info.cloudPath == data;
1419 });
1420 CHECK_AND_CONTINUE(it != fileInfos.end());
1421 it->fileIdNew = fileId;
1422 }
1423 resultSet->Close();
1424 }
1425
BatchInsertMap(const vector<FileInfo> & fileInfos,int64_t & totalRowNum)1426 void BaseRestore::BatchInsertMap(const vector<FileInfo> &fileInfos, int64_t &totalRowNum)
1427 {
1428 vector<NativeRdb::ValuesBucket> values;
1429 for (const auto &fileInfo : fileInfos) {
1430 if (!fileInfo.packageName.empty()) {
1431 // add for trigger insert_photo_insert_source_album
1432 continue;
1433 }
1434
1435 bool cond = (fileInfo.cloudPath.empty() || fileInfo.mediaAlbumId <= 0 || fileInfo.fileIdNew <= 0);
1436 CHECK_AND_CONTINUE_ERR_LOG(!cond, "AlbumMap error file name = %{public}s.", fileInfo.displayName.c_str());
1437 NativeRdb::ValuesBucket value;
1438 value.PutInt(PhotoMap::ASSET_ID, fileInfo.fileIdNew);
1439 value.PutInt(PhotoMap::ALBUM_ID, fileInfo.mediaAlbumId);
1440 values.emplace_back(value);
1441 }
1442 int64_t rowNum = 0;
1443 int32_t errCode = BatchInsertWithRetry(PhotoMap::TABLE, values, rowNum);
1444 CHECK_AND_PRINT_LOG(errCode == E_OK, "Batch insert map failed, errCode: %{public}d", errCode);
1445 totalRowNum += rowNum;
1446 }
1447
StartRestoreEx(const std::string & backupRetoreDir,const std::string & upgradePath,std::string & restoreExInfo)1448 void BaseRestore::StartRestoreEx(const std::string &backupRetoreDir, const std::string &upgradePath,
1449 std::string &restoreExInfo)
1450 {
1451 UpgradeRestoreTaskReport()
1452 .SetSceneCode(this->sceneCode_)
1453 .SetTaskId(this->taskId_)
1454 .ReportProgress("start", std::to_string(MediaFileUtils::UTCTimeSeconds()));
1455 restoreMode_ = GetRestoreModeFromRestoreInfo(restoreInfo_);
1456 MEDIA_INFO_LOG("set restore mode to :%{public}d", restoreMode_);
1457 StartRestore(backupRetoreDir, upgradePath);
1458 DatabaseReport()
1459 .SetSceneCode(this->sceneCode_)
1460 .SetTaskId(this->taskId_)
1461 .ReportMedia(this->mediaLibraryRdb_, DatabaseReport::PERIOD_AFTER);
1462 DatabaseReport()
1463 .SetSceneCode(this->sceneCode_)
1464 .SetTaskId(this->taskId_)
1465 .ReportAudio(audioTotalNumber_);
1466 restoreExInfo = GetRestoreExInfo();
1467 UpgradeRestoreTaskReport()
1468 .SetSceneCode(this->sceneCode_)
1469 .SetTaskId(this->taskId_)
1470 .ReportTask(restoreExInfo)
1471 .ReportTotal(std::to_string(errorCode_), GetRestoreTotalInfo())
1472 .ReportTimeCost(migrateFileNumber_ + audioTotalNumber_, migratePhotoDuplicateNumber_, totalFailCount_)
1473 .ReportProgress("end", std::to_string(MediaFileUtils::UTCTimeSeconds()))
1474 .ReportUpgradeEnh(std::to_string(errorCode_), GetUpgradeEnhance());
1475 }
1476
GetRestoreExInfo()1477 std::string BaseRestore::GetRestoreExInfo()
1478 {
1479 nlohmann::json restoreExInfoJson;
1480 restoreExInfoJson[STAT_KEY_RESULT_INFO] = { GetErrorInfoJson(), GetCountInfoJson(STAT_TYPES) };
1481 return restoreExInfoJson.dump();
1482 }
1483
GetErrorInfoJson()1484 nlohmann::json BaseRestore::GetErrorInfoJson()
1485 {
1486 int32_t errorCode = errorCode_ == RestoreError::SUCCESS ? STAT_DEFAULT_ERROR_CODE_SUCCESS :
1487 STAT_DEFAULT_ERROR_CODE_FAILED;
1488 nlohmann::json errorInfoJson = {
1489 { STAT_KEY_TYPE, STAT_VALUE_ERROR_INFO },
1490 { STAT_KEY_ERROR_CODE, std::to_string(errorCode) },
1491 { STAT_KEY_ERROR_INFO, errorInfo_ }
1492 };
1493 return errorInfoJson;
1494 }
1495
GetCountInfoJson(const std::vector<std::string> & countInfoTypes)1496 nlohmann::json BaseRestore::GetCountInfoJson(const std::vector<std::string> &countInfoTypes)
1497 {
1498 nlohmann::json countInfoJson;
1499 countInfoJson[STAT_KEY_TYPE] = STAT_VALUE_COUNT_INFO;
1500 size_t limit = MAX_FAILED_FILES_LIMIT;
1501 for (const auto &type : countInfoTypes) {
1502 SubCountInfo subCountInfo = GetSubCountInfo(type);
1503 totalFailCount_ += subCountInfo.failedFiles.size();
1504 MEDIA_INFO_LOG("SubCountInfo %{public}s success: %{public}lld, duplicate: %{public}lld, failed: %{public}zu",
1505 type.c_str(), (long long)subCountInfo.successCount, (long long)subCountInfo.duplicateCount,
1506 subCountInfo.failedFiles.size());
1507 countInfoJson[STAT_KEY_INFOS].push_back(GetSubCountInfoJson(type, subCountInfo, limit));
1508 }
1509 return countInfoJson;
1510 }
1511
GetSubCountInfo(const std::string & type)1512 SubCountInfo BaseRestore::GetSubCountInfo(const std::string &type)
1513 {
1514 std::unordered_map<std::string, FailedFileInfo> failedFiles = GetFailedFiles(type);
1515 if (type == STAT_TYPE_PHOTO) {
1516 return SubCountInfo(migrateFileNumber_ - migrateVideoFileNumber_, migratePhotoDuplicateNumber_, failedFiles);
1517 }
1518 if (type == STAT_TYPE_VIDEO) {
1519 return SubCountInfo(migrateVideoFileNumber_, migrateVideoDuplicateNumber_, failedFiles);
1520 }
1521 return SubCountInfo(migrateAudioFileNumber_, migrateAudioDuplicateNumber_, failedFiles);
1522 }
1523
GetFailedFiles(const std::string & type)1524 std::unordered_map<std::string, FailedFileInfo> BaseRestore::GetFailedFiles(const std::string &type)
1525 {
1526 std::lock_guard<mutex> lock(failedFilesMutex_);
1527 std::unordered_map<std::string, FailedFileInfo> failedFiles;
1528 auto iter = failedFilesMap_.find(type);
1529 if (iter != failedFilesMap_.end()) {
1530 return iter->second;
1531 }
1532 return failedFiles;
1533 }
1534
GetSubCountInfoJson(const std::string & type,const SubCountInfo & subCountInfo,size_t & limit)1535 nlohmann::json BaseRestore::GetSubCountInfoJson(const std::string &type, const SubCountInfo &subCountInfo,
1536 size_t &limit)
1537 {
1538 nlohmann::json subCountInfoJson;
1539 subCountInfoJson[STAT_KEY_BACKUP_INFO] = type;
1540 subCountInfoJson[STAT_KEY_SUCCESS_COUNT] = subCountInfo.successCount;
1541 subCountInfoJson[STAT_KEY_DUPLICATE_COUNT] = subCountInfo.duplicateCount;
1542 subCountInfoJson[STAT_KEY_FAILED_COUNT] = subCountInfo.failedFiles.size();
1543 // update currentLimit = min(limit, failedFiles.size())
1544 size_t currentLimit = limit <= subCountInfo.failedFiles.size() ? limit : subCountInfo.failedFiles.size();
1545 std::string detailsPath;
1546 std::vector<std::string> failedFilesList;
1547 if (sceneCode_ == UPGRADE_RESTORE_ID) {
1548 detailsPath = BackupFileUtils::GetDetailsPath(DEFAULT_RESTORE_ID, type, subCountInfo.failedFiles, currentLimit);
1549 subCountInfoJson[STAT_KEY_DETAILS] = detailsPath;
1550 } else {
1551 failedFilesList = BackupFileUtils::GetFailedFilesList(DEFAULT_RESTORE_ID, subCountInfo.failedFiles,
1552 currentLimit);
1553 subCountInfoJson[STAT_KEY_DETAILS] = failedFilesList;
1554 }
1555 MEDIA_INFO_LOG("Get %{public}s details size: %{public}zu", type.c_str(), currentLimit);
1556 limit -= currentLimit; // update total limit
1557 return subCountInfoJson;
1558 }
1559
GetBackupInfo()1560 std::string BaseRestore::GetBackupInfo()
1561 {
1562 return "";
1563 }
1564
SetErrorCode(int32_t errorCode)1565 void BaseRestore::SetErrorCode(int32_t errorCode)
1566 {
1567 errorCode_ = errorCode;
1568 errorInfo_ = BackupLogUtils::RestoreErrorToString(errorCode);
1569 }
1570
UpdateFailedFileByFileType(int32_t fileType,const FileInfo & fileInfo,int32_t errorCode)1571 void BaseRestore::UpdateFailedFileByFileType(int32_t fileType, const FileInfo &fileInfo, int32_t errorCode)
1572 {
1573 std::lock_guard<mutex> lock(failedFilesMutex_);
1574 FailedFileInfo failedFileInfo(sceneCode_, fileInfo, errorCode);
1575 if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE)) {
1576 failedFilesMap_[STAT_TYPE_PHOTO].emplace(fileInfo.oldPath, failedFileInfo);
1577 return;
1578 }
1579 if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
1580 failedFilesMap_[STAT_TYPE_VIDEO].emplace(fileInfo.oldPath, failedFileInfo);
1581 return;
1582 }
1583 if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_AUDIO)) {
1584 failedFilesMap_[STAT_TYPE_AUDIO].emplace(fileInfo.oldPath, failedFileInfo);
1585 return;
1586 }
1587 MEDIA_ERR_LOG("Unsupported file type: %{public}d", fileType);
1588 }
1589
UpdateFailedFiles(int32_t fileType,const FileInfo & fileInfo,int32_t errorCode)1590 void BaseRestore::UpdateFailedFiles(int32_t fileType, const FileInfo &fileInfo, int32_t errorCode)
1591 {
1592 SetErrorCode(errorCode);
1593 UpdateFailedFileByFileType(fileType, fileInfo, errorCode);
1594 }
1595
UpdateFailedFiles(const std::vector<FileInfo> & fileInfos,int32_t errorCode)1596 void BaseRestore::UpdateFailedFiles(const std::vector<FileInfo> &fileInfos, int32_t errorCode)
1597 {
1598 SetErrorCode(errorCode);
1599 for (const auto &fileInfo : fileInfos) {
1600 UpdateFailedFileByFileType(fileInfo.fileType, fileInfo, errorCode);
1601 }
1602 }
1603
UpdateDuplicateNumber(int32_t fileType)1604 void BaseRestore::UpdateDuplicateNumber(int32_t fileType)
1605 {
1606 if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE)) {
1607 migratePhotoDuplicateNumber_++;
1608 return;
1609 }
1610 if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
1611 migrateVideoDuplicateNumber_++;
1612 return;
1613 }
1614 if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_AUDIO)) {
1615 migrateAudioDuplicateNumber_++;
1616 return;
1617 }
1618 MEDIA_ERR_LOG("Unsupported file type: %{public}d", fileType);
1619 }
1620
SetParameterForClone()1621 void BaseRestore::SetParameterForClone()
1622 {
1623 auto currentTime = to_string(MediaFileUtils::UTCTimeSeconds());
1624 MEDIA_INFO_LOG("SetParameterForClone currentTime:%{public}s", currentTime.c_str());
1625 bool retFlag = system::SetParameter(CLONE_FLAG, currentTime);
1626 CHECK_AND_PRINT_LOG(retFlag, "Failed to set parameter cloneFlag, retFlag:%{public}d", retFlag);
1627 }
1628
StopParameterForClone()1629 void BaseRestore::StopParameterForClone()
1630 {
1631 MEDIA_INFO_LOG("StopParameterForClone set 0");
1632 bool retFlag = system::SetParameter(CLONE_FLAG, "0");
1633 CHECK_AND_PRINT_LOG(retFlag, "Failed to set stop parameter cloneFlag, retFlag:%{public}d", retFlag);
1634 }
1635
SetParameterForBackup()1636 void BaseRestore::SetParameterForBackup()
1637 {
1638 auto currentTime = to_string(MediaFileUtils::UTCTimeSeconds());
1639 MEDIA_INFO_LOG("SetParameterForBackup currentTime:%{public}s", currentTime.c_str());
1640 bool retFlag = system::SetParameter(BACKUP_FLAG, currentTime);
1641 CHECK_AND_PRINT_LOG(retFlag, "Failed to set parameter backupFlag, retFlag:%{public}d", retFlag);
1642 }
1643
StopParameterForBackup()1644 void BaseRestore::StopParameterForBackup()
1645 {
1646 MEDIA_INFO_LOG("StopParameterForBackup set 0");
1647 bool retFlag = system::SetParameter(BACKUP_FLAG, "0");
1648 CHECK_AND_PRINT_LOG(retFlag, "Failed to set stop parameter backupFlag, retFlag:%{public}d", retFlag);
1649 }
1650
SetParameterForRestore()1651 void BaseRestore::SetParameterForRestore()
1652 {
1653 auto currentTime = to_string(MediaFileUtils::UTCTimeSeconds());
1654 MEDIA_INFO_LOG("SetParameterForRestore currentTime:%{public}s", currentTime.c_str());
1655 bool retFlag = system::SetParameter(RESTORE_FLAG, currentTime);
1656 CHECK_AND_PRINT_LOG(retFlag, "Failed to set parameter restoreFlag, retFlag:%{public}d", retFlag);
1657 }
1658
StopParameterForRestore()1659 void BaseRestore::StopParameterForRestore()
1660 {
1661 MEDIA_INFO_LOG("StopParameterForRestore set 0");
1662 bool retFlag = system::SetParameter(RESTORE_FLAG, "0");
1663 CHECK_AND_PRINT_LOG(retFlag, "Failed to set stop parameter restoreFlag, retFlag:%{public}d", retFlag);
1664 }
1665
InsertPhotoRelated(std::vector<FileInfo> & fileInfos,int32_t sourceType)1666 void BaseRestore::InsertPhotoRelated(std::vector<FileInfo> &fileInfos, int32_t sourceType)
1667 {
1668 if (sourceType != SourceType::GALLERY) {
1669 return;
1670 }
1671 NeedQueryMap needQueryMap;
1672 CHECK_AND_RETURN_INFO_LOG(NeedBatchQueryPhoto(fileInfos, needQueryMap), "There is no need to batch query photo");
1673 int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1674 BatchQueryPhoto(fileInfos, false, needQueryMap);
1675 int64_t startInsertMap = MediaFileUtils::UTCTimeMilliSeconds();
1676 int64_t mapRowNum = 0;
1677 InsertPhotoMap(fileInfos, mapRowNum);
1678 int64_t startInsertPortrait = MediaFileUtils::UTCTimeMilliSeconds();
1679 int64_t faceRowNum = 0;
1680 int64_t portraitMapRowNum = 0;
1681 int64_t portraitPhotoNum = 0;
1682 InsertFaceAnalysisData(fileInfos, needQueryMap, faceRowNum, portraitMapRowNum, portraitPhotoNum);
1683 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1684 MEDIA_INFO_LOG("TimeCost: query cost %{public}ld, insert %{public}ld maps cost %{public}ld, "
1685 "insert face analysis data of %{public}ld photos (%{public}ld faces + %{public}ld maps) cost %{public}ld",
1686 (long)(startInsertMap - startQuery), (long)mapRowNum, (long)(startInsertPortrait - startInsertMap),
1687 (long)portraitPhotoNum, (long)faceRowNum, (long)portraitMapRowNum, (long)(end - startInsertPortrait));
1688 }
1689
NeedBatchQueryPhoto(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)1690 bool BaseRestore::NeedBatchQueryPhoto(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
1691 {
1692 return NeedBatchQueryPhotoForPhotoMap(fileInfos, needQueryMap) ||
1693 NeedBatchQueryPhotoForPortrait(fileInfos, needQueryMap);
1694 }
1695
NeedBatchQueryPhotoForPhotoMap(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)1696 bool BaseRestore::NeedBatchQueryPhotoForPhotoMap(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
1697 {
1698 std::unordered_set<std::string> needQuerySet;
1699 for (const auto &fileInfo : fileInfos) {
1700 if (!fileInfo.packageName.empty()) {
1701 continue;
1702 }
1703 if (fileInfo.cloudPath.empty() || fileInfo.mediaAlbumId <= 0) {
1704 MEDIA_ERR_LOG("Album error file name = %{public}s.", fileInfo.displayName.c_str());
1705 continue;
1706 }
1707 needQuerySet.insert(fileInfo.cloudPath);
1708 }
1709 if (needQuerySet.empty()) {
1710 return false;
1711 }
1712 needQueryMap[PhotoRelatedType::PHOTO_MAP] = needQuerySet;
1713 return true;
1714 }
1715
NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)1716 bool BaseRestore::NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
1717 {
1718 return false;
1719 }
1720
NeedQuery(const FileInfo & fileInfo,const NeedQueryMap & needQueryMap)1721 bool BaseRestore::NeedQuery(const FileInfo &fileInfo, const NeedQueryMap &needQueryMap)
1722 {
1723 for (auto iter = needQueryMap.begin(); iter != needQueryMap.end(); ++iter) {
1724 if (NeedQueryByPhotoRelatedType(fileInfo, iter->first, iter->second)) {
1725 return true;
1726 }
1727 }
1728 return false;
1729 }
1730
NeedQueryByPhotoRelatedType(const FileInfo & fileInfo,PhotoRelatedType photoRelatedType,const std::unordered_set<std::string> & needQuerySet)1731 bool BaseRestore::NeedQueryByPhotoRelatedType(const FileInfo &fileInfo, PhotoRelatedType photoRelatedType,
1732 const std::unordered_set<std::string> &needQuerySet)
1733 {
1734 std::string searchPath;
1735 switch (photoRelatedType) {
1736 case PhotoRelatedType::PHOTO_MAP: {
1737 searchPath = fileInfo.cloudPath;
1738 break;
1739 }
1740 case PhotoRelatedType::PORTRAIT: {
1741 searchPath = fileInfo.hashCode;
1742 break;
1743 }
1744 default:
1745 MEDIA_ERR_LOG("Unsupported photo related type: %{public}d", static_cast<int32_t>(photoRelatedType));
1746 }
1747 return !searchPath.empty() && needQuerySet.count(searchPath) > 0;
1748 }
1749
InsertFaceAnalysisData(const std::vector<FileInfo> & fileInfos,const NeedQueryMap & needQueryMap,int64_t & faceRowNum,int64_t & mapRowNum,int64_t & photoNum)1750 void BaseRestore::InsertFaceAnalysisData(const std::vector<FileInfo> &fileInfos, const NeedQueryMap &needQueryMap,
1751 int64_t &faceRowNum, int64_t &mapRowNum, int64_t &photoNum)
1752 {
1753 return;
1754 }
1755
ReportPortraitStat(int32_t sceneCode)1756 void BaseRestore::ReportPortraitStat(int32_t sceneCode)
1757 {
1758 MEDIA_INFO_LOG("PortraitStat: album %{public}zu, photo %{public}lld, face %{public}lld, cost %{public}lld",
1759 portraitAlbumIdMap_.size(), (long long)migratePortraitPhotoNumber_, (long long)migratePortraitFaceNumber_,
1760 (long long)migratePortraitTotalTimeCost_);
1761 BackupDfxUtils::PostPortraitStat(static_cast<uint32_t>(portraitAlbumIdMap_.size()), migratePortraitPhotoNumber_,
1762 migratePortraitFaceNumber_, migratePortraitTotalTimeCost_);
1763 }
1764
GetUniqueId(int32_t fileType)1765 int32_t BaseRestore::GetUniqueId(int32_t fileType)
1766 {
1767 int32_t uniqueId = -1;
1768 switch (fileType) {
1769 case MediaType::MEDIA_TYPE_IMAGE: {
1770 std::lock_guard<ffrt::mutex> lock(imageMutex_);
1771 uniqueId = static_cast<int32_t>(imageNumber_);
1772 imageNumber_++;
1773 break;
1774 }
1775 case MediaType::MEDIA_TYPE_VIDEO: {
1776 std::lock_guard<ffrt::mutex> lock(videoMutex_);
1777 uniqueId = static_cast<int32_t>(videoNumber_);
1778 videoNumber_++;
1779 break;
1780 }
1781 case MediaType::MEDIA_TYPE_AUDIO: {
1782 std::lock_guard<ffrt::mutex> lock(audioMutex_);
1783 uniqueId = static_cast<int32_t>(audioNumber_);
1784 audioNumber_++;
1785 break;
1786 }
1787 default:
1788 MEDIA_ERR_LOG("Unsupported file type: %{public}d", fileType);
1789 }
1790 return uniqueId;
1791 }
1792
GetProgressInfo()1793 std::string BaseRestore::GetProgressInfo()
1794 {
1795 nlohmann::json progressInfoJson;
1796 for (const auto &type : STAT_PROGRESS_TYPES) {
1797 SubProcessInfo subProcessInfo = GetSubProcessInfo(type);
1798 progressInfoJson[STAT_KEY_PROGRESS_INFO].push_back(GetSubProcessInfoJson(type, subProcessInfo));
1799 }
1800 std::string progressInfo = progressInfoJson.dump();
1801 UpgradeRestoreTaskReport()
1802 .SetSceneCode(this->sceneCode_)
1803 .SetTaskId(this->taskId_)
1804 .ReportProgress("onProcess", progressInfo, ongoingTotalNumber_.load())
1805 .ReportTimeout(ongoingTotalNumber_.load());
1806 return progressInfo;
1807 }
1808
GetSubProcessInfo(const std::string & type)1809 SubProcessInfo BaseRestore::GetSubProcessInfo(const std::string &type)
1810 {
1811 uint64_t success = 0;
1812 uint64_t duplicate = 0;
1813 uint64_t failed = 0;
1814 uint64_t total = 0;
1815 if (type == STAT_TYPE_PHOTO_VIDEO) {
1816 success = migrateFileNumber_;
1817 duplicate = migratePhotoDuplicateNumber_ + migrateVideoDuplicateNumber_;
1818 failed = static_cast<uint64_t>(GetFailedFiles(STAT_TYPE_PHOTO).size() + GetFailedFiles(STAT_TYPE_VIDEO).size());
1819 total = totalNumber_;
1820 MEDIA_ERR_LOG("GetSubProcessInfo: %{public}s, migrateFileNumber: %{public}" PRIu64
1821 ",migratePhotoDuplicateNumber: %{public}" PRIu64 ",migrateVideoDuplicateNumber :%{public}" PRIu64
1822 "totalNumber :%{public}" PRIu64 ",failed :%{public}" PRIu64, type.c_str(), migrateFileNumber_.load(),
1823 migratePhotoDuplicateNumber_.load(), migrateVideoDuplicateNumber_.load(), totalNumber_.load(), failed);
1824 } else if (type == STAT_TYPE_AUDIO) {
1825 success = migrateAudioFileNumber_;
1826 duplicate = migrateAudioDuplicateNumber_;
1827 failed = static_cast<uint64_t>(GetFailedFiles(type).size());
1828 total = audioTotalNumber_;
1829 } else if (type == STAT_TYPE_UPDATE) {
1830 UpdateProcessedNumber(updateProcessStatus_, updateProcessedNumber_, updateTotalNumber_);
1831 success = updateProcessedNumber_;
1832 total = updateTotalNumber_;
1833 } else if (type == STAT_TYPE_THUMBNAIL) {
1834 success = thumbnailProcessedNumber_;
1835 total = thumbnailTotalNumber_;
1836 } else if (type == STAT_TYPE_OTHER) {
1837 UpdateProcessedNumber(otherProcessStatus_, otherProcessedNumber_, otherTotalNumber_);
1838 success = otherProcessedNumber_;
1839 total = otherTotalNumber_;
1840 } else {
1841 ongoingTotalNumber_++;
1842 success = ongoingTotalNumber_;
1843 total = ongoingTotalNumber_; // make sure progressInfo changes as process goes on
1844 }
1845 uint64_t processed = success + duplicate + failed;
1846 return SubProcessInfo(processed, total);
1847 }
1848
UpdateProcessedNumber(const std::atomic<int32_t> & processStatus,std::atomic<uint64_t> & processedNumber,const std::atomic<uint64_t> & totalNumber)1849 void BaseRestore::UpdateProcessedNumber(const std::atomic<int32_t> &processStatus,
1850 std::atomic<uint64_t> &processedNumber, const std::atomic<uint64_t> &totalNumber)
1851 {
1852 if (processStatus == ProcessStatus::STOP) {
1853 processedNumber = totalNumber.load();
1854 return;
1855 }
1856 processedNumber += processedNumber < totalNumber ? 1 : 0;
1857 }
1858
GetSubProcessInfoJson(const std::string & type,const SubProcessInfo & subProcessInfo)1859 nlohmann::json BaseRestore::GetSubProcessInfoJson(const std::string &type, const SubProcessInfo &subProcessInfo)
1860 {
1861 nlohmann::json subProcessInfoJson;
1862 subProcessInfoJson[STAT_KEY_NAME] = type;
1863 subProcessInfoJson[STAT_KEY_PROCESSED] = subProcessInfo.processed;
1864 subProcessInfoJson[STAT_KEY_TOTAL] = subProcessInfo.total;
1865 subProcessInfoJson[STAT_KEY_IS_PERCENTAGE] = false;
1866 return subProcessInfoJson;
1867 }
1868
UpdateDatabase()1869 void BaseRestore::UpdateDatabase()
1870 {
1871 int64_t startUpdateDatabase = MediaFileUtils::UTCTimeMilliSeconds();
1872 updateProcessStatus_ = ProcessStatus::START;
1873 GetUpdateTotalCount();
1874 MEDIA_INFO_LOG("Start update all albums");
1875 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1876 MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, {}, { NotifyAlbumType::NO_NOTIFY, true,
1877 AlbumOperationType::DEFAULT, false });
1878 MEDIA_INFO_LOG("Start update unique number");
1879 BackupDatabaseUtils::UpdateUniqueNumber(mediaLibraryRdb_, imageNumber_, IMAGE_ASSET_TYPE);
1880 BackupDatabaseUtils::UpdateUniqueNumber(mediaLibraryRdb_, videoNumber_, VIDEO_ASSET_TYPE);
1881 BackupDatabaseUtils::UpdateUniqueNumber(mediaLibraryRdb_, audioNumber_, AUDIO_ASSET_TYPE);
1882 MEDIA_INFO_LOG("Start notify");
1883 NotifyAlbum();
1884 updateProcessStatus_ = ProcessStatus::STOP;
1885 int64_t endUpdateDatabase = MediaFileUtils::UTCTimeMilliSeconds();
1886 MEDIA_INFO_LOG("TimeCost: UpdateDatabase cost: %{public}" PRId64, endUpdateDatabase - startUpdateDatabase);
1887 }
1888
UpdatePhotoAlbumDateModified(const vector<string> & albumIds,const string & tableName)1889 void BaseRestore::UpdatePhotoAlbumDateModified(const vector<string> &albumIds, const string &tableName)
1890 {
1891 CHECK_AND_RETURN(!albumIds.empty());
1892 CHECK_AND_RETURN(tableName == PhotoAlbumColumns::TABLE);
1893 MEDIA_INFO_LOG("Start update photoAlbums date modified tableName:%{public}s, albumIds count:%{public}zu",
1894 tableName.c_str(), albumIds.size());
1895 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1896 MediaLibraryRdbUtils::UpdateUserAlbumInternal(rdbStore, albumIds, false, true);
1897 MediaLibraryRdbUtils::UpdateSourceAlbumInternal(rdbStore, albumIds, false, true);
1898 }
1899
NotifyAlbum()1900 void BaseRestore::NotifyAlbum()
1901 {
1902 auto watch = MediaLibraryNotify::GetInstance();
1903 CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
1904
1905 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::NOTIFY_FOR_RECHECK);
1906 int ret = IPC::UserDefineIPCClient().Call(businessCode);
1907 CHECK_AND_PRINT_LOG(ret == E_OK, "Notify check refresh failed");
1908
1909 watch->Notify(PhotoColumn::DEFAULT_PHOTO_URI, NotifyType::NOTIFY_ADD);
1910 watch->Notify(PhotoAlbumColumns::ALBUM_URI_PREFIX, NotifyType::NOTIFY_ADD);
1911 }
1912
GetUpdateTotalCount()1913 void BaseRestore::GetUpdateTotalCount()
1914 {
1915 GetUpdateAllAlbumsCount();
1916 GetUpdateUniqueNumberCount();
1917 }
1918
GetUpdateAllAlbumsCount()1919 void BaseRestore::GetUpdateAllAlbumsCount()
1920 {
1921 const std::vector<std::string> ALBUM_TABLE_LIST = { "PhotoAlbum", "AnalysisAlbum" };
1922 int32_t albumTotalCount = 0;
1923 for (const auto &tableName : ALBUM_TABLE_LIST) {
1924 std::string querySql = "SELECT count(1) as count FROM " + tableName;
1925 albumTotalCount += BackupDatabaseUtils::QueryInt(mediaLibraryRdb_, querySql, CUSTOM_COUNT);
1926 }
1927 updateTotalNumber_ += static_cast<uint64_t>(albumTotalCount);
1928 MEDIA_INFO_LOG("onProcess Update updateTotalNumber_: %{public}lld", (long long)updateTotalNumber_);
1929 }
1930
GetUpdateUniqueNumberCount()1931 void BaseRestore::GetUpdateUniqueNumberCount()
1932 {
1933 updateTotalNumber_ += UNIQUE_NUMBER_NUM;
1934 MEDIA_INFO_LOG("onProcess Update updateTotalNumber_: %{public}lld", (long long)updateTotalNumber_);
1935 }
1936
GetNotFoundNumber()1937 uint64_t BaseRestore::GetNotFoundNumber()
1938 {
1939 return notFoundNumber_;
1940 }
1941
RestoreThumbnail()1942 void BaseRestore::RestoreThumbnail()
1943 {
1944 // restore thumbnail for date fronted 2000 photos
1945 int32_t localNoAstcCount = BackupDatabaseUtils::QueryLocalNoAstcCount(mediaLibraryRdb_);
1946 CHECK_AND_RETURN_LOG(localNoAstcCount > 0,
1947 "No need to RestoreThumbnail, localNoAstcCount:%{public}d", localNoAstcCount);
1948 int32_t restoreAstcCount = localNoAstcCount < MAX_RESTORE_ASTC_NUM ? localNoAstcCount : MAX_RESTORE_ASTC_NUM;
1949 uint64_t thumbnailTotalNumber = static_cast<uint64_t>(restoreAstcCount);
1950 thumbnailTotalNumber_ = thumbnailTotalNumber;
1951 int32_t readyAstcCount = BackupDatabaseUtils::QueryReadyAstcCount(mediaLibraryRdb_);
1952 CHECK_AND_RETURN_LOG(readyAstcCount >= 0, "ReadyAstcCount:%{public}d is invalid", readyAstcCount);
1953 uint64_t waitAstcNum = sceneCode_ != UPGRADE_RESTORE_ID ? thumbnailTotalNumber :
1954 std::min(thumbnailTotalNumber, MAX_UPGRADE_WAIT_ASTC_NUM);
1955
1956 MEDIA_INFO_LOG("Start RestoreThumbnail, readyAstcCount:%{public}d, restoreAstcCount:%{public}d, "
1957 "waitAstcNum:%{public}" PRIu64, readyAstcCount, restoreAstcCount, waitAstcNum);
1958 BackupFileUtils::GenerateThumbnailsAfterRestore(restoreAstcCount);
1959 uint64_t thumbnailProcessedNumber = 0;
1960 int32_t timeoutTimes = 0;
1961 int64_t startRestoreThumbnailTime = MediaFileUtils::UTCTimeMilliSeconds();
1962 bool isNeedWaitRestoreThumbnail = true;
1963 while (thumbnailProcessedNumber < waitAstcNum && isNeedWaitRestoreThumbnail) {
1964 thumbnailProcessedNumber_ = thumbnailProcessedNumber;
1965 std::this_thread::sleep_for(std::chrono::milliseconds(THUMBNAIL_QUERY_INTERVAL));
1966 int32_t newReadyAstcCount = BackupDatabaseUtils::QueryReadyAstcCount(mediaLibraryRdb_);
1967 CHECK_AND_RETURN_LOG(newReadyAstcCount >= 0, "NewReadyAstcCount:%{public}d is invalid", newReadyAstcCount);
1968 if (newReadyAstcCount <= readyAstcCount) {
1969 MEDIA_WARN_LOG("Astc is not added, oldReadyAstcCount:%{public}d, newReadyAstcCount:%{public}d, "
1970 "timeoutTimes:%{public}d", readyAstcCount, newReadyAstcCount, timeoutTimes);
1971 readyAstcCount = newReadyAstcCount;
1972 ++timeoutTimes;
1973 isNeedWaitRestoreThumbnail = timeoutTimes <= MAX_RESTORE_THUMBNAIL_TIMEOUT_TIMES ||
1974 MediaFileUtils::UTCTimeMilliSeconds() - startRestoreThumbnailTime <= MIN_RESTORE_THUMBNAIL_TIME;
1975 continue;
1976 }
1977 thumbnailProcessedNumber += static_cast<uint64_t>(newReadyAstcCount - readyAstcCount);
1978 readyAstcCount = newReadyAstcCount;
1979 timeoutTimes = 0;
1980 isNeedWaitRestoreThumbnail = true;
1981 }
1982 thumbnailProcessedNumber_ = thumbnailProcessedNumber < thumbnailTotalNumber ?
1983 thumbnailProcessedNumber : thumbnailTotalNumber;
1984 MEDIA_INFO_LOG("Finish RestoreThumbnail, readyAstcCount:%{public}d, restoreAstcCount:%{public}d",
1985 readyAstcCount, restoreAstcCount);
1986 }
1987
StartBackup()1988 void BaseRestore::StartBackup()
1989 {}
1990
CheckInvalidFile(const FileInfo & fileInfo,int32_t errCode)1991 std::string BaseRestore::CheckInvalidFile(const FileInfo &fileInfo, int32_t errCode)
1992 {
1993 return "";
1994 }
1995
GetRestoreTotalInfo()1996 std::string BaseRestore::GetRestoreTotalInfo()
1997 {
1998 std::stringstream restoreTotalInfo;
1999 uint64_t success = migrateFileNumber_;
2000 uint64_t duplicate = migratePhotoDuplicateNumber_ + migrateVideoDuplicateNumber_;
2001 uint64_t failed = static_cast<uint64_t>(GetFailedFiles(STAT_TYPE_PHOTO).size() +
2002 GetFailedFiles(STAT_TYPE_VIDEO).size());
2003 uint64_t error = totalNumber_ - success - duplicate - failed - notFoundNumber_;
2004 restoreTotalInfo << failed;
2005 restoreTotalInfo << ";" << error;
2006 restoreTotalInfo << ";" << GetNoNeedMigrateCount();
2007 return restoreTotalInfo.str();
2008 }
2009
GetNoNeedMigrateCount()2010 int32_t BaseRestore::GetNoNeedMigrateCount()
2011 {
2012 return 0;
2013 }
2014
ExtraCheckForCloneSameFile(FileInfo & fileInfo,PhotosDao::PhotosRowData & rowData)2015 bool BaseRestore::ExtraCheckForCloneSameFile(FileInfo &fileInfo, PhotosDao::PhotosRowData &rowData)
2016 {
2017 fileInfo.isNew = false;
2018 fileInfo.fileIdNew = rowData.fileId;
2019 fileInfo.cloudPath = rowData.data;
2020 bool isInCloud = rowData.cleanFlag == 1 && rowData.position == static_cast<int32_t>(PhotoPositionType::CLOUD);
2021 // If the file was in cloud previously with clean_flag = 1, reset it's position to local
2022 if (rowData.fileId > 0 && isInCloud) {
2023 fileInfo.needUpdate = true;
2024 return false;
2025 }
2026 fileInfo.needMove = false;
2027 return true;
2028 }
2029
UpdatePhotosByFileInfoMap(std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb,std::vector<FileInfo> & fileInfos)2030 void BaseRestore::UpdatePhotosByFileInfoMap(std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb,
2031 std::vector<FileInfo>& fileInfos)
2032 {
2033 std::vector<std::string> inColumn;
2034 for (FileInfo &fileInfo : fileInfos) {
2035 if (fileInfo.fileIdNew <= 0 || fileInfo.isNew || !fileInfo.needUpdate) {
2036 continue;
2037 }
2038 if (MediaFileUtils::IsFileExists(fileInfo.cloudPath)) {
2039 int32_t ret = RemoveDentryFileWithConflict(fileInfo);
2040 if (ret != E_OK) {
2041 fileInfo.needUpdate = false;
2042 MEDIA_ERR_LOG("Failed to remove dentry file %{public}s", fileInfo.cloudPath.c_str());
2043 continue;
2044 }
2045 inColumn.push_back(to_string(fileInfo.fileIdNew));
2046 }
2047 }
2048 BackupDatabaseUtils::BatchUpdatePhotosToLocal(mediaLibraryRdb, inColumn);
2049 }
2050
RemoveDentryFileWithConflict(const FileInfo & fileInfo)2051 int32_t BaseRestore::RemoveDentryFileWithConflict(const FileInfo &fileInfo)
2052 {
2053 // Delete dentry file
2054 string dummyPath = fileInfo.cloudPath + ".tmp";
2055 int32_t moveToRet = MoveFile(fileInfo.cloudPath, dummyPath);
2056 CHECK_AND_RETURN_RET_LOG(moveToRet == E_OK, moveToRet,
2057 "Move file from %{public}s to %{public}s failed, ret=%{public}d", fileInfo.cloudPath.c_str(),
2058 dummyPath.c_str(), moveToRet);
2059
2060 bool dentryDeleted = false;
2061 if (MediaFileUtils::IsFileExists(fileInfo.cloudPath)) {
2062 (void)MediaFileUtils::DeleteFile(fileInfo.cloudPath);
2063 dentryDeleted = true;
2064 }
2065
2066 int32_t moveBackRet = MoveFile(dummyPath, fileInfo.cloudPath);
2067 CHECK_AND_RETURN_RET_LOG(moveBackRet == E_OK, moveBackRet,
2068 "Move file from %{public}s to %{public}s failed, ret=%{public}d", dummyPath.c_str(),
2069 fileInfo.cloudPath.c_str(), moveBackRet);
2070
2071 // Delete thumb dentry file
2072 string tmpPathThumb = fileInfo.cloudPath;
2073 string thumbPath = tmpPathThumb.replace(0, RESTORE_CLOUD_DIR.length(), RESTORE_THUMB_CLOUD_DIR);
2074 bool cond = (MediaFileUtils::IsFileExists(thumbPath) && dentryDeleted);
2075 CHECK_AND_EXECUTE(!cond, (void)MediaFileUtils::DeleteDir(thumbPath));
2076 return E_OK;
2077 }
2078
AddToPhotoInfoMap(std::vector<FileInfo> & fileInfos)2079 void BaseRestore::AddToPhotoInfoMap(std::vector<FileInfo> &fileInfos)
2080 {
2081 std::lock_guard<ffrt::mutex> lock(photoInfoMutex_);
2082 for (auto fileInfo: fileInfos) {
2083 PhotoInfo photoInfo;
2084 photoInfo.fileIdNew = fileInfo.fileIdNew;
2085 photoInfo.fileType = fileInfo.fileType;
2086 photoInfo.displayName = fileInfo.displayName;
2087 photoInfo.cloudPath = fileInfo.cloudPath;
2088 photoInfoMap_.insert(std::make_pair(fileInfo.fileIdOld, photoInfo));
2089 }
2090 }
2091
GetUpgradeEnhance()2092 std::string BaseRestore::GetUpgradeEnhance()
2093 {
2094 std::stringstream upgradeEnhance;
2095 upgradeEnhance << localLcdCount_;
2096 upgradeEnhance << "," << localThumbnailCount_;
2097 upgradeEnhance << "," << cloudLcdCount_;
2098 upgradeEnhance << "," << cloudThumbnailCount_;
2099 upgradeEnhance << "," << totalCloudMetaNumber_;
2100 upgradeEnhance << "," << successCloudMetaNumber_;
2101 upgradeEnhance << "," << rotateLcdMigrateFileNumber_;
2102 upgradeEnhance << "," << rotateThmMigrateFileNumber_;
2103 return upgradeEnhance.str();
2104 }
2105
IsCloudRestoreSatisfied()2106 bool BaseRestore::IsCloudRestoreSatisfied()
2107 {
2108 return isAccountValid_ && isSyncSwitchOn_;
2109 }
2110
ProcessBurstPhotos()2111 void BaseRestore::ProcessBurstPhotos()
2112 {
2113 int64_t startProcess = MediaFileUtils::UTCTimeMilliSeconds();
2114 BackupDatabaseUtils::UpdateBurstPhotos(mediaLibraryRdb_);
2115 int64_t endProcess = MediaFileUtils::UTCTimeMilliSeconds();
2116 MEDIA_INFO_LOG("process burst photos end, cost: %{public}" PRId64, endProcess - startProcess);
2117 }
2118
SetOrientationAndExifRotate(FileInfo & info,NativeRdb::ValuesBucket & value,std::unique_ptr<Metadata> & data)2119 void BaseRestore::SetOrientationAndExifRotate(FileInfo &info, NativeRdb::ValuesBucket &value,
2120 std::unique_ptr<Metadata> &data)
2121 {
2122 CHECK_AND_RETURN_LOG(data != nullptr, "Metadata is nullptr");
2123 info.orientation = data->GetOrientation();
2124 value.PutInt(PhotoColumn::PHOTO_ORIENTATION, info.orientation);
2125 info.exifRotate = data->GetExifRotate();
2126 value.PutInt(PhotoColumn::PHOTO_EXIF_ROTATE, info.exifRotate);
2127 }
2128
HasExThumbnail(const FileInfo & info)2129 bool BaseRestore::HasExThumbnail(const FileInfo &info)
2130 {
2131 CHECK_AND_RETURN_RET(info.localMediaId != -1, BackupFileUtils::HasOrientationOrExifRotate(info));
2132 return info.fileType == MediaType::MEDIA_TYPE_IMAGE && BackupFileUtils::HasOrientationOrExifRotate(info);
2133 }
2134
GetSouthDeviceSwithStatusTimestamp()2135 inline int64_t GetSouthDeviceSwithStatusTimestamp()
2136 {
2137 constexpr int64_t defaultValueTime = 0;
2138 return system::GetIntParameter(CLOUDSYNC_SWITCH_STATUS_KEY.c_str(), defaultValueTime);
2139 }
2140
WaitSouthDeviceExitTimeout()2141 bool BaseRestore::WaitSouthDeviceExitTimeout()
2142 {
2143 constexpr int64_t defaultValueTime = 0;
2144 int64_t startTimeClean = GetSouthDeviceSwithStatusTimestamp();
2145 int64_t startTimeWait = MediaFileUtils::UTCTimeMilliSeconds();
2146 MEDIA_INFO_LOG("Wait for the south device to exit. startTimeWait: %{public}" PRId64
2147 ", startTimeClean: %{public}" PRId64, startTimeWait, startTimeClean);
2148 while (startTimeClean > 0) {
2149 auto nowTime = MediaFileUtils::UTCTimeMilliSeconds();
2150 int64_t waitTimeout = RESTORE_OR_BACKUP_WAIT_FORCE_RETAIN_CLOUD_MEDIA_TIMEOUT_MILLISECOND; // unit: ms
2151 if ((nowTime - startTimeWait) > waitTimeout) {
2152 MEDIA_WARN_LOG("[Restore or Backup] timeout: now: %{public}" PRId64", startTimeWait: %{public}" PRId64
2153 ", startTimeClean: %{public}" PRId64, nowTime, startTimeWait, startTimeClean);
2154 return true;
2155 }
2156 std::this_thread::sleep_for(std::chrono::milliseconds(
2157 RESTORE_OR_BACKUP_WAIT_FORCE_RETAIN_CLOUD_MEDIA_SLEEP_TIME_MILLISECOND));
2158 startTimeClean = GetSouthDeviceSwithStatusTimestamp();
2159 MEDIA_DEBUG_LOG("[Restore or Backup] waiting: now: %{public}" PRId64", startTimeWait: %{public}" PRId64
2160 ", startTimeClean: %{public}" PRId64, nowTime, startTimeWait, startTimeClean);
2161 }
2162 MEDIA_INFO_LOG("the south device has exited. exitTime: %{public}" PRId64, MediaFileUtils::UTCTimeMilliSeconds());
2163 return false;
2164 }
2165
StartBackupEx(std::string & backupExInfo)2166 void BaseRestore::StartBackupEx(std::string& backupExInfo)
2167 {
2168 StartBackup();
2169 backupExInfo = GetBackupExInfo();
2170 }
2171
GetBackupExInfo()2172 std::string BaseRestore::GetBackupExInfo()
2173 {
2174 return GetBackupErrorInfoJson().dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
2175 }
2176
GetBackupErrorInfoJson()2177 nlohmann::json BaseRestore::GetBackupErrorInfoJson()
2178 {
2179 int32_t errorCode = errorCode_ == RestoreError::SUCCESS ? STAT_DEFAULT_ERROR_CODE_SUCCESS :
2180 STAT_DEFAULT_ERROR_CODE_FAILED;
2181 nlohmann::json errorInfoJson = {
2182 { STAT_KEY_TYPE, STAT_VALUE_ERROR_INFO },
2183 { STAT_KEY_ERROR_CODE, std::to_string(errorCode) },
2184 { STAT_KEY_ERROR_INFO, errorInfo_ }
2185 };
2186 return errorInfoJson;
2187 }
2188
Release(ReleaseScene releaseScene)2189 void BaseRestore::Release(ReleaseScene releaseScene)
2190 {
2191 if (releaseScene == ReleaseScene::BACKUP) {
2192 BackupRelease();
2193 } else if (releaseScene == ReleaseScene::RESTORE) {
2194 RestoreRelease();
2195 } else {
2196 MEDIA_ERR_LOG("Invalid ReleaseScene: %{public}d", static_cast<int>(releaseScene));
2197 }
2198 }
2199
BackupRelease()2200 void BaseRestore::BackupRelease()
2201 {
2202 }
2203
RestoreRelease()2204 void BaseRestore::RestoreRelease()
2205 {
2206 }
2207 } // namespace Media
2208 } // namespace OHOS
2209