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