• 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 "application_context.h"
21 #include "backup_database_utils.h"
22 #include "backup_dfx_utils.h"
23 #include "backup_file_utils.h"
24 #include "directory_ex.h"
25 #include "extension_context.h"
26 #include "media_column.h"
27 #include "media_log.h"
28 #include "media_file_utils.h"
29 #include "media_scanner_manager.h"
30 #include "medialibrary_asset_operations.h"
31 #include "medialibrary_data_manager.h"
32 #include "medialibrary_object_utils.h"
33 #include "medialibrary_rdb_utils.h"
34 #include "medialibrary_type_const.h"
35 #include "medialibrary_errno.h"
36 #include "metadata.h"
37 #include "moving_photo_file_utils.h"
38 #include "parameters.h"
39 #include "photo_album_column.h"
40 #include "result_set_utils.h"
41 #include "userfilemgr_uri.h"
42 #include "medialibrary_notify.h"
43 #include "upgrade_restore_task_report.h"
44 #include "medialibrary_rdb_transaction.h"
45 
46 namespace OHOS {
47 namespace Media {
48 const std::string DATABASE_PATH = "/data/storage/el2/database/rdb/media_library.db";
49 const std::string singleDirName = "A";
50 const std::string CLONE_FLAG = "multimedia.medialibrary.cloneFlag";
51 
StartRestore(const std::string & backupRetoreDir,const std::string & upgradePath)52 void BaseRestore::StartRestore(const std::string &backupRetoreDir, const std::string &upgradePath)
53 {
54     backupRestoreDir_ = backupRetoreDir;
55     int32_t errorCode = Init(backupRetoreDir, upgradePath, true);
56     if (errorCode == E_OK) {
57         RestorePhoto();
58         RestoreAudio();
59         MEDIA_INFO_LOG("migrate database number: %{public}lld, file number: %{public}lld (%{public}lld + "
60             "%{public}lld), duplicate number: %{public}lld + %{public}lld, audio database number:%{public}lld, "
61             "audio file number:%{public}lld, duplicate audio number: %{public}lld, map number: %{public}lld",
62             (long long)migrateDatabaseNumber_, (long long)migrateFileNumber_,
63             (long long)(migrateFileNumber_ - migrateVideoFileNumber_), (long long)migrateVideoFileNumber_,
64             (long long)migratePhotoDuplicateNumber_, (long long)migrateVideoDuplicateNumber_,
65             (long long)migrateAudioDatabaseNumber_, (long long)migrateAudioFileNumber_,
66             (long long)migrateAudioDuplicateNumber_, (long long) migrateDatabaseMapNumber_);
67         UpdateDatabase();
68     } else {
69         if (errorCode != EXTERNAL_DB_NOT_EXIST) {
70             SetErrorCode(RestoreError::INIT_FAILED);
71         }
72     }
73     HandleRestData();
74 }
75 
Init(void)76 int32_t BaseRestore::Init(void)
77 {
78     if (mediaLibraryRdb_ != nullptr) {
79         return E_OK;
80     }
81     auto context = AbilityRuntime::Context::GetApplicationContext();
82     if (context == nullptr) {
83         MEDIA_ERR_LOG("Failed to get context");
84         return E_FAIL;
85     }
86     int32_t err = BackupDatabaseUtils::InitDb(mediaLibraryRdb_, MEDIA_DATA_ABILITY_DB_NAME, DATABASE_PATH, BUNDLE_NAME,
87         true, context->GetArea());
88     if (err != E_OK) {
89         MEDIA_ERR_LOG("medialibrary rdb fail, err = %{public}d", err);
90         return E_FAIL;
91     }
92     int32_t sceneCode = 0;
93     int32_t errCode = MediaLibraryDataManager::GetInstance()->InitMediaLibraryMgr(context, nullptr, sceneCode);
94     if (errCode != E_OK) {
95         MEDIA_ERR_LOG("When restore, InitMediaLibraryMgr fail, errcode = %{public}d", errCode);
96         return errCode;
97     }
98     migrateDatabaseNumber_ = 0;
99     migrateFileNumber_ = 0;
100     migrateVideoFileNumber_ = 0;
101     migrateAudioDatabaseNumber_ = 0;
102     migrateAudioFileNumber_ = 0;
103     imageNumber_ = BackupDatabaseUtils::QueryUniqueNumber(mediaLibraryRdb_, IMAGE_ASSET_TYPE);
104     videoNumber_ = BackupDatabaseUtils::QueryUniqueNumber(mediaLibraryRdb_, VIDEO_ASSET_TYPE);
105     audioNumber_ = BackupDatabaseUtils::QueryUniqueNumber(mediaLibraryRdb_, AUDIO_ASSET_TYPE);
106     MEDIA_INFO_LOG("imageNumber: %{public}d", (int)imageNumber_);
107     MEDIA_INFO_LOG("videoNumber: %{public}d", (int)videoNumber_);
108     MEDIA_INFO_LOG("audioNumber: %{public}d", (int)audioNumber_);
109     return E_OK;
110 }
111 
ConvertPathToRealPath(const std::string & srcPath,const std::string & prefix,std::string & newPath,std::string & relativePath)112 bool BaseRestore::ConvertPathToRealPath(const std::string &srcPath, const std::string &prefix,
113     std::string &newPath, std::string &relativePath)
114 {
115     size_t pos = 0;
116     int32_t count = 0;
117     constexpr int32_t prefixLevel = 4;
118     for (size_t i = 0; i < srcPath.length(); i++) {
119         if (srcPath[i] == '/') {
120             count++;
121             if (count == prefixLevel) {
122                 pos = i;
123                 break;
124             }
125         }
126     }
127     if (count < prefixLevel) {
128         return false;
129     }
130     relativePath = srcPath.substr(pos);
131     if (!dualDirName_.empty() && relativePath.find(dualDirName_) != string::npos) {
132         std::size_t posStart = relativePath.find_first_of("/");
133         std::size_t posEnd = relativePath.find_first_of("/", posStart + 1);
134         if (posEnd != string::npos) {
135             string temp = relativePath.substr(posStart + 1, posEnd - posStart -1);
136             if (temp == dualDirName_) {
137                 relativePath.replace(relativePath.find(dualDirName_), dualDirName_.length(), singleDirName);
138             }
139         }
140     }
141     newPath = prefix + relativePath;
142     return true;
143 }
144 
QuerySql(const string & sql,const vector<string> & selectionArgs) const145 shared_ptr<NativeRdb::ResultSet> BaseRestore::QuerySql(const string &sql, const vector<string> &selectionArgs) const
146 {
147     if (mediaLibraryRdb_ == nullptr) {
148         MEDIA_ERR_LOG("Pointer rdb_ is nullptr. Maybe it didn't init successfully.");
149         return nullptr;
150     }
151 
152     return mediaLibraryRdb_->QuerySql(sql, selectionArgs);
153 }
154 
MoveFile(const std::string & srcFile,const std::string & dstFile) const155 int32_t BaseRestore::MoveFile(const std::string &srcFile, const std::string &dstFile) const
156 {
157     int32_t errCode = BackupFileUtils::MoveFile(srcFile, dstFile, sceneCode_);
158     if (errCode == E_SUCCESS) {
159         return E_OK;
160     }
161     if (this->CopyFile(srcFile, dstFile) != E_OK) {
162         return E_FAIL;
163     }
164     (void)MediaFileUtils::DeleteFile(srcFile);
165     return E_OK;
166 }
167 
CopyFile(const std::string & srcFile,const std::string & dstFile) const168 int32_t BaseRestore::CopyFile(const std::string &srcFile, const std::string &dstFile) const
169 {
170     if (!MediaFileUtils::CopyFileUtil(srcFile, dstFile)) {
171         MEDIA_ERR_LOG("CopyFile failed, src: %{public}s, dst: %{public}s, errMsg: %{public}s",
172             BackupFileUtils::GarbleFilePath(srcFile, sceneCode_).c_str(),
173             BackupFileUtils::GarbleFilePath(srcFile, DEFAULT_RESTORE_ID).c_str(), strerror(errno));
174         return E_FAIL;
175     }
176     return E_OK;
177 }
178 
IsFileValid(FileInfo & fileInfo,const int32_t sceneCode)179 bool BaseRestore::IsFileValid(FileInfo &fileInfo, const int32_t sceneCode)
180 {
181     if (!BackupFileUtils::IsFileValid(fileInfo.filePath, DUAL_FRAME_CLONE_RESTORE_ID,
182         fileInfo.relativePath, hasLowQualityImage_)) {
183         MEDIA_ERR_LOG("File is not valid: %{public}s, errno=%{public}d.",
184             BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode).c_str(), errno);
185         return false;
186     }
187 
188     if (BackupFileUtils::IsLivePhoto(fileInfo)) {
189         if (!MediaFileUtils::IsFileValid(fileInfo.movingPhotoVideoPath)) {
190             MEDIA_ERR_LOG("Moving photo video is not valid: %{public}s, errno=%{public}d.",
191                 BackupFileUtils::GarbleFilePath(fileInfo.movingPhotoVideoPath, sceneCode).c_str(), errno);
192             return false;
193         }
194 
195         if (!MediaFileUtils::IsFileValid(fileInfo.extraDataPath)) {
196             MEDIA_WARN_LOG("Media extra data is not valid: %{public}s, errno=%{public}d.",
197                 BackupFileUtils::GarbleFilePath(fileInfo.extraDataPath, sceneCode).c_str(), errno);
198             return false;
199         }
200     }
201     return true;
202 }
203 
RemoveDuplicateDualCloneFiles(const FileInfo & fileInfo)204 static void RemoveDuplicateDualCloneFiles(const FileInfo &fileInfo)
205 {
206     (void)MediaFileUtils::DeleteFile(fileInfo.filePath);
207     if (BackupFileUtils::IsLivePhoto(fileInfo)) {
208         (void)MediaFileUtils::DeleteFile(fileInfo.movingPhotoVideoPath);
209         (void)MediaFileUtils::DeleteFile(fileInfo.extraDataPath);
210     }
211 }
212 
GetInsertValues(const int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)213 vector<NativeRdb::ValuesBucket> BaseRestore::GetInsertValues(const int32_t sceneCode, std::vector<FileInfo> &fileInfos,
214     int32_t sourceType)
215 {
216     vector<NativeRdb::ValuesBucket> values;
217     for (size_t i = 0; i < fileInfos.size(); i++) {
218         if (!IsFileValid(fileInfos[i], sceneCode)) {
219             MEDIA_WARN_LOG("File is not exist, filePath = %{public}s.",
220                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
221             fileInfos[i].needMove = false;
222             if (fileInfos[i].fileSize == 0) {
223                 MEDIA_ERR_LOG("this is file size is 0");
224             }
225             MEDIA_ERR_LOG("File is invalid: sceneCode: %{public}d, sourceType: %{public}d, filePath: %{public}s",
226                 sceneCode,
227                 sourceType,
228                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
229             continue;
230         }
231         std::string cloudPath;
232         int32_t uniqueId = GetUniqueId(fileInfos[i].fileType);
233         int32_t errCode = BackupFileUtils::CreateAssetPathById(uniqueId, fileInfos[i].fileType,
234             MediaFileUtils::GetExtensionFromPath(fileInfos[i].displayName), cloudPath);
235         if (errCode != E_OK) {
236             fileInfos[i].needMove = false;
237             MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d, path: %{public}s", errCode,
238                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
239             continue;
240         }
241         fileInfos[i].cloudPath = cloudPath;
242         NativeRdb::ValuesBucket value = GetInsertValue(fileInfos[i], cloudPath, sourceType);
243         SetValueFromMetaData(fileInfos[i], value);
244         if ((sceneCode == DUAL_FRAME_CLONE_RESTORE_ID || sceneCode == OTHERS_PHONE_CLONE_RESTORE ||
245             sceneCode == I_PHONE_CLONE_RESTORE) && this->HasSameFileForDualClone(fileInfos[i])) {
246             fileInfos[i].needMove = false;
247             RemoveDuplicateDualCloneFiles(fileInfos[i]);
248             MEDIA_WARN_LOG("File %{public}s already exists.",
249                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
250             UpdateDuplicateNumber(fileInfos[i].fileType);
251             continue;
252         }
253         values.emplace_back(value);
254     }
255     return values;
256 }
257 
InsertDateAdded(std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & value)258 static void InsertDateAdded(std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &value)
259 {
260     int64_t dateAdded = metadata->GetFileDateAdded();
261     if (dateAdded != 0) {
262         value.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
263         return;
264     }
265 
266     int64_t dateTaken = metadata->GetDateTaken();
267     if (dateTaken == 0) {
268         int64_t dateModified = metadata->GetFileDateModified();
269         if (dateModified == 0) {
270             dateAdded = MediaFileUtils::UTCTimeMilliSeconds();
271         } else {
272             dateAdded = dateModified;
273         }
274     } else {
275         dateAdded = dateTaken;
276     }
277     value.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
278 }
279 
InsertOrientation(std::unique_ptr<Metadata> & metadata,NativeRdb::ValuesBucket & value,FileInfo & fileInfo,int32_t sceneCode)280 static void InsertOrientation(std::unique_ptr<Metadata> &metadata, NativeRdb::ValuesBucket &value,
281     FileInfo &fileInfo, int32_t sceneCode)
282 {
283     bool hasOrientation = value.HasColumn(PhotoColumn::PHOTO_ORIENTATION);
284     if (hasOrientation && fileInfo.fileType != MEDIA_TYPE_VIDEO) {
285         return; // image use orientation in rdb
286     }
287     if (hasOrientation) {
288         value.Delete(PhotoColumn::PHOTO_ORIENTATION);
289     }
290     value.PutInt(PhotoColumn::PHOTO_ORIENTATION, metadata->GetOrientation()); // video use orientation in metadata
291     if (sceneCode == OTHERS_PHONE_CLONE_RESTORE || sceneCode == I_PHONE_CLONE_RESTORE) {
292         fileInfo.orientation = metadata->GetOrientation();
293     }
294 }
295 
SetCoverPosition(const FileInfo & fileInfo,const unique_ptr<Metadata> & imageMetaData,NativeRdb::ValuesBucket & value)296 static void SetCoverPosition(const FileInfo &fileInfo,
297     const unique_ptr<Metadata> &imageMetaData, NativeRdb::ValuesBucket &value)
298 {
299     uint64_t coverPosition = 0;
300     if (BackupFileUtils::IsLivePhoto(fileInfo)) {
301         uint32_t version = 0;
302         uint32_t frameIndex = 0;
303         bool hasCinemagraphInfo = false;
304         string absExtraDataPath;
305         if (!PathToRealPath(fileInfo.extraDataPath, absExtraDataPath)) {
306             MEDIA_ERR_LOG("file is not real path: %{private}s, errno: %{public}d",
307                 fileInfo.extraDataPath.c_str(), errno);
308             value.PutLong(PhotoColumn::PHOTO_COVER_POSITION, static_cast<int64_t>(coverPosition));
309             return;
310         }
311         UniqueFd extraDataFd(open(absExtraDataPath.c_str(), O_RDONLY));
312         (void)MovingPhotoFileUtils::GetVersionAndFrameNum(extraDataFd.Get(), version, frameIndex, hasCinemagraphInfo);
313         (void)MovingPhotoFileUtils::GetCoverPosition(fileInfo.movingPhotoVideoPath,
314             frameIndex, coverPosition, Scene::AV_META_SCENE_CLONE);
315     }
316     value.PutLong(PhotoColumn::PHOTO_COVER_POSITION, static_cast<int64_t>(coverPosition));
317 }
318 
SetValueFromMetaData(FileInfo & fileInfo,NativeRdb::ValuesBucket & value)319 void BaseRestore::SetValueFromMetaData(FileInfo &fileInfo, NativeRdb::ValuesBucket &value)
320 {
321     std::unique_ptr<Metadata> data = make_unique<Metadata>();
322     data->SetFilePath(fileInfo.filePath);
323     data->SetFileMediaType(fileInfo.fileType);
324     data->SetFileDateModified(fileInfo.dateModified);
325     data->SetFileName(fileInfo.displayName);
326     BackupFileUtils::FillMetadata(data);
327     MediaType mediaType = data->GetFileMediaType();
328 
329     value.PutString(MediaColumn::MEDIA_FILE_PATH, data->GetFilePath());
330     value.PutString(MediaColumn::MEDIA_MIME_TYPE, data->GetFileMimeType());
331     value.PutInt(MediaColumn::MEDIA_TYPE, mediaType);
332     value.PutString(MediaColumn::MEDIA_TITLE, data->GetFileTitle());
333     if (fileInfo.fileSize != 0) {
334         value.PutLong(MediaColumn::MEDIA_SIZE, fileInfo.fileSize);
335     } else {
336         MEDIA_WARN_LOG("DB file size is zero!");
337         value.PutLong(MediaColumn::MEDIA_SIZE, data->GetFileSize());
338         fileInfo.fileSize = data->GetFileSize();
339     }
340     value.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, data->GetFileDateModified());
341     value.PutInt(MediaColumn::MEDIA_DURATION, data->GetFileDuration());
342     value.PutLong(MediaColumn::MEDIA_DATE_TAKEN, data->GetDateTaken());
343     value.PutLong(MediaColumn::MEDIA_TIME_PENDING, 0);
344     value.PutInt(PhotoColumn::PHOTO_HEIGHT, data->GetFileHeight());
345     value.PutInt(PhotoColumn::PHOTO_WIDTH, data->GetFileWidth());
346     value.PutDouble(PhotoColumn::PHOTO_LONGITUDE, data->GetLongitude());
347     value.PutDouble(PhotoColumn::PHOTO_LATITUDE, data->GetLatitude());
348     value.PutString(PhotoColumn::PHOTO_ALL_EXIF, data->GetAllExif());
349     value.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, data->GetShootingMode());
350     value.PutString(PhotoColumn::PHOTO_SHOOTING_MODE_TAG, data->GetShootingModeTag());
351     value.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, data->GetLastVisitTime());
352     value.PutString(PhotoColumn::PHOTO_FRONT_CAMERA, data->GetFrontCamera());
353     value.PutInt(PhotoColumn::PHOTO_DYNAMIC_RANGE_TYPE, data->GetDynamicRangeType());
354     InsertDateAdded(data, value);
355     InsertOrientation(data, value, fileInfo, sceneCode_);
356     int64_t dateAdded = 0;
357     NativeRdb::ValueObject valueObject;
358     if (value.GetObject(MediaColumn::MEDIA_DATE_ADDED, valueObject)) {
359         valueObject.GetLong(dateAdded);
360     }
361     fileInfo.dateAdded = dateAdded;
362     value.PutString(PhotoColumn::PHOTO_DATE_YEAR,
363         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_YEAR_FORMAT, dateAdded));
364     value.PutString(PhotoColumn::PHOTO_DATE_MONTH,
365         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_MONTH_FORMAT, dateAdded));
366     value.PutString(PhotoColumn::PHOTO_DATE_DAY,
367         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_DAY_FORMAT, dateAdded));
368     SetCoverPosition(fileInfo, data, value);
369 }
370 
CreateDir(std::string & dir)371 void BaseRestore::CreateDir(std::string &dir)
372 {
373     if (!MediaFileUtils::IsFileExists(dir)) {
374         MediaFileUtils::CreateDirectory(dir);
375     }
376 }
377 
RecursiveCreateDir(std::string & relativePath,std::string & suffix)378 void BaseRestore::RecursiveCreateDir(std::string &relativePath, std::string &suffix)
379 {
380     CreateDir(relativePath);
381     size_t pos = suffix.find('/');
382     if (pos == std::string::npos) {
383         MEDIA_ERR_LOG("Recursive completion, return.");
384         return;
385     }
386     std::string prefix = suffix.substr(0, pos + 1);
387     std::string suffixTmp = suffix.erase(0, prefix.length());
388     prefix = relativePath + prefix;
389     RecursiveCreateDir(prefix, suffixTmp);
390 }
391 
InsertAudio(int32_t sceneCode,std::vector<FileInfo> & fileInfos)392 void BaseRestore::InsertAudio(int32_t sceneCode, std::vector<FileInfo> &fileInfos)
393 {
394     if (fileInfos.empty()) {
395         MEDIA_ERR_LOG("fileInfos are empty");
396         return;
397     }
398     int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
399     int32_t fileMoveCount = 0;
400     for (size_t i = 0; i < fileInfos.size(); i++) {
401         if (!MediaFileUtils::IsFileExists(fileInfos[i].filePath)) {
402             continue;
403         }
404         string relativePath0 = RESTORE_MUSIC_LOCAL_DIR;
405         string relativePath1 = fileInfos[i].relativePath;
406         if (relativePath1[0] == '/') {
407             relativePath1.erase(0, 1);
408         }
409         string dstPath = RESTORE_MUSIC_LOCAL_DIR + relativePath1;
410         RecursiveCreateDir(relativePath0, relativePath1);
411         if (MediaFileUtils::IsFileExists(dstPath)) {
412             MEDIA_INFO_LOG("dstPath %{public}s already exists.",
413                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str());
414             UpdateDuplicateNumber(fileInfos[i].fileType);
415             continue;
416         }
417         int32_t moveErrCode = BackupFileUtils::MoveFile(fileInfos[i].filePath, dstPath, sceneCode);
418         if (moveErrCode != E_SUCCESS) {
419             MEDIA_ERR_LOG("MoveFile failed, filePath: %{public}s, errCode: %{public}d, errno: %{public}d",
420                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, sceneCode).c_str(), moveErrCode, errno);
421             UpdateFailedFiles(fileInfos[i].fileType, fileInfos[i], RestoreError::MOVE_FAILED);
422             continue;
423         }
424         BackupFileUtils::ModifyFile(dstPath, fileInfos[i].dateModified / MSEC_TO_SEC);
425         fileMoveCount++;
426     }
427     migrateAudioFileNumber_ += fileMoveCount;
428     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
429     MEDIA_INFO_LOG("move %{public}ld file cost %{public}ld.", (long)fileMoveCount, (long)(end - startMove));
430 }
431 
MoveExtraData(const FileInfo & fileInfo,int32_t sceneCode)432 static bool MoveExtraData(const FileInfo &fileInfo, int32_t sceneCode)
433 {
434     string localExtraDataDir = BackupFileUtils::GetReplacedPathByPrefixType(
435         PrefixType::CLOUD, PrefixType::LOCAL, MovingPhotoFileUtils::GetMovingPhotoExtraDataDir(fileInfo.cloudPath));
436     if (localExtraDataDir.empty()) {
437         MEDIA_WARN_LOG("Failed to get local extra data dir");
438         return false;
439     }
440     if (!MediaFileUtils::IsFileExists(localExtraDataDir) && !MediaFileUtils::CreateDirectory(localExtraDataDir)) {
441         MEDIA_WARN_LOG("Failed to create local extra data dir, errno:%{public}d", errno);
442         return false;
443     }
444 
445     string localExtraDataPath = BackupFileUtils::GetReplacedPathByPrefixType(
446         PrefixType::CLOUD, PrefixType::LOCAL, MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(fileInfo.cloudPath));
447     if (localExtraDataPath.empty()) {
448         MEDIA_WARN_LOG("Failed to get local extra data path");
449         return false;
450     }
451     int32_t errCode = BackupFileUtils::MoveFile(fileInfo.extraDataPath, localExtraDataPath, sceneCode);
452     if (errCode != E_OK) {
453         MEDIA_WARN_LOG("MoveFile failed, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
454             BackupFileUtils::GarbleFilePath(fileInfo.extraDataPath, sceneCode).c_str(),
455             BackupFileUtils::GarbleFilePath(localExtraDataPath, sceneCode).c_str(), errCode, errno);
456         return false;
457     }
458     return true;
459 }
460 
MoveAndModifyFile(const FileInfo & fileInfo,int32_t sceneCode)461 static bool MoveAndModifyFile(const FileInfo &fileInfo, int32_t sceneCode)
462 {
463     string tmpPath = fileInfo.cloudPath;
464     string localPath = tmpPath.replace(0, RESTORE_CLOUD_DIR.length(), RESTORE_LOCAL_DIR);
465     int32_t errCode = BackupFileUtils::MoveFile(fileInfo.filePath, localPath, sceneCode);
466     if (errCode != E_OK) {
467         MEDIA_ERR_LOG("MoveFile failed, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
468             BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode).c_str(),
469             BackupFileUtils::GarbleFilePath(localPath, sceneCode).c_str(), errCode, errno);
470         return false;
471     }
472     BackupFileUtils::ModifyFile(localPath, fileInfo.dateModified / MSEC_TO_SEC);
473 
474     if (BackupFileUtils::IsLivePhoto(fileInfo)) {
475         string tmpVideoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(fileInfo.cloudPath);
476         string localVideoPath = tmpVideoPath.replace(0, RESTORE_CLOUD_DIR.length(), RESTORE_LOCAL_DIR);
477         errCode = BackupFileUtils::MoveFile(fileInfo.movingPhotoVideoPath, localVideoPath, sceneCode);
478         if (errCode != E_OK) {
479             MEDIA_ERR_LOG(
480                 "MoveFile failed for mov video, src:%{public}s, dest:%{public}s, err:%{public}d, errno:%{public}d",
481                 BackupFileUtils::GarbleFilePath(fileInfo.movingPhotoVideoPath, sceneCode).c_str(),
482                 BackupFileUtils::GarbleFilePath(localVideoPath, sceneCode).c_str(), errCode, errno);
483             (void)MediaFileUtils::DeleteFile(localPath);
484             return false;
485         }
486         BackupFileUtils::ModifyFile(localVideoPath, fileInfo.dateModified / MSEC_TO_SEC);
487         return MoveExtraData(fileInfo, sceneCode);
488     }
489     return true;
490 }
491 
MoveMigrateFile(std::vector<FileInfo> & fileInfos,int32_t & fileMoveCount,int32_t & videoFileMoveCount,int32_t sceneCode)492 void BaseRestore::MoveMigrateFile(std::vector<FileInfo> &fileInfos, int32_t &fileMoveCount, int32_t &videoFileMoveCount,
493     int32_t sceneCode)
494 {
495     vector<std::string> moveFailedData;
496     for (size_t i = 0; i < fileInfos.size(); i++) {
497         if (!fileInfos[i].needMove) {
498             continue;
499         }
500         if (!IsFileValid(fileInfos[i], sceneCode)) {
501             continue;
502         }
503         if (!MoveAndModifyFile(fileInfos[i], sceneCode)) {
504             UpdateFailedFiles(fileInfos[i].fileType, fileInfos[i], RestoreError::MOVE_FAILED);
505             moveFailedData.push_back(fileInfos[i].cloudPath);
506             continue;
507         }
508         fileMoveCount++;
509         videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
510     }
511     DeleteMoveFailedData(moveFailedData);
512     migrateFileNumber_ += fileMoveCount;
513     migrateVideoFileNumber_ += videoFileMoveCount;
514 }
515 
InsertPhoto(int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)516 void BaseRestore::InsertPhoto(int32_t sceneCode, std::vector<FileInfo> &fileInfos, int32_t sourceType)
517 {
518     MEDIA_INFO_LOG("Start insert %{public}zu photos", fileInfos.size());
519     if (mediaLibraryRdb_ == nullptr) {
520         MEDIA_ERR_LOG("mediaLibraryRdb_ is null");
521         return;
522     }
523     if (fileInfos.empty()) {
524         MEDIA_ERR_LOG("fileInfos are empty");
525         return;
526     }
527     int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
528     vector<NativeRdb::ValuesBucket> values = GetInsertValues(sceneCode, fileInfos, sourceType);
529     int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
530     int64_t rowNum = 0;
531     int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, rowNum);
532     if (errCode != E_OK) {
533         UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
534         return;
535     }
536 
537     int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
538     InsertPhotoRelated(fileInfos, sourceType);
539 
540     int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
541     migrateDatabaseNumber_ += rowNum;
542     int32_t fileMoveCount = 0;
543     int32_t videoFileMoveCount = 0;
544     MoveMigrateFile(fileInfos, fileMoveCount, videoFileMoveCount, sceneCode);
545     this->tabOldPhotosRestore_.Restore(this->mediaLibraryRdb_, fileInfos);
546     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
547     MEDIA_INFO_LOG("generate values cost %{public}ld, insert %{public}ld assets cost %{public}ld, insert photo related"
548         " cost %{public}ld, and move %{public}ld files (%{public}ld + %{public}ld) cost %{public}ld.",
549         (long)(startInsert - startGenerate), (long)rowNum, (long)(startInsertRelated - startInsert),
550         (long)(startMove - startInsertRelated), (long)fileMoveCount, (long)(fileMoveCount - videoFileMoveCount),
551         (long)videoFileMoveCount, (long)(end - startMove));
552 }
553 
DeleteMoveFailedData(std::vector<std::string> & moveFailedData)554 void BaseRestore::DeleteMoveFailedData(std::vector<std::string> &moveFailedData)
555 {
556     if (moveFailedData.empty()) {
557         MEDIA_INFO_LOG("No move failed");
558         return;
559     }
560     MEDIA_INFO_LOG("%{public}d file move failed", static_cast<int>(moveFailedData.size()));
561     NativeRdb::AbsRdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
562     predicates.In(MediaColumn::MEDIA_FILE_PATH, moveFailedData);
563     int32_t changedRows = 0;
564     int deleteRes = BackupDatabaseUtils::Delete(predicates, changedRows, mediaLibraryRdb_);
565     MEDIA_INFO_LOG("changeRows:%{public}d, deleteRes:%{public}d", changedRows, deleteRes);
566 }
567 
BatchInsertWithRetry(const std::string & tableName,std::vector<NativeRdb::ValuesBucket> & values,int64_t & rowNum)568 int32_t BaseRestore::BatchInsertWithRetry(const std::string &tableName, std::vector<NativeRdb::ValuesBucket> &values,
569     int64_t &rowNum)
570 {
571     if (values.empty()) {
572         return 0;
573     }
574 
575     int32_t errCode = E_ERR;
576     TransactionOperations trans;
577     trans.SetBackupRdbStore(mediaLibraryRdb_);
578     errCode = trans.Start(__func__, true);
579     if (errCode != NativeRdb::E_OK) {
580         MEDIA_ERR_LOG("can not get rdb before batch insert");
581         return errCode;
582     }
583     errCode = trans.BatchInsert(rowNum, tableName, values);
584     if (errCode != E_OK) {
585         MEDIA_ERR_LOG("InsertSql failed, errCode: %{public}d, rowNum: %{public}ld.", errCode, (long)rowNum);
586         return errCode;
587     }
588     errCode = trans.Finish();
589     if (errCode != E_OK) {
590         MEDIA_ERR_LOG("BatchInsertWithRetry: tans finish fail!, ret:%{public}d", errCode);
591     }
592     return errCode;
593 }
594 
MoveDirectory(const std::string & srcDir,const std::string & dstDir,bool deleteOriginalFile) const595 int32_t BaseRestore::MoveDirectory(const std::string &srcDir, const std::string &dstDir, bool deleteOriginalFile) const
596 {
597     if (!MediaFileUtils::CreateDirectory(dstDir)) {
598         MEDIA_ERR_LOG("Create dstDir %{public}s failed",
599             BackupFileUtils::GarbleFilePath(dstDir, DEFAULT_RESTORE_ID).c_str());
600         return E_FAIL;
601     }
602     if (!MediaFileUtils::IsFileExists(srcDir)) {
603         MEDIA_WARN_LOG("%{public}s doesn't exist, skip.", srcDir.c_str());
604         return E_OK;
605     }
606     for (const auto &dirEntry : std::filesystem::directory_iterator{ srcDir }) {
607         std::string srcFilePath = dirEntry.path();
608         std::string tmpFilePath = srcFilePath;
609         std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
610         int32_t opRet = E_FAIL;
611         if (deleteOriginalFile) {
612             opRet = this->MoveFile(srcFilePath, dstFilePath);
613         } else {
614             opRet = this->CopyFile(srcFilePath, dstFilePath);
615         }
616         if (opRet != E_OK) {
617             MEDIA_ERR_LOG("Move file from %{public}s to %{public}s failed, deleteOriginalFile=%{public}d",
618                 BackupFileUtils::GarbleFilePath(srcFilePath, sceneCode_).c_str(),
619                 BackupFileUtils::GarbleFilePath(dstFilePath, DEFAULT_RESTORE_ID).c_str(),
620                 deleteOriginalFile);
621             return E_FAIL;
622         }
623     }
624     return E_OK;
625 }
626 
IsSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & tableName,FileInfo & fileInfo)627 bool BaseRestore::IsSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore, const std::string &tableName,
628     FileInfo &fileInfo)
629 {
630     string srcPath = fileInfo.filePath;
631     string dstPath = BackupFileUtils::GetFullPathByPrefixType(PrefixType::LOCAL, fileInfo.relativePath);
632     struct stat srcStatInfo {};
633     struct stat dstStatInfo {};
634 
635     if (access(dstPath.c_str(), F_OK)) {
636         return false;
637     }
638     if (stat(srcPath.c_str(), &srcStatInfo) != 0) {
639         MEDIA_ERR_LOG("Failed to get file %{private}s StatInfo, err=%{public}d", srcPath.c_str(), errno);
640         return false;
641     }
642     if (stat(dstPath.c_str(), &dstStatInfo) != 0) {
643         MEDIA_ERR_LOG("Failed to get file %{private}s StatInfo, err=%{public}d", dstPath.c_str(), errno);
644         return false;
645     }
646     if ((srcStatInfo.st_size != dstStatInfo.st_size || srcStatInfo.st_mtime != dstStatInfo.st_mtime) &&
647         !HasSameAudioFile(rdbStore, tableName, fileInfo)) { /* file size & last modify time */
648         MEDIA_INFO_LOG("Size (%{public}lld -> %{public}lld) or mtime (%{public}lld -> %{public}lld) differs",
649             (long long)srcStatInfo.st_size, (long long)dstStatInfo.st_size, (long long)srcStatInfo.st_mtime,
650             (long long)dstStatInfo.st_mtime);
651         return false;
652     }
653     fileInfo.isNew = false;
654     return true;
655 }
656 
HasSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & tableName,FileInfo & fileInfo)657 bool BaseRestore::HasSameAudioFile(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore, const std::string &tableName,
658     FileInfo &fileInfo)
659 {
660     string querySql = "SELECT " + MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + " FROM " +
661         tableName + " WHERE " + MediaColumn::MEDIA_NAME + " = '" + fileInfo.displayName + "' AND " +
662         MediaColumn::MEDIA_SIZE + " = " + to_string(fileInfo.fileSize) + " AND " +
663         MediaColumn::MEDIA_DATE_MODIFIED + " = " + to_string(fileInfo.dateModified);
664     querySql += " LIMIT 1";
665     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(rdbStore, querySql);
666     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
667         return false;
668     }
669     int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
670     string cloudPath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
671     if (fileId <= 0 || cloudPath.empty()) {
672         return false;
673     }
674     fileInfo.fileIdNew = fileId;
675     fileInfo.cloudPath = cloudPath;
676     return true;
677 }
678 
InsertPhotoMap(std::vector<FileInfo> & fileInfos,int64_t & mapRowNum)679 void BaseRestore::InsertPhotoMap(std::vector<FileInfo> &fileInfos, int64_t &mapRowNum)
680 {
681     BatchInsertMap(fileInfos, mapRowNum);
682     migrateDatabaseMapNumber_ += mapRowNum;
683 }
684 
BatchQueryPhoto(vector<FileInfo> & fileInfos,bool isFull,const NeedQueryMap & needQueryMap)685 void BaseRestore::BatchQueryPhoto(vector<FileInfo> &fileInfos, bool isFull, const NeedQueryMap &needQueryMap)
686 {
687     string querySql = "SELECT " + MediaColumn::MEDIA_ID + " , " + MediaColumn::MEDIA_FILE_PATH + " FROM " +
688         PhotoColumn::PHOTOS_TABLE + " WHERE ";
689     bool firstSql = false;
690     std::vector<std::string> cloudPathArgs;
691     for (auto &fileInfo : fileInfos) {
692         if (!isFull && !NeedQuery(fileInfo, needQueryMap)) {
693             continue;
694         }
695         if (firstSql) {
696             querySql += " OR ";
697         } else {
698             firstSql = true;
699         }
700         querySql += MediaColumn::MEDIA_FILE_PATH + " = ? ";
701         cloudPathArgs.push_back(fileInfo.cloudPath);
702     }
703     auto result = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql, cloudPathArgs);
704     if (result == nullptr) {
705         MEDIA_ERR_LOG("Query resultSql is null.");
706         return;
707     }
708     while (result->GoToNextRow() == NativeRdb::E_OK) {
709         int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, result);
710         std::string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, result);
711         auto pathMatch = [path {path}](const auto &fileInfo) {
712             return fileInfo.cloudPath == path;
713         };
714         auto it = std::find_if(fileInfos.begin(), fileInfos.end(), pathMatch);
715         if (it != fileInfos.end() && fileId > 0) {
716             it->fileIdNew = fileId;
717         }
718     }
719 }
720 
BatchInsertMap(const vector<FileInfo> & fileInfos,int64_t & totalRowNum)721 void BaseRestore::BatchInsertMap(const vector<FileInfo> &fileInfos, int64_t &totalRowNum)
722 {
723     vector<NativeRdb::ValuesBucket> values;
724     for (const auto &fileInfo : fileInfos) {
725         if (!fileInfo.packageName.empty()) {
726             // add for trigger insert_photo_insert_source_album
727             continue;
728         }
729         if (fileInfo.cloudPath.empty() || fileInfo.mediaAlbumId <= 0 || fileInfo.fileIdNew <= 0) {
730             MEDIA_ERR_LOG("AlbumMap error file name = %{public}s.", fileInfo.displayName.c_str());
731             continue;
732         }
733         NativeRdb::ValuesBucket value;
734         value.PutInt(PhotoMap::ASSET_ID, fileInfo.fileIdNew);
735         value.PutInt(PhotoMap::ALBUM_ID, fileInfo.mediaAlbumId);
736         values.emplace_back(value);
737     }
738     int64_t rowNum = 0;
739     int32_t errCode = BatchInsertWithRetry(PhotoMap::TABLE, values, rowNum);
740     if (errCode != E_OK) {
741         MEDIA_ERR_LOG("Batch insert map failed, errCode: %{public}d", errCode);
742     }
743     totalRowNum += rowNum;
744 }
745 
StartRestoreEx(const std::string & backupRetoreDir,const std::string & upgradePath,std::string & restoreExInfo)746 void BaseRestore::StartRestoreEx(const std::string &backupRetoreDir, const std::string &upgradePath,
747     std::string &restoreExInfo)
748 {
749     StartRestore(backupRetoreDir, upgradePath);
750     restoreExInfo = GetRestoreExInfo();
751     UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).Report(restoreExInfo);
752 }
753 
GetRestoreExInfo()754 std::string BaseRestore::GetRestoreExInfo()
755 {
756     nlohmann::json restoreExInfoJson;
757     restoreExInfoJson[STAT_KEY_RESULT_INFO] = { GetErrorInfoJson(), GetCountInfoJson(STAT_TYPES) };
758     return restoreExInfoJson.dump();
759 }
760 
GetErrorInfoJson()761 nlohmann::json BaseRestore::GetErrorInfoJson()
762 {
763     int32_t errorCode = errorCode_ == RestoreError::SUCCESS ? STAT_DEFAULT_ERROR_CODE_SUCCESS :
764         STAT_DEFAULT_ERROR_CODE_FAILED;
765     nlohmann::json errorInfoJson = {
766         { STAT_KEY_TYPE, STAT_VALUE_ERROR_INFO },
767         { STAT_KEY_ERROR_CODE, std::to_string(errorCode) },
768         { STAT_KEY_ERROR_INFO, errorInfo_ }
769     };
770     return errorInfoJson;
771 }
772 
GetCountInfoJson(const std::vector<std::string> & countInfoTypes)773 nlohmann::json BaseRestore::GetCountInfoJson(const std::vector<std::string> &countInfoTypes)
774 {
775     nlohmann::json countInfoJson;
776     countInfoJson[STAT_KEY_TYPE] = STAT_VALUE_COUNT_INFO;
777     size_t limit = MAX_FAILED_FILES_LIMIT;
778     for (const auto &type : countInfoTypes) {
779         SubCountInfo subCountInfo = GetSubCountInfo(type);
780         MEDIA_INFO_LOG("SubCountInfo %{public}s success: %{public}lld, duplicate: %{public}lld, failed: %{public}zu",
781             type.c_str(), (long long)subCountInfo.successCount, (long long)subCountInfo.duplicateCount,
782             subCountInfo.failedFiles.size());
783         countInfoJson[STAT_KEY_INFOS].push_back(GetSubCountInfoJson(type, subCountInfo, limit));
784     }
785     return countInfoJson;
786 }
787 
GetSubCountInfo(const std::string & type)788 SubCountInfo BaseRestore::GetSubCountInfo(const std::string &type)
789 {
790     std::unordered_map<std::string, FailedFileInfo> failedFiles = GetFailedFiles(type);
791     if (type == STAT_TYPE_PHOTO) {
792         return SubCountInfo(migrateFileNumber_ - migrateVideoFileNumber_, migratePhotoDuplicateNumber_, failedFiles);
793     }
794     if (type == STAT_TYPE_VIDEO) {
795         return SubCountInfo(migrateVideoFileNumber_, migrateVideoDuplicateNumber_, failedFiles);
796     }
797     return SubCountInfo(migrateAudioFileNumber_, migrateAudioDuplicateNumber_, failedFiles);
798 }
799 
GetFailedFiles(const std::string & type)800 std::unordered_map<std::string, FailedFileInfo> BaseRestore::GetFailedFiles(const std::string &type)
801 {
802     std::lock_guard<mutex> lock(failedFilesMutex_);
803     std::unordered_map<std::string, FailedFileInfo> failedFiles;
804     auto iter = failedFilesMap_.find(type);
805     if (iter != failedFilesMap_.end()) {
806         return iter->second;
807     }
808     return failedFiles;
809 }
810 
GetSubCountInfoJson(const std::string & type,const SubCountInfo & subCountInfo,size_t & limit)811 nlohmann::json BaseRestore::GetSubCountInfoJson(const std::string &type, const SubCountInfo &subCountInfo,
812     size_t &limit)
813 {
814     nlohmann::json subCountInfoJson;
815     subCountInfoJson[STAT_KEY_BACKUP_INFO] = type;
816     subCountInfoJson[STAT_KEY_SUCCESS_COUNT] = subCountInfo.successCount;
817     subCountInfoJson[STAT_KEY_DUPLICATE_COUNT] = subCountInfo.duplicateCount;
818     subCountInfoJson[STAT_KEY_FAILED_COUNT] = subCountInfo.failedFiles.size();
819     // update currentLimit = min(limit, failedFiles.size())
820     size_t currentLimit = limit <= subCountInfo.failedFiles.size() ? limit : subCountInfo.failedFiles.size();
821     std::string detailsPath;
822     std::vector<std::string> failedFilesList;
823     if (sceneCode_ == UPGRADE_RESTORE_ID) {
824         detailsPath = BackupFileUtils::GetDetailsPath(sceneCode_, type, subCountInfo.failedFiles, currentLimit);
825         subCountInfoJson[STAT_KEY_DETAILS] = detailsPath;
826     } else {
827         failedFilesList = BackupFileUtils::GetFailedFilesList(sceneCode_, subCountInfo.failedFiles, currentLimit);
828         subCountInfoJson[STAT_KEY_DETAILS] = failedFilesList;
829     }
830     MEDIA_INFO_LOG("Get %{public}s details size: %{public}zu", type.c_str(), currentLimit);
831     limit -= currentLimit; // update total limit
832     return subCountInfoJson;
833 }
834 
GetBackupInfo()835 std::string BaseRestore::GetBackupInfo()
836 {
837     return "";
838 }
839 
SetErrorCode(int32_t errorCode)840 void BaseRestore::SetErrorCode(int32_t errorCode)
841 {
842     errorCode_ = errorCode;
843     auto iter = RESTORE_ERROR_MAP.find(errorCode_);
844     if (iter == RESTORE_ERROR_MAP.end()) {
845         errorInfo_ = "";
846         return;
847     }
848     errorInfo_ = iter->second;
849 }
850 
UpdateFailedFileByFileType(int32_t fileType,const FileInfo & fileInfo,int32_t errorCode)851 void BaseRestore::UpdateFailedFileByFileType(int32_t fileType, const FileInfo &fileInfo, int32_t errorCode)
852 {
853     std::lock_guard<mutex> lock(failedFilesMutex_);
854     FailedFileInfo failedFileInfo(sceneCode_, fileInfo, errorCode);
855     if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE)) {
856         failedFilesMap_[STAT_TYPE_PHOTO].emplace(fileInfo.oldPath, failedFileInfo);
857         return;
858     }
859     if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
860         failedFilesMap_[STAT_TYPE_VIDEO].emplace(fileInfo.oldPath, failedFileInfo);
861         return;
862     }
863     if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_AUDIO)) {
864         failedFilesMap_[STAT_TYPE_AUDIO].emplace(fileInfo.oldPath, failedFileInfo);
865         return;
866     }
867     MEDIA_ERR_LOG("Unsupported file type: %{public}d", fileType);
868 }
869 
UpdateFailedFiles(int32_t fileType,const FileInfo & fileInfo,int32_t errorCode)870 void BaseRestore::UpdateFailedFiles(int32_t fileType, const FileInfo &fileInfo, int32_t errorCode)
871 {
872     SetErrorCode(errorCode);
873     UpdateFailedFileByFileType(fileType, fileInfo, errorCode);
874 }
875 
UpdateFailedFiles(const std::vector<FileInfo> & fileInfos,int32_t errorCode)876 void BaseRestore::UpdateFailedFiles(const std::vector<FileInfo> &fileInfos, int32_t errorCode)
877 {
878     SetErrorCode(errorCode);
879     for (const auto &fileInfo : fileInfos) {
880         UpdateFailedFileByFileType(fileInfo.fileType, fileInfo, errorCode);
881     }
882 }
883 
UpdateDuplicateNumber(int32_t fileType)884 void BaseRestore::UpdateDuplicateNumber(int32_t fileType)
885 {
886     if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE)) {
887         migratePhotoDuplicateNumber_++;
888         return;
889     }
890     if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
891         migrateVideoDuplicateNumber_++;
892         return;
893     }
894     if (fileType == static_cast<int32_t>(MediaType::MEDIA_TYPE_AUDIO)) {
895         migrateAudioDuplicateNumber_++;
896         return;
897     }
898     MEDIA_ERR_LOG("Unsupported file type: %{public}d", fileType);
899 }
900 
SetParameterForClone()901 void BaseRestore::SetParameterForClone()
902 {
903     auto currentTime = to_string(MediaFileUtils::UTCTimeSeconds());
904     MEDIA_INFO_LOG("SetParameterForClone currentTime:%{public}s", currentTime.c_str());
905     bool retFlag = system::SetParameter(CLONE_FLAG, currentTime);
906     if (!retFlag) {
907         MEDIA_ERR_LOG("Failed to set parameter cloneFlag, retFlag:%{public}d", retFlag);
908     }
909 }
910 
StopParameterForClone(int32_t sceneCode)911 void BaseRestore::StopParameterForClone(int32_t sceneCode)
912 {
913     bool retFlag = system::SetParameter(CLONE_FLAG, "0");
914     if (!retFlag) {
915         MEDIA_ERR_LOG("Failed to set parameter cloneFlag, retFlag:%{public}d", retFlag);
916     }
917 }
918 
InsertPhotoRelated(std::vector<FileInfo> & fileInfos,int32_t sourceType)919 void BaseRestore::InsertPhotoRelated(std::vector<FileInfo> &fileInfos, int32_t sourceType)
920 {
921     if (sourceType != SourceType::GALLERY) {
922         return;
923     }
924     NeedQueryMap needQueryMap;
925     if (!NeedBatchQueryPhoto(fileInfos, needQueryMap)) {
926         MEDIA_INFO_LOG("There is no need to batch query photo");
927         return;
928     }
929     int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
930     BatchQueryPhoto(fileInfos, false, needQueryMap);
931     int64_t startInsertMap = MediaFileUtils::UTCTimeMilliSeconds();
932     int64_t mapRowNum = 0;
933     InsertPhotoMap(fileInfos, mapRowNum);
934     int64_t startInsertPortrait = MediaFileUtils::UTCTimeMilliSeconds();
935     int64_t faceRowNum = 0;
936     int64_t portraitMapRowNum = 0;
937     int64_t portraitPhotoNum = 0;
938     InsertFaceAnalysisData(fileInfos, needQueryMap, faceRowNum, portraitMapRowNum, portraitPhotoNum);
939     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
940     MEDIA_INFO_LOG("query cost %{public}ld, insert %{public}ld maps cost %{public}ld, insert face analysis data of "
941         "%{public}ld photos (%{public}ld faces + %{public}ld maps) cost %{public}ld",
942         (long)(startInsertMap - startQuery), (long)mapRowNum, (long)(startInsertPortrait - startInsertMap),
943         (long)portraitPhotoNum, (long)faceRowNum, (long)portraitMapRowNum, (long)(end - startInsertPortrait));
944 }
945 
NeedBatchQueryPhoto(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)946 bool BaseRestore::NeedBatchQueryPhoto(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
947 {
948     return NeedBatchQueryPhotoForPhotoMap(fileInfos, needQueryMap) ||
949         NeedBatchQueryPhotoForPortrait(fileInfos, needQueryMap);
950 }
951 
NeedBatchQueryPhotoForPhotoMap(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)952 bool BaseRestore::NeedBatchQueryPhotoForPhotoMap(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
953 {
954     std::unordered_set<std::string> needQuerySet;
955     for (const auto &fileInfo : fileInfos) {
956         if (!fileInfo.packageName.empty()) {
957             continue;
958         }
959         if (fileInfo.cloudPath.empty() || fileInfo.mediaAlbumId <= 0) {
960             MEDIA_ERR_LOG("Album error file name = %{public}s.", fileInfo.displayName.c_str());
961             continue;
962         }
963         needQuerySet.insert(fileInfo.cloudPath);
964     }
965     if (needQuerySet.empty()) {
966         return false;
967     }
968     needQueryMap[PhotoRelatedType::PHOTO_MAP] = needQuerySet;
969     return true;
970 }
971 
NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)972 bool BaseRestore::NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
973 {
974     return false;
975 }
976 
NeedQuery(const FileInfo & fileInfo,const NeedQueryMap & needQueryMap)977 bool BaseRestore::NeedQuery(const FileInfo &fileInfo, const NeedQueryMap &needQueryMap)
978 {
979     for (auto iter = needQueryMap.begin(); iter != needQueryMap.end(); ++iter) {
980         if (NeedQueryByPhotoRelatedType(fileInfo, iter->first, iter->second)) {
981             return true;
982         }
983     }
984     return false;
985 }
986 
NeedQueryByPhotoRelatedType(const FileInfo & fileInfo,PhotoRelatedType photoRelatedType,const std::unordered_set<std::string> & needQuerySet)987 bool BaseRestore::NeedQueryByPhotoRelatedType(const FileInfo &fileInfo, PhotoRelatedType photoRelatedType,
988     const std::unordered_set<std::string> &needQuerySet)
989 {
990     std::string searchPath;
991     switch (photoRelatedType) {
992         case PhotoRelatedType::PHOTO_MAP: {
993             searchPath = fileInfo.cloudPath;
994             break;
995         }
996         case PhotoRelatedType::PORTRAIT: {
997             searchPath = fileInfo.hashCode;
998             break;
999         }
1000         default:
1001             MEDIA_ERR_LOG("Unsupported photo related type: %{public}d", static_cast<int32_t>(photoRelatedType));
1002     }
1003     return !searchPath.empty() && needQuerySet.count(searchPath) > 0;
1004 }
1005 
InsertFaceAnalysisData(const std::vector<FileInfo> & fileInfos,const NeedQueryMap & needQueryMap,int64_t & faceRowNum,int64_t & mapRowNum,int64_t & photoNum)1006 void BaseRestore::InsertFaceAnalysisData(const std::vector<FileInfo> &fileInfos, const NeedQueryMap &needQueryMap,
1007     int64_t &faceRowNum, int64_t &mapRowNum, int64_t &photoNum)
1008 {
1009     return;
1010 }
1011 
ReportPortraitStat(int32_t sceneCode)1012 void BaseRestore::ReportPortraitStat(int32_t sceneCode)
1013 {
1014     MEDIA_INFO_LOG("PortraitStat: album %{public}zu, photo %{public}lld, face %{public}lld, cost %{public}lld",
1015         portraitAlbumIdMap_.size(), (long long)migratePortraitPhotoNumber_, (long long)migratePortraitFaceNumber_,
1016         (long long)migratePortraitTotalTimeCost_);
1017     BackupDfxUtils::PostPortraitStat(static_cast<uint32_t>(portraitAlbumIdMap_.size()), migratePortraitPhotoNumber_,
1018         migratePortraitFaceNumber_, migratePortraitTotalTimeCost_);
1019 }
1020 
GetUniqueId(int32_t fileType)1021 int32_t BaseRestore::GetUniqueId(int32_t fileType)
1022 {
1023     int32_t uniqueId = -1;
1024     switch (fileType) {
1025         case MediaType::MEDIA_TYPE_IMAGE: {
1026             lock_guard<mutex> lock(imageMutex_);
1027             uniqueId = static_cast<int32_t>(imageNumber_);
1028             imageNumber_++;
1029             break;
1030         }
1031         case MediaType::MEDIA_TYPE_VIDEO: {
1032             lock_guard<mutex> lock(videoMutex_);
1033             uniqueId = static_cast<int32_t>(videoNumber_);
1034             videoNumber_++;
1035             break;
1036         }
1037         case MediaType::MEDIA_TYPE_AUDIO: {
1038             lock_guard<mutex> lock(audioMutex_);
1039             uniqueId = static_cast<int32_t>(audioNumber_);
1040             audioNumber_++;
1041             break;
1042         }
1043         default:
1044             MEDIA_ERR_LOG("Unsupported file type: %{public}d", fileType);
1045     }
1046     return uniqueId;
1047 }
1048 
GetProgressInfo()1049 std::string BaseRestore::GetProgressInfo()
1050 {
1051     nlohmann::json progressInfoJson;
1052     for (const auto &type : STAT_PROGRESS_TYPES) {
1053         SubProcessInfo subProcessInfo = GetSubProcessInfo(type);
1054         progressInfoJson[STAT_KEY_PROGRESS_INFO].push_back(GetSubProcessInfoJson(type, subProcessInfo));
1055     }
1056     return progressInfoJson.dump();
1057 }
1058 
GetSubProcessInfo(const std::string & type)1059 SubProcessInfo BaseRestore::GetSubProcessInfo(const std::string &type)
1060 {
1061     uint64_t success = 0;
1062     uint64_t duplicate = 0;
1063     uint64_t failed = 0;
1064     uint64_t total = 0;
1065     if (type == STAT_TYPE_PHOTO_VIDEO) {
1066         success = migrateFileNumber_;
1067         duplicate = migratePhotoDuplicateNumber_ + migrateVideoDuplicateNumber_;
1068         failed = static_cast<uint64_t>(GetFailedFiles(STAT_TYPE_PHOTO).size() + GetFailedFiles(STAT_TYPE_VIDEO).size());
1069         total = totalNumber_;
1070     } else if (type == STAT_TYPE_AUDIO) {
1071         success = migrateAudioFileNumber_;
1072         duplicate = migrateAudioDuplicateNumber_;
1073         failed = static_cast<uint64_t>(GetFailedFiles(type).size());
1074         total = audioTotalNumber_;
1075     } else if (type == STAT_TYPE_UPDATE) {
1076         UpdateProcessedNumber(updateProcessStatus_, updateProcessedNumber_, updateTotalNumber_);
1077         success = updateProcessedNumber_;
1078         total = updateTotalNumber_;
1079     } else if (type == STAT_TYPE_OTHER) {
1080         UpdateProcessedNumber(otherProcessStatus_, otherProcessedNumber_, otherTotalNumber_);
1081         success = otherProcessedNumber_;
1082         total = otherTotalNumber_;
1083     } else {
1084         ongoingTotalNumber_++;
1085         success = ongoingTotalNumber_;
1086         total = ongoingTotalNumber_; // make sure progressInfo changes as process goes on
1087     }
1088     uint64_t processed = success + duplicate + failed;
1089     return SubProcessInfo(processed, total);
1090 }
1091 
UpdateProcessedNumber(const std::atomic<int32_t> & processStatus,std::atomic<uint64_t> & processedNumber,const std::atomic<uint64_t> & totalNumber)1092 void BaseRestore::UpdateProcessedNumber(const std::atomic<int32_t> &processStatus,
1093     std::atomic<uint64_t> &processedNumber, const std::atomic<uint64_t> &totalNumber)
1094 {
1095     if (processStatus == ProcessStatus::STOP) {
1096         processedNumber = totalNumber.load();
1097         return;
1098     }
1099     processedNumber += processedNumber < totalNumber ? 1 : 0;
1100 }
1101 
GetSubProcessInfoJson(const std::string & type,const SubProcessInfo & subProcessInfo)1102 nlohmann::json BaseRestore::GetSubProcessInfoJson(const std::string &type, const SubProcessInfo &subProcessInfo)
1103 {
1104     nlohmann::json subProcessInfoJson;
1105     subProcessInfoJson[STAT_KEY_NAME] = type;
1106     subProcessInfoJson[STAT_KEY_PROCESSED] = subProcessInfo.processed;
1107     subProcessInfoJson[STAT_KEY_TOTAL] = subProcessInfo.total;
1108     subProcessInfoJson[STAT_KEY_IS_PERCENTAGE] = false;
1109     return subProcessInfoJson;
1110 }
1111 
UpdateDatabase()1112 void BaseRestore::UpdateDatabase()
1113 {
1114     updateProcessStatus_ = ProcessStatus::START;
1115     GetUpdateTotalCount();
1116     MEDIA_INFO_LOG("Start update all albums");
1117     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1118     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore);
1119     MEDIA_INFO_LOG("Start update unique number");
1120     BackupDatabaseUtils::UpdateUniqueNumber(mediaLibraryRdb_, imageNumber_, IMAGE_ASSET_TYPE);
1121     BackupDatabaseUtils::UpdateUniqueNumber(mediaLibraryRdb_, videoNumber_, VIDEO_ASSET_TYPE);
1122     BackupDatabaseUtils::UpdateUniqueNumber(mediaLibraryRdb_, audioNumber_, AUDIO_ASSET_TYPE);
1123     MEDIA_INFO_LOG("Start notify");
1124     NotifyAlbum();
1125     updateProcessStatus_ = ProcessStatus::STOP;
1126 }
1127 
NotifyAlbum()1128 void BaseRestore::NotifyAlbum()
1129 {
1130     auto watch = MediaLibraryNotify::GetInstance();
1131     if (watch == nullptr) {
1132         MEDIA_ERR_LOG("Can not get MediaLibraryNotify Instance");
1133         return;
1134     }
1135     watch->Notify(PhotoColumn::DEFAULT_PHOTO_URI, NotifyType::NOTIFY_ADD);
1136 }
1137 
GetUpdateTotalCount()1138 void BaseRestore::GetUpdateTotalCount()
1139 {
1140     GetUpdateAllAlbumsCount();
1141     GetUpdateUniqueNumberCount();
1142 }
1143 
GetUpdateAllAlbumsCount()1144 void BaseRestore::GetUpdateAllAlbumsCount()
1145 {
1146     const std::vector<std::string> ALBUM_TABLE_LIST = { "PhotoAlbum", "AnalysisAlbum" };
1147     int32_t albumTotalCount = 0;
1148     for (const auto &tableName : ALBUM_TABLE_LIST) {
1149         std::string querySql = "SELECT count(1) as count FROM " + tableName;
1150         albumTotalCount += BackupDatabaseUtils::QueryInt(mediaLibraryRdb_, querySql, CUSTOM_COUNT);
1151     }
1152     updateTotalNumber_ += static_cast<uint64_t>(albumTotalCount);
1153     MEDIA_INFO_LOG("onProcess Update updateTotalNumber_: %{public}lld", (long long)updateTotalNumber_);
1154 }
1155 
GetUpdateUniqueNumberCount()1156 void BaseRestore::GetUpdateUniqueNumberCount()
1157 {
1158     updateTotalNumber_ += UNIQUE_NUMBER_NUM;
1159     MEDIA_INFO_LOG("onProcess Update updateTotalNumber_: %{public}lld", (long long)updateTotalNumber_);
1160 }
1161 
RestoreThumbnail()1162 void BaseRestore::RestoreThumbnail()
1163 {
1164     // restore thumbnail for date fronted 500 photos
1165     MEDIA_INFO_LOG("Start RestoreThumbnail");
1166     otherProcessStatus_ = ProcessStatus::START;
1167     otherTotalNumber_ += THUMBNAIL_NUM;
1168     MEDIA_INFO_LOG("onProcess Update otherTotalNumber_: %{public}lld", (long long)otherTotalNumber_);
1169     BackupFileUtils::GenerateThumbnailsAfterRestore();
1170     otherProcessStatus_ = ProcessStatus::STOP;
1171 }
1172 } // namespace Media
1173 } // namespace OHOS
1174