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