1 /*
2 * Copyright (C) 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 "MediaLibraryOthersCloneRestore"
17
18 #include "others_clone_restore.h"
19
20 #include <securec.h>
21 #include <dirent.h>
22
23 #include "album_plugin_config.h"
24 #include "backup_database_utils.h"
25 #include "backup_file_utils.h"
26 #include "datashare_abs_result_set.h"
27 #include "directory_ex.h"
28 #include "ffrt.h"
29 #include "ffrt_inner.h"
30 #include "medialibrary_db_const.h"
31 #include "medialibrary_errno.h"
32 #include "media_file_utils.h"
33 #include "media_file_uri.h"
34 #include "media_log.h"
35 #include "media_scanner.h"
36 #include "medialibrary_rdb_transaction.h"
37
38 namespace OHOS {
39 namespace Media {
40 const int PHONE_FIRST_NUMBER = 105;
41 const int PHONE_SECOND_NUMBER = 80;
42 const int PHONE_THIRD_NUMBER = 104;
43 const int PHONE_FOURTH_NUMBER = 111;
44 const int PHONE_FIFTH_NUMBER = 110;
45 const int PHONE_SIXTH_NUMBER = 101;
46 const int QUERY_NUMBER = 200;
47 constexpr int32_t MAX_CLONE_THREAD_NUM = 2;
48 constexpr int64_t SECONDS_LEVEL_LIMIT = 1e10;
49 const std::string I_PHONE_LPATH = "/Pictures/";
50 const std::string PHONE_TYPE = "type";
51 const std::string PHONE_DEVICE_TYPE = "deviceType";
52 const std::string PHONE_DETAIL = "detail";
53 const std::string PHOTO_DB_NAME = "photo_MediaInfo.db";
54 const std::string VIDEO_DB_NAME = "video_MediaInfo.db";
55 const std::string OTHER_CLONE_FILE_ROOT_PATH = "/storage/media/local/files/.backup/restore";
56 const std::string OTHER_CLONE_DB_PATH = "/storage/media/local/files/.backup/restore/storage/emulated/0/";
57 const std::string OTHER_CLONE_FILE_PATH = "/storage/media/local/files/.backup/restore/storage/emulated/";
58 const std::string OTHER_CLONE_DISPLAYNAME = "primaryStr";
59 const std::string OTHER_CLONE_DATA = "_data";
60 const std::string OTHER_CLONE_MODIFIED = "date_modified";
61 const std::string OTHER_CLONE_TAKEN = "datetaken";
62 const std::string OTHER_MUSIC_ROOT_PATH = "/storage/emulated/0/";
63
GetPhoneName()64 static std::string GetPhoneName()
65 {
66 int arr[] = { PHONE_FIRST_NUMBER, PHONE_SECOND_NUMBER, PHONE_THIRD_NUMBER, PHONE_FOURTH_NUMBER, PHONE_FIFTH_NUMBER,
67 PHONE_SIXTH_NUMBER };
68 int len = sizeof(arr) / sizeof(arr[0]);
69 std::string phoneName = "";
70 for (int i = 0; i < len; i++) {
71 phoneName += static_cast<char>(arr[i]);
72 }
73 return phoneName;
74 }
75
OthersCloneRestore(int32_t sceneCode,const std::string & mediaAppName,const std::string & bundleInfo)76 OthersCloneRestore::OthersCloneRestore(int32_t sceneCode, const std::string &mediaAppName,
77 const std::string &bundleInfo)
78 {
79 sceneCode_ = sceneCode;
80 mediaAppName_ = mediaAppName;
81 if (sceneCode_ == I_PHONE_CLONE_RESTORE) {
82 nlohmann::json jsonObj = nlohmann::json::parse(bundleInfo, nullptr, false);
83 if (jsonObj.is_discarded()) {
84 MEDIA_ERR_LOG("parse json failed");
85 clonePhoneName_ = GetPhoneName();
86 return;
87 }
88 for (auto &obj : jsonObj) {
89 if (obj.contains(PHONE_TYPE) && obj.at(PHONE_TYPE) == PHONE_DEVICE_TYPE) {
90 clonePhoneName_ = obj.at(PHONE_DETAIL);
91 }
92 }
93 if (clonePhoneName_.empty()) {
94 MEDIA_ERR_LOG("read json error");
95 clonePhoneName_ = GetPhoneName();
96 }
97 }
98 }
99
CloneInfoPushBack(std::vector<CloneDbInfo> & pushInfos,std::vector<CloneDbInfo> & popInfos)100 void OthersCloneRestore::CloneInfoPushBack(std::vector<CloneDbInfo> &pushInfos, std::vector<CloneDbInfo> &popInfos)
101 {
102 std::lock_guard<std::mutex> guard(cloneMutex_);
103 for (auto &info : popInfos) {
104 pushInfos.push_back(info);
105 }
106 }
107
HandleSelectBatch(std::shared_ptr<NativeRdb::RdbStore> mediaRdb,int32_t offset,int32_t sceneCode,std::vector<CloneDbInfo> & mediaDbInfo)108 void OthersCloneRestore::HandleSelectBatch(std::shared_ptr<NativeRdb::RdbStore> mediaRdb, int32_t offset,
109 int32_t sceneCode, std::vector<CloneDbInfo> &mediaDbInfo)
110 {
111 MEDIA_INFO_LOG("start handle clone batch, offset: %{public}d", offset);
112 if (mediaRdb == nullptr) {
113 MEDIA_ERR_LOG("rdb is nullptr, Maybe init failed.");
114 return;
115 }
116 std::string queryExternalMayClonePhoto;
117 if (sceneCode == I_PHONE_CLONE_RESTORE) {
118 queryExternalMayClonePhoto = "SELECT primaryStr, date_modified, datetaken FROM mediainfo LIMIT " +
119 std::to_string(offset) + ", " + std::to_string(QUERY_NUMBER);
120 } else {
121 queryExternalMayClonePhoto = "SELECT _data, date_modified, datetaken FROM mediainfo LIMIT " +
122 std::to_string(offset) + ", " + std::to_string(QUERY_NUMBER);
123 }
124 auto resultSet = mediaRdb->QuerySql(queryExternalMayClonePhoto);
125 if (resultSet == nullptr) {
126 MEDIA_ERR_LOG("Query resultSql is null.");
127 return;
128 }
129 std::vector<CloneDbInfo> infos;
130 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
131 CloneDbInfo tmpDbInfo;
132 if (sceneCode == I_PHONE_CLONE_RESTORE) {
133 tmpDbInfo.displayName = GetStringVal(OTHER_CLONE_DISPLAYNAME, resultSet);
134 tmpDbInfo.dateModified = GetDoubleVal(OTHER_CLONE_MODIFIED, resultSet);
135 tmpDbInfo.dateTaken = GetDoubleVal(OTHER_CLONE_TAKEN, resultSet);
136 } else {
137 tmpDbInfo.data = GetStringVal(OTHER_CLONE_DATA, resultSet);
138 tmpDbInfo.dateModified = static_cast<double>(GetInt64Val(OTHER_CLONE_MODIFIED, resultSet));
139 tmpDbInfo.dateTaken = static_cast<double>(GetInt64Val(OTHER_CLONE_TAKEN, resultSet));
140 }
141 infos.push_back(tmpDbInfo);
142 };
143 CloneInfoPushBack(mediaDbInfo, infos);
144 }
145
GetCloneDbInfos(const std::string & dbName,std::vector<CloneDbInfo> & mediaDbInfo)146 void OthersCloneRestore::GetCloneDbInfos(const std::string &dbName, std::vector<CloneDbInfo> &mediaDbInfo)
147 {
148 std::string dbPath = OTHER_CLONE_DB_PATH + dbName;
149 if (access(dbPath.c_str(), F_OK) != 0) {
150 MEDIA_ERR_LOG("Init rdb not exists, dbName = %{public}s", dbName.c_str());
151 return;
152 }
153 std::shared_ptr<NativeRdb::RdbStore> mediaRdb;
154 int32_t initErr = BackupDatabaseUtils::InitDb(mediaRdb, dbName, dbPath, mediaAppName_, false);
155 if (mediaRdb == nullptr) {
156 MEDIA_ERR_LOG("Init rdb fail, dbName = %{public}s, err = %{public}d", dbName.c_str(), initErr);
157 return;
158 }
159
160 std::string selectTotalCloneMediaNumber = "SELECT count(1) AS count FROM mediainfo";
161 int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb, selectTotalCloneMediaNumber, CUSTOM_COUNT);
162 MEDIA_INFO_LOG("dbName = %{public}s, totalNumber = %{public}d", dbName.c_str(), totalNumber);
163 ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_CLONE_THREAD_NUM);
164 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_NUMBER) {
165 ffrt::submit([this, mediaRdb, offset, &mediaDbInfo]() {
166 HandleSelectBatch(mediaRdb, offset, sceneCode_, mediaDbInfo);
167 }, { &offset }, {}, ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
168 }
169 ffrt::wait();
170 }
171
Init(const std::string & backupRetoreDir,const std::string & upgradeFilePath,bool isUpgrade)172 int32_t OthersCloneRestore::Init(const std::string &backupRetoreDir, const std::string &upgradeFilePath, bool isUpgrade)
173 {
174 if (BaseRestore::Init() != E_OK) {
175 MEDIA_ERR_LOG("GetBackupInfo init failed");
176 return E_FAIL;
177 }
178 if (mediaLibraryRdb_ == nullptr) {
179 MEDIA_ERR_LOG("GetBackupInfo Rdbstore is null");
180 return E_FAIL;
181 }
182 int64_t startGetInfo = MediaFileUtils::UTCTimeMilliSeconds();
183 GetCloneDbInfos(AUDIO_DB_NAME, audioDbInfo_);
184 GetCloneDbInfos(PHOTO_DB_NAME, photoDbInfo_);
185 GetCloneDbInfos(VIDEO_DB_NAME, photoDbInfo_);
186 int64_t startCurrent = MediaFileUtils::UTCTimeMilliSeconds();
187 int32_t err = GetAllfilesInCurrentDir(backupRestoreDir_);
188 if (err != E_OK) {
189 MEDIA_ERR_LOG("get all files err %{public}d", err);
190 return err;
191 }
192 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
193 MEDIA_INFO_LOG("GetCloneDb cost %{public}ld, recursively getting all files cost %{public}ld, phonesize:%{public}d, \
194 audiosize:%{public}d", (long)(startCurrent - startGetInfo), (long)(end - startCurrent),
195 (int)photoInfos_.size(), (int)audioInfos_.size());
196 this->photoAlbumDao_.SetMediaLibraryRdb(this->mediaLibraryRdb_);
197 this->photosRestore_.OnStart(this->mediaLibraryRdb_, nullptr);
198 MEDIA_INFO_LOG("Init end");
199 return E_OK;
200 }
201
GetInsertValue(const FileInfo & fileInfo,const std::string & newPath,int32_t sourceType)202 NativeRdb::ValuesBucket OthersCloneRestore::GetInsertValue(const FileInfo &fileInfo, const std::string &newPath,
203 int32_t sourceType)
204 {
205 NativeRdb::ValuesBucket values;
206 values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
207 values.PutString(MediaColumn::MEDIA_TITLE, fileInfo.title);
208 values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
209 // use owner_album_id to mark the album id which the photo is in.
210 values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, fileInfo.ownerAlbumId);
211 // only SOURCE album has package_name and owner_package.
212 values.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileInfo.packageName);
213 values.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileInfo.bundleName);
214 if (fileInfo.dateTaken != 0) {
215 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, fileInfo.dateTaken);
216 values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateTaken);
217 }
218 if (fileInfo.dateModified != 0) {
219 values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, fileInfo.dateModified);
220 }
221 return values;
222 }
223
ParseSourcePathToPath(const std::string & sourcePath,const std::string & prefix)224 static std::string ParseSourcePathToPath(const std::string &sourcePath, const std::string &prefix)
225 {
226 size_t startPos = sourcePath.find(prefix);
227 std::string result = sourcePath;
228 if (startPos != std::string::npos) {
229 startPos += prefix.length();
230 result = sourcePath.substr(startPos, sourcePath.size() - startPos);
231 }
232 return result;
233 }
234
SetFileInfosInCurrentDir(const std::string & file,struct stat & statInfo)235 void OthersCloneRestore::SetFileInfosInCurrentDir(const std::string &file, struct stat &statInfo)
236 {
237 FileInfo tmpInfo;
238 tmpInfo.filePath = file;
239 tmpInfo.displayName = ExtractFileName(file);
240 tmpInfo.title = BackupFileUtils::GetFileTitle(tmpInfo.displayName);
241 tmpInfo.fileType = MediaFileUtils::GetMediaType(tmpInfo.displayName);
242 tmpInfo.fileSize = statInfo.st_size;
243 tmpInfo.dateModified = MediaFileUtils::Timespec2Millisecond(statInfo.st_mtim);
244 if (tmpInfo.fileType == MediaType::MEDIA_TYPE_IMAGE || tmpInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
245 UpDateFileModifiedTime(tmpInfo);
246 photoInfos_.emplace_back(tmpInfo);
247 } else if (tmpInfo.fileType == MediaType::MEDIA_TYPE_AUDIO) {
248 UpDateFileModifiedTime(tmpInfo);
249 tmpInfo.relativePath = ParseSourcePathToPath(tmpInfo.filePath, OTHER_MUSIC_ROOT_PATH);
250 if (tmpInfo.relativePath == tmpInfo.filePath) {
251 tmpInfo.relativePath = ParseSourcePathToPath(tmpInfo.filePath, OTHER_CLONE_FILE_ROOT_PATH);
252 }
253 audioInfos_.emplace_back(tmpInfo);
254 } else {
255 tmpInfo.fileType = MediaFileUtils::GetMediaTypeNotSupported(tmpInfo.displayName);
256 if (tmpInfo.fileType == MediaType::MEDIA_TYPE_IMAGE || tmpInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
257 UpDateFileModifiedTime(tmpInfo);
258 photoInfos_.emplace_back(tmpInfo);
259 MEDIA_WARN_LOG("Not supported media %{public}s", BackupFileUtils::GarbleFilePath(file, sceneCode_).c_str());
260 } else {
261 MEDIA_WARN_LOG("Not supported file %{public}s", BackupFileUtils::GarbleFilePath(file, sceneCode_).c_str());
262 }
263 }
264 }
265
UpDateFileModifiedTime(FileInfo & fileInfo)266 void OthersCloneRestore::UpDateFileModifiedTime(FileInfo &fileInfo)
267 {
268 auto pathMatch = [displayName {fileInfo.displayName}, filePath {fileInfo.filePath},
269 sceneCode {sceneCode_}](const auto &info) {
270 if (sceneCode == I_PHONE_CLONE_RESTORE) {
271 return info.displayName == displayName;
272 } else {
273 return info.data == ParseSourcePathToPath(filePath, OTHER_CLONE_FILE_ROOT_PATH);
274 }
275 };
276 CloneDbInfo info;
277 if (fileInfo.fileType == MediaType::MEDIA_TYPE_AUDIO) {
278 auto it = std::find_if(audioDbInfo_.begin(), audioDbInfo_.end(), pathMatch);
279 if (it != audioDbInfo_.end()) {
280 info.dateModified = it->dateModified;
281 info.dateTaken = it->dateTaken;
282 } else {
283 return;
284 }
285 } else if (fileInfo.fileType == MediaType::MEDIA_TYPE_IMAGE || fileInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
286 auto it = std::find_if(photoDbInfo_.begin(), photoDbInfo_.end(), pathMatch);
287 if (it != photoDbInfo_.end()) {
288 info.dateModified = it->dateModified;
289 info.dateTaken = it->dateTaken;
290 } else {
291 auto it = std::find_if(audioDbInfo_.begin(), audioDbInfo_.end(), pathMatch);
292 if (it != audioDbInfo_.end()) {
293 MEDIA_WARN_LOG("find video in audio info map %{public}s", fileInfo.displayName.c_str());
294 info.dateModified = it->dateModified;
295 info.dateTaken = it->dateTaken;
296 }
297 }
298 } else {
299 MEDIA_WARN_LOG("Not supported file %{public}s", fileInfo.displayName.c_str());
300 return;
301 }
302 if (info.dateModified < SECONDS_LEVEL_LIMIT) {
303 info.dateModified = info.dateModified * static_cast<double>(MSEC_TO_SEC);
304 }
305 if (info.dateTaken < SECONDS_LEVEL_LIMIT) {
306 info.dateTaken = info.dateTaken * static_cast<double>(MSEC_TO_SEC);
307 }
308 fileInfo.dateModified = static_cast<int64_t>(info.dateModified);
309 fileInfo.dateTaken = static_cast<int64_t>(info.dateTaken);
310 BackupFileUtils::ModifyFile(fileInfo.filePath, fileInfo.dateModified / MSEC_TO_SEC);
311 }
312
GetAllfilesInCurrentDir(const std::string & path)313 int32_t OthersCloneRestore::GetAllfilesInCurrentDir(const std::string &path)
314 {
315 int err = E_OK;
316 DIR *dirPath = nullptr;
317 struct dirent *currentFile = nullptr;
318 size_t len = path.length();
319 struct stat statInfo;
320
321 if (len >= FILENAME_MAX - 1) {
322 return ERR_INCORRECT_PATH;
323 }
324 auto fName = (char *)calloc(FILENAME_MAX, sizeof(char));
325 if (fName == nullptr) {
326 return ERR_MEM_ALLOC_FAIL;
327 }
328 if (strcpy_s(fName, FILENAME_MAX, path.c_str()) != ERR_SUCCESS) {
329 FREE_MEMORY_AND_SET_NULL(fName);
330 return ERR_MEM_ALLOC_FAIL;
331 }
332 fName[len++] = '/';
333 if ((dirPath = opendir(path.c_str())) == nullptr) {
334 FREE_MEMORY_AND_SET_NULL(fName);
335 MEDIA_ERR_LOG("Failed to opendir %{private}s, errno %{private}d", path.c_str(), errno);
336 return ERR_NOT_ACCESSIBLE;
337 }
338
339 while ((currentFile = readdir(dirPath)) != nullptr) {
340 if (!strcmp(currentFile->d_name, ".") || !strcmp(currentFile->d_name, "..")) {
341 continue;
342 }
343 if (strncpy_s(fName + len, FILENAME_MAX - len, currentFile->d_name, FILENAME_MAX - len)) {
344 MEDIA_ERR_LOG("Failed to copy file name %{private}s ", fName);
345 continue;
346 }
347 if (lstat(fName, &statInfo) == -1) {
348 MEDIA_ERR_LOG("Failed to get info of directory %{private}s ", fName);
349 continue;
350 }
351 std::string currentPath = fName;
352 if (S_ISDIR(statInfo.st_mode)) {
353 (void)GetAllfilesInCurrentDir(currentPath);
354 } else if (S_ISREG(statInfo.st_mode)) {
355 SetFileInfosInCurrentDir(fName, statInfo);
356 } else {
357 MEDIA_INFO_LOG("Not directory or regular file, name is %{private}s", fName);
358 }
359 }
360 closedir(dirPath);
361 dirPath = nullptr;
362 FREE_MEMORY_AND_SET_NULL(fName);
363 return err;
364 }
365
HandleInsertBatch(int32_t offset)366 void OthersCloneRestore::HandleInsertBatch(int32_t offset)
367 {
368 int32_t totalNumber = std::min(static_cast<int32_t>(photoInfos_.size()),
369 static_cast<int32_t>(offset + QUERY_NUMBER));
370 vector<FileInfo> insertInfos;
371 for (offset; offset < totalNumber; offset++) {
372 FileInfo info = photoInfos_[offset];
373 if (info.fileType != MediaType::MEDIA_TYPE_IMAGE && info.fileType != MediaType::MEDIA_TYPE_VIDEO) {
374 MEDIA_WARN_LOG("photo info error : %{public}s", info.displayName.c_str());
375 continue;
376 }
377 UpdateAlbumInfo(info);
378 insertInfos.push_back(info);
379 }
380 InsertPhoto(insertInfos);
381 }
382
RestorePhoto()383 void OthersCloneRestore::RestorePhoto()
384 {
385 if (!photoInfos_.size()) {
386 MEDIA_INFO_LOG("photo infos size zero");
387 return;
388 }
389 std::vector<FileInfo> fileInfos;
390 totalNumber_ += photoInfos_.size();
391 RestoreAlbum(photoInfos_);
392 unsigned long pageSize = 200;
393 vector<FileInfo> insertInfos;
394 int32_t totalNumber = static_cast<int32_t>(photoInfos_.size());
395 ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_CLONE_THREAD_NUM);
396 for (int32_t offset = 0; offset < totalNumber; offset += QUERY_NUMBER) {
397 ffrt::submit([this, offset]() {
398 HandleInsertBatch(offset);
399 }, { &offset }, {}, ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
400 }
401 ffrt::wait();
402 }
403
InsertPhoto(std::vector<FileInfo> & fileInfos)404 void OthersCloneRestore::InsertPhoto(std::vector<FileInfo> &fileInfos)
405 {
406 int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
407 vector<NativeRdb::ValuesBucket> values = BaseRestore::GetInsertValues(sceneCode_, fileInfos, SourceType::PHOTOS);
408 int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
409 int64_t rowNum = 0;
410 int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, rowNum);
411 if (errCode != E_OK) {
412 MEDIA_ERR_LOG("BatchInsert fail err %{public}d", errCode);
413 UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
414 return;
415 }
416
417 int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
418 migrateDatabaseNumber_ += rowNum;
419 int32_t fileMoveCount = 0;
420 int32_t videoFileMoveCount = 0;
421 MoveMigrateFile(fileInfos, fileMoveCount, videoFileMoveCount, sceneCode_);
422 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
423 MEDIA_INFO_LOG("generate values cost %{public}ld, insert %{public}ld assets cost %{public}ld"
424 ", and move %{public}ld files (%{public}ld + %{public}ld) cost %{public}ld.",
425 (long)(startInsert - start), (long)rowNum, (long)(startMove - startInsert),
426 (long)fileMoveCount, (long)(fileMoveCount - videoFileMoveCount),
427 (long)videoFileMoveCount, (long)(end - startMove));
428 }
429
NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)430 bool OthersCloneRestore::NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> &fileInfos,
431 NeedQueryMap &needQueryMap)
432 {
433 return true;
434 }
435
RestoreAudio()436 void OthersCloneRestore::RestoreAudio()
437 {
438 MEDIA_INFO_LOG("restore audio");
439 if (sceneCode_ == I_PHONE_CLONE_RESTORE) {
440 MEDIA_INFO_LOG("No need move audio");
441 return;
442 }
443 if (!audioInfos_.size()) {
444 MEDIA_INFO_LOG("audio infos size zero");
445 return;
446 }
447 audioTotalNumber_ += audioInfos_.size();
448 int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
449 InsertAudio(sceneCode_, audioInfos_);
450 int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
451 MEDIA_INFO_LOG("generate values cost %{public}ld, insert audio %{public}ld",
452 (long)(end - start), (long)audioTotalNumber_);
453 }
454
HandleRestData()455 void OthersCloneRestore::HandleRestData()
456 {
457 MEDIA_INFO_LOG("Start to handle rest data in native.");
458 RestoreThumbnail();
459 }
460
ParseSourcePathToLPath(int32_t sceneCode,const std::string & filePath)461 static std::string ParseSourcePathToLPath(int32_t sceneCode, const std::string &filePath)
462 {
463 std::string lPath = filePath;
464 std::string source = OTHER_CLONE_FILE_PATH;
465 auto findPos = lPath.find(source);
466 if (findPos != std::string::npos) {
467 lPath.replace(lPath.find(source), source.length(), "");
468 } else {
469 MEDIA_WARN_LOG("find other clone path error path: %{public}s",
470 BackupFileUtils::GarbleFilePath(filePath, sceneCode).c_str());
471 source = OTHER_CLONE_FILE_ROOT_PATH;
472 findPos = lPath.find(source);
473 if (findPos != std::string::npos) {
474 lPath.replace(lPath.find(source), source.length(), "");
475 }
476 }
477 std::size_t startPos = lPath.find_first_of(FILE_SEPARATOR);
478 if (startPos != std::string::npos) {
479 lPath = lPath.substr(startPos);
480 }
481 std::size_t pos = lPath.find_last_of(FILE_SEPARATOR);
482 if (pos != std::string::npos) {
483 lPath = lPath.substr(0, pos);
484 } else {
485 MEDIA_WARN_LOG("find error path is: %{public}s",
486 BackupFileUtils::GarbleFilePath(filePath, sceneCode).c_str());
487 lPath = FILE_SEPARATOR;
488 }
489 if (lPath.empty()) {
490 MEDIA_WARN_LOG("find path is empty: %{public}s",
491 BackupFileUtils::GarbleFilePath(filePath, sceneCode).c_str());
492 lPath = FILE_SEPARATOR;
493 }
494 return lPath;
495 }
496
AddGalleryAlbum(std::vector<PhotoAlbumRestore::GalleryAlbumRowData> & galleryAlbumInfos,const std::string & lPath)497 static void AddGalleryAlbum(std::vector<PhotoAlbumRestore::GalleryAlbumRowData> &galleryAlbumInfos,
498 const std::string &lPath)
499 {
500 auto pathMatch = [lPath {lPath}](const auto &galleryAlbumInfo) {
501 return galleryAlbumInfo.lPath == lPath;
502 };
503 auto it = std::find_if(galleryAlbumInfos.begin(), galleryAlbumInfos.end(), pathMatch);
504 if (it != galleryAlbumInfos.end()) {
505 return;
506 }
507
508 PhotoAlbumRestore::GalleryAlbumRowData galleryAlbum;
509 std::size_t pos = lPath.find_last_of(FILE_SEPARATOR);
510 if (pos != std::string::npos) {
511 galleryAlbum.albumName = lPath.substr(pos + 1);
512 } else {
513 galleryAlbum.albumName = lPath;
514 }
515 galleryAlbum.lPath = lPath;
516 galleryAlbum.priority = 1;
517 galleryAlbumInfos.emplace_back(galleryAlbum);
518 }
519
ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,std::string dbName)520 bool OthersCloneRestore::ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
521 std::string dbName)
522 {
523 return true;
524 }
525
ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)526 bool OthersCloneRestore::ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
527 {
528 return true;
529 }
530
RestoreAlbum(std::vector<FileInfo> & fileInfos)531 void OthersCloneRestore::RestoreAlbum(std::vector<FileInfo> &fileInfos)
532 {
533 std::vector<PhotoAlbumDao::PhotoAlbumRowData> albumInfos = this->photoAlbumDao_.GetPhotoAlbums();
534 std::vector<PhotoAlbumRestore::GalleryAlbumRowData> galleryAlbumInfos;
535 if (sceneCode_ == I_PHONE_CLONE_RESTORE) {
536 PhotoAlbumRestore::GalleryAlbumRowData galleryAlbum;
537 galleryAlbum.albumName = clonePhoneName_;
538 galleryAlbum.bundleName = clonePhoneName_;
539 galleryAlbum.lPath = I_PHONE_LPATH + clonePhoneName_;
540 galleryAlbum.priority = 1;
541 galleryAlbumInfos.emplace_back(galleryAlbum);
542 } else if (sceneCode_ == OTHERS_PHONE_CLONE_RESTORE) {
543 for (auto &info : fileInfos) {
544 info.lPath = ParseSourcePathToLPath(sceneCode_, info.filePath);
545 AddGalleryAlbum(galleryAlbumInfos, info.lPath);
546 }
547 }
548 std::vector<PhotoAlbumDao::PhotoAlbumRowData> albumInfosToRestore =
549 photoAlbumRestore_.GetAlbumsToRestore(albumInfos, galleryAlbumInfos);
550 auto ret = photoAlbumDao_.RestoreAlbums(albumInfosToRestore);
551 if (ret != NativeRdb::E_OK) {
552 MEDIA_ERR_LOG("Failed to RestoreAlbums : %{public}d", ret);
553 }
554 }
555
HasSameFileForDualClone(FileInfo & fileInfo)556 bool OthersCloneRestore::HasSameFileForDualClone(FileInfo &fileInfo)
557 {
558 PhotosDao::PhotosRowData rowData = this->photosRestore_.FindSameFile(fileInfo);
559 int32_t fileId = rowData.fileId;
560 std::string cloudPath = rowData.data;
561 if (fileId <= 0 || cloudPath.empty()) {
562 return false;
563 }
564 fileInfo.fileIdNew = fileId;
565 fileInfo.cloudPath = cloudPath;
566 return true;
567 }
568
ToLower(const std::string & str)569 static std::string ToLower(const std::string &str)
570 {
571 std::string lowerStr;
572 std::transform(
573 str.begin(), str.end(), std::back_inserter(lowerStr), [](unsigned char c) { return std::tolower(c); });
574 return lowerStr;
575 }
576
FindAlbumInfo(FileInfo & fileInfo)577 PhotoAlbumDao::PhotoAlbumRowData OthersCloneRestore::FindAlbumInfo(FileInfo &fileInfo)
578 {
579 PhotoAlbumDao::PhotoAlbumRowData albumInfo;
580 if (fileInfo.lPath.empty()) {
581 MEDIA_ERR_LOG("others clone lPath is empty, path: %{public}s",
582 BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode_).c_str());
583 return albumInfo;
584 }
585 if (ToLower(fileInfo.lPath) == ToLower(AlbumPlugin::LPATH_SCREEN_SHOTS) &&
586 fileInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
587 albumInfo = this->photoAlbumDao_.BuildAlbumInfoOfRecorders();
588 albumInfo = this->photoAlbumDao_.GetOrCreatePhotoAlbum(albumInfo);
589 MEDIA_INFO_LOG(
590 "others clone: screenshots redirect to screenrecords, path: %{public}s",
591 BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode_).c_str());
592 fileInfo.lPath = AlbumPlugin::LPATH_SCREEN_RECORDS;
593 return albumInfo;
594 }
595 albumInfo = this->photoAlbumDao_.GetPhotoAlbum(fileInfo.lPath);
596 if (albumInfo.lPath.empty()) {
597 MEDIA_ERR_LOG("others clone: albumInfo is empty, path: %{public}s",
598 BackupFileUtils::GarbleFilePath(fileInfo.filePath, sceneCode_).c_str());
599 }
600 return albumInfo;
601 }
602
UpdateAlbumInfo(FileInfo & info)603 void OthersCloneRestore::UpdateAlbumInfo(FileInfo &info)
604 {
605 if (sceneCode_ == I_PHONE_CLONE_RESTORE) {
606 PhotoAlbumDao::PhotoAlbumRowData albumInfo = photoAlbumDao_.GetPhotoAlbum(I_PHONE_LPATH + clonePhoneName_);
607 info.lPath = I_PHONE_LPATH + clonePhoneName_;
608 info.mediaAlbumId = albumInfo.albumId;
609 info.ownerAlbumId = albumInfo.albumId;
610 info.packageName = clonePhoneName_;
611 info.bundleName = clonePhoneName_;
612 } else if (sceneCode_ == OTHERS_PHONE_CLONE_RESTORE) {
613 PhotoAlbumDao::PhotoAlbumRowData albumInfo = FindAlbumInfo(info);
614 info.mediaAlbumId = albumInfo.albumId;
615 info.ownerAlbumId = albumInfo.albumId;
616 }
617 }
618
AnalyzeSource()619 void OthersCloneRestore::AnalyzeSource()
620 {
621 MEDIA_INFO_LOG("analyze source later");
622 }
623
624 } // namespace Media
625 } // namespace OHOS
626