• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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