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