• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2025 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 "MediaLibraryCloneRestore"
17 
18 #include "clone_restore.h"
19 #include "backup_const_column.h"
20 
21 #include "application_context.h"
22 #include "backup_dfx_utils.h"
23 #include "backup_file_utils.h"
24 #include "backup_log_utils.h"
25 #include "clone_restore_classify.h"
26 #include "clone_restore_cv_analysis.h"
27 #include "clone_restore_highlight.h"
28 #include "clone_restore_geo.h"
29 #include "cloud_sync_utils.h"
30 #include "database_report.h"
31 #include "exif_rotate_utils.h"
32 #include "media_column.h"
33 #include "media_file_utils.h"
34 #include "media_library_db_upgrade.h"
35 #include "media_log.h"
36 #include "medialibrary_data_manager.h"
37 #include "medialibrary_errno.h"
38 #include "medialibrary_notify.h"
39 #include "medialibrary_photo_operations.h"
40 #include "medialibrary_type_const.h"
41 #include "ohos_account_kits.h"
42 #include "photos_dao.h"
43 #include "rdb_store.h"
44 #include "result_set_utils.h"
45 #include "upgrade_restore_task_report.h"
46 #include "userfile_manager_types.h"
47 #include "ohos_account_kits.h"
48 
49 #ifdef CLOUD_SYNC_MANAGER
50 #include "cloud_sync_manager.h"
51 #endif
52 
53 using namespace std;
54 namespace OHOS {
55 namespace Media {
56 const int32_t CLONE_QUERY_COUNT = 200;
57 const string MEDIA_DB_PATH = "/data/storage/el2/database/rdb/media_library.db";
58 const std::string THM_SAVE_WITHOUT_ROTATE_PATH = "/THM_EX";
59 constexpr int64_t SECONDS_LEVEL_LIMIT = 1e10;
60 const int32_t ORIETATION_ZERO = 0;
61 const int32_t MIGRATE_CLOUD_THM_TYPE = 0;
62 const int32_t MIGRATE_CLOUD_LCD_TYPE = 1;
63 const int32_t MIGRATE_CLOUD_ASTC_TYPE = 2;
64 const int32_t RELEATED_TO_PHOTO_MAP = 1;
65 const unordered_map<string, unordered_set<string>> NEEDED_COLUMNS_MAP = {
66     { PhotoColumn::PHOTOS_TABLE,
67         {
68             MediaColumn::MEDIA_ID,
69             MediaColumn::MEDIA_FILE_PATH,
70             MediaColumn::MEDIA_SIZE,
71             MediaColumn::MEDIA_TYPE,
72             MediaColumn::MEDIA_NAME,
73             MediaColumn::MEDIA_DATE_ADDED,
74             MediaColumn::MEDIA_DATE_MODIFIED,
75             PhotoColumn::PHOTO_ORIENTATION,
76             PhotoColumn::PHOTO_SUBTYPE,
77             MediaColumn::MEDIA_DATE_TRASHED,
78             MediaColumn::MEDIA_HIDDEN,
79         }},
80     { PhotoAlbumColumns::TABLE,
81         {
82             PhotoAlbumColumns::ALBUM_ID,
83             PhotoAlbumColumns::ALBUM_TYPE,
84             PhotoAlbumColumns::ALBUM_SUBTYPE,
85             PhotoAlbumColumns::ALBUM_NAME,
86             PhotoAlbumColumns::ALBUM_BUNDLE_NAME,
87         }},
88     { PhotoMap::TABLE,
89         {
90             PhotoMap::ALBUM_ID,
91             PhotoMap::ASSET_ID,
92         }},
93     { ANALYSIS_ALBUM_TABLE,
94         {
95             PhotoAlbumColumns::ALBUM_ID,
96             PhotoAlbumColumns::ALBUM_TYPE,
97             PhotoAlbumColumns::ALBUM_SUBTYPE,
98             PhotoAlbumColumns::ALBUM_NAME,
99         }},
100     { ANALYSIS_PHOTO_MAP_TABLE,
101         {
102             PhotoMap::ALBUM_ID,
103             PhotoMap::ASSET_ID,
104         }},
105     { AudioColumn::AUDIOS_TABLE,
106         {
107             MediaColumn::MEDIA_ID,
108             MediaColumn::MEDIA_FILE_PATH,
109             MediaColumn::MEDIA_SIZE,
110             MediaColumn::MEDIA_TYPE,
111             MediaColumn::MEDIA_NAME,
112             MediaColumn::MEDIA_DATE_ADDED,
113             MediaColumn::MEDIA_DATE_MODIFIED,
114         }},
115 };
116 const unordered_map<string, unordered_set<string>> NEEDED_COLUMNS_EXCEPTION_MAP = {
117     { PhotoAlbumColumns::TABLE,
118         {
119             PhotoAlbumColumns::ALBUM_BUNDLE_NAME,
120         }},
121 };
122 const unordered_map<string, unordered_set<string>> EXCLUDED_COLUMNS_MAP = {
123     { PhotoColumn::PHOTOS_TABLE,
124         {
125             PhotoColumn::PHOTO_CLOUD_ID, PhotoColumn::PHOTO_DIRTY,
126             PhotoColumn::PHOTO_SYNC_STATUS, PhotoColumn::PHOTO_CLOUD_VERSION, PhotoColumn::PHOTO_POSITION,
127             PhotoColumn::PHOTO_THUMB_STATUS, PhotoColumn::PHOTO_CLEAN_FLAG, // cloud related
128             PhotoColumn::PHOTO_THUMBNAIL_READY, PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, // thumbnail related
129             PhotoColumn::PHOTO_LCD_VISIT_TIME, // lcd related
130             PhotoColumn::PHOTO_CE_AVAILABLE, PhotoColumn::PHOTO_CE_STATUS_CODE, // cloud enhancement
131             PhotoColumn::PHOTO_METADATA_FLAGS, // meta recovery related
132             PhotoColumn::PHOTO_EXIF_ROTATE,
133         }},
134     { PhotoAlbumColumns::TABLE,
135         {
136             PhotoAlbumColumns::ALBUM_COVER_URI, PhotoAlbumColumns::ALBUM_COUNT, PhotoAlbumColumns::CONTAINS_HIDDEN,
137             PhotoAlbumColumns::HIDDEN_COUNT, PhotoAlbumColumns::HIDDEN_COVER, PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
138             PhotoAlbumColumns::ALBUM_VIDEO_COUNT, // updated by album udpate
139             PhotoAlbumColumns::ALBUM_DIRTY, PhotoAlbumColumns::ALBUM_CLOUD_ID, // cloud related
140             PhotoAlbumColumns::ALBUM_ORDER, // created by trigger
141         }},
142     { ANALYSIS_ALBUM_TABLE,
143         {
144             PhotoAlbumColumns::ALBUM_COVER_URI,
145             PhotoAlbumColumns::ALBUM_COUNT,
146         }},
147 };
148 const unordered_map<string, unordered_map<string, string>> TABLE_QUERY_WHERE_CLAUSE_MAP = {
149     { PhotoColumn::PHOTOS_TABLE,
150         {
151             { PhotoColumn::PHOTO_POSITION, PhotoColumn::PHOTO_POSITION + " IN (1, 3) "},
152             { PhotoColumn::PHOTO_SYNC_STATUS, PhotoColumn::PHOTO_SYNC_STATUS + " = " +
153                 to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) },
154             { PhotoColumn::PHOTO_CLEAN_FLAG, PhotoColumn::PHOTO_CLEAN_FLAG + " = " +
155                 to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) },
156             { MediaColumn::MEDIA_TIME_PENDING, MediaColumn::MEDIA_TIME_PENDING + " = 0" },
157             { PhotoColumn::PHOTO_IS_TEMP, PhotoColumn::PHOTO_IS_TEMP + " = 0" },
158         }},
159     { PhotoAlbumColumns::TABLE,
160         {
161             { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
162             { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_TYPE + " != " +
163                 to_string(PhotoAlbumType::SYSTEM)},
164         }},
165     { ANALYSIS_ALBUM_TABLE,
166         {
167             { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
168             { PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumColumns::ALBUM_SUBTYPE + " IN (" +
169                 to_string(PhotoAlbumSubType::SHOOTING_MODE) + ", " +
170                 to_string(PhotoAlbumSubType::GEOGRAPHY_CITY) + ", " +
171                 to_string(PhotoAlbumSubType::CLASSIFY) + ")" },
172         }},
173 };
174 const unordered_map<string, unordered_map<string, string>> TABLE_QUERY_WHERE_CLAUSE_MAP_WITH_CLOUD = {
175     { PhotoColumn::PHOTOS_TABLE,
176         {
177             { PhotoColumn::PHOTO_POSITION, PhotoColumn::PHOTO_POSITION + " IN (1, 2, 3) "},
178             { PhotoColumn::PHOTO_SYNC_STATUS, PhotoColumn::PHOTO_SYNC_STATUS + " = " +
179                 to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) },
180             { PhotoColumn::PHOTO_CLEAN_FLAG, PhotoColumn::PHOTO_CLEAN_FLAG + " = " +
181                 to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) },
182             { MediaColumn::MEDIA_TIME_PENDING, MediaColumn::MEDIA_TIME_PENDING + " = 0" },
183             { PhotoColumn::PHOTO_IS_TEMP, PhotoColumn::PHOTO_IS_TEMP + " = 0" },
184         }},
185     { PhotoAlbumColumns::TABLE,
186         {
187             { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
188             { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_TYPE + " != " +
189                 to_string(PhotoAlbumType::SYSTEM)},
190         }},
191     { ANALYSIS_ALBUM_TABLE,
192         {
193             { PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_NAME + " IS NOT NULL" },
194             { PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumColumns::ALBUM_SUBTYPE + " IN (" +
195                 to_string(PhotoAlbumSubType::SHOOTING_MODE) + ", " +
196                 to_string(PhotoAlbumSubType::GEOGRAPHY_CITY) + ", " +
197                 to_string(PhotoAlbumSubType::CLASSIFY) + ")" },
198         }},
199 };
200 const vector<string> CLONE_ALBUMS = { PhotoAlbumColumns::TABLE, ANALYSIS_ALBUM_TABLE };
201 const unordered_map<string, string> CLONE_ALBUM_MAP = {
202     { PhotoAlbumColumns::TABLE, PhotoMap::TABLE },
203     { ANALYSIS_ALBUM_TABLE, ANALYSIS_PHOTO_MAP_TABLE },
204 };
205 const unordered_map<string, ResultSetDataType> COLUMN_TYPE_MAP = {
206     { "INT", ResultSetDataType::TYPE_INT32 },
207     { "INTEGER", ResultSetDataType::TYPE_INT32 },
208     { "BIGINT", ResultSetDataType::TYPE_INT64 },
209     { "DOUBLE", ResultSetDataType::TYPE_DOUBLE },
210     { "REAL", ResultSetDataType::TYPE_DOUBLE },
211     { "TEXT", ResultSetDataType::TYPE_STRING },
212     { "BLOB", ResultSetDataType::TYPE_BLOB },
213 };
214 const unordered_map<string, string> ALBUM_URI_PREFIX_MAP = {
215     { PhotoAlbumColumns::TABLE, PhotoAlbumColumns::ALBUM_URI_PREFIX },
216     { ANALYSIS_ALBUM_TABLE, PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX },
217 };
218 
219 template<typename Key, typename Value>
GetValueFromMap(const unordered_map<Key,Value> & map,const Key & key,const Value & defaultValue=Value ())220 Value GetValueFromMap(const unordered_map<Key, Value> &map, const Key &key, const Value &defaultValue = Value())
221 {
222     auto it = map.find(key);
223     CHECK_AND_RETURN_RET(it != map.end(), defaultValue);
224     return it->second;
225 }
226 
CloneRestore()227 CloneRestore::CloneRestore()
228 {
229     sceneCode_ = CLONE_RESTORE_ID;
230     ffrt_disable_worker_escape();
231     MEDIA_INFO_LOG("Set ffrt_disable_worker_escape");
232 }
233 
StartRestore(const string & backupRestoreDir,const string & upgradePath)234 void CloneRestore::StartRestore(const string &backupRestoreDir, const string &upgradePath)
235 {
236     if (WaitSouthDeviceExitTimeout()) {
237         MEDIA_ERR_LOG("restore, wait south device cleaning data timeout.");
238         SetErrorCode(RestoreError::RETAIN_FORCE_TIMEOUT);
239         ErrorInfo errorInfo(RestoreError::RETAIN_FORCE_TIMEOUT, 0, "",
240             "restore, wait south device cleaning data timeout.");
241         UpgradeRestoreTaskReport(sceneCode_, taskId_).ReportError(errorInfo);
242         return;
243     }
244     MEDIA_INFO_LOG("Start clone restore");
245     SetParameterForClone();
246     SetParameterForRestore();
247     GetAccountValid();
248     GetSyncSwitchOn();
249     MEDIA_INFO_LOG("the isAccountValid_ is %{public}d, the isSyncSwitchOn_ is %{public}d", isAccountValid_,
250         isSyncSwitchOn_);
251 #ifdef CLOUD_SYNC_MANAGER
252     FileManagement::CloudSync::CloudSyncManager::GetInstance().StopSync("com.ohos.medialibrary.medialibrarydata");
253 #endif
254     backupRestoreDir_ = backupRestoreDir;
255     garbagePath_ = backupRestoreDir_ + "/storage/media/local/files";
256     int32_t errorCode = Init(backupRestoreDir, upgradePath, true);
257     if (errorCode == E_OK) {
258         RestoreGallery();
259         RestoreMusic();
260         UpdateDatabase();
261         (void)NativeRdb::RdbHelper::DeleteRdbStore(dbPath_);
262     } else {
263         SetErrorCode(RestoreError::INIT_FAILED);
264         ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, errorCode);
265         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
266     }
267     HandleRestData();
268     StopParameterForRestore();
269     StopParameterForClone();
270     CloseAllKvStore();
271     MEDIA_INFO_LOG("End clone restore");
272 }
273 
InitThumbnailStatus()274 void CloneRestore::InitThumbnailStatus()
275 {
276     std::string cloneThumbnailDir = backupRestoreDir_ + RESTORE_FILES_LOCAL_DIR + ".thumbs";
277     if (!MediaFileUtils::IsFileExists(cloneThumbnailDir)) {
278         MEDIA_WARN_LOG("Uncloned thumbnail dir, no need to clone thumbnail");
279         return;
280     }
281     hasCloneThumbnailDir_ = true;
282     isInitKvstoreSuccess_ = InitAllKvStore();
283 }
284 
Init(const string & backupRestoreDir,const string & upgradePath,bool isUpgrade)285 int32_t CloneRestore::Init(const string &backupRestoreDir, const string &upgradePath, bool isUpgrade)
286 {
287     dbPath_ = backupRestoreDir_ + MEDIA_DB_PATH;
288     filePath_ = backupRestoreDir_ + "/storage/media/local/files";
289     if (!MediaFileUtils::IsFileExists(dbPath_)) {
290         MEDIA_ERR_LOG("Media db is not exist.");
291         return E_FAIL;
292     }
293     if (isUpgrade && BaseRestore::Init() != E_OK) {
294         return E_FAIL;
295     }
296 
297     auto context = AbilityRuntime::Context::GetApplicationContext();
298     CHECK_AND_RETURN_RET_LOG(context != nullptr, E_FAIL, "Failed to get context");
299     int32_t err = BackupDatabaseUtils::InitDb(mediaRdb_, MEDIA_DATA_ABILITY_DB_NAME, dbPath_, BUNDLE_NAME, true,
300         context->GetArea());
301     CHECK_AND_RETURN_RET_LOG(mediaRdb_ != nullptr, E_FAIL, "Init remote medialibrary rdb fail, err = %{public}d", err);
302 
303     BackupDatabaseUtils::CheckDbIntegrity(mediaRdb_, sceneCode_, "OLD_MEDIA_LIBRARY");
304     InitThumbnailStatus();
305     this->photoAlbumClone_.OnStart(this->mediaRdb_, this->mediaLibraryRdb_, IsCloudRestoreSatisfied());
306     this->photosClone_.OnStart(this->mediaLibraryRdb_, this->mediaRdb_);
307     cloneRestoreGeoDictionary_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->mediaRdb_);
308     MEDIA_INFO_LOG("Init db succ.");
309     return E_OK;
310 }
311 
RestorePhoto()312 void CloneRestore::RestorePhoto()
313 {
314     MEDIA_INFO_LOG("Start clone restore: photos");
315     CHECK_AND_RETURN_LOG(IsReadyForRestore(PhotoColumn::PHOTOS_TABLE),
316         "Column status is not ready for restore photo, quit");
317     unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_,
318         PhotoColumn::PHOTOS_TABLE);
319     unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
320         PhotoColumn::PHOTOS_TABLE);
321     UpdateExistNewAddColumnSet(srcColumnInfoMap);
322     if (!PrepareCommonColumnInfoMap(PhotoColumn::PHOTOS_TABLE, srcColumnInfoMap, dstColumnInfoMap)) {
323         MEDIA_ERR_LOG("Prepare common column info failed");
324         return;
325     }
326     // The begining of the restore process
327     // Start clone restore
328     this->photosClone_.LoadPhotoAlbums();
329     // Scenario 1, clone photos from PhotoAlbum, PhotoMap and Photos.
330     int totalNumberInPhotoMap = this->photosClone_.GetPhotosRowCountInPhotoMap();
331     MEDIA_INFO_LOG("GetPhotosRowCountInPhotoMap, totalNumber = %{public}d", totalNumberInPhotoMap);
332     totalNumber_ += static_cast<uint64_t>(totalNumberInPhotoMap);
333     MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
334     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
335     for (int32_t offset = 0; offset < totalNumberInPhotoMap; offset += CLONE_QUERY_COUNT) {
336         ffrt::submit([this, offset]() { RestorePhotoBatch(offset, RELEATED_TO_PHOTO_MAP); }, {&offset}, {},
337             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
338     }
339     ffrt::wait();
340     ProcessPhotosBatchFailedOffsets(RELEATED_TO_PHOTO_MAP);
341     needReportFailed_ = false;
342     // Scenario 2, clone photos from Photos only.
343     int32_t totalNumber = this->photosClone_.GetPhotosRowCountNotInPhotoMap();
344     MEDIA_INFO_LOG("QueryTotalNumberNot, totalNumber = %{public}d", totalNumber);
345     totalNumber_ += static_cast<uint64_t>(totalNumber);
346     MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
347     for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
348         ffrt::submit([this, offset]() { RestorePhotoBatch(offset); }, { &offset }, {},
349             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
350     }
351     ffrt::wait();
352     ProcessPhotosBatchFailedOffsets();
353     this->photosClone_.OnStop(otherTotalNumber_, otherProcessStatus_);
354 }
355 
GetAccountValid()356 void CloneRestore::GetAccountValid()
357 {
358     string oldId = "";
359     string newId = "";
360     nlohmann::json jsonArr = nlohmann::json::parse(restoreInfo_, nullptr, false);
361     CHECK_AND_RETURN_LOG(!jsonArr.is_discarded(), "cloud account parse failed");
362     for (const auto& item : jsonArr) {
363         bool cond = (!item.contains("type") || !item.contains("detail") || item["type"] != "singleAccountId");
364         CHECK_AND_CONTINUE(!cond);
365         oldId = item["detail"];
366         MEDIA_INFO_LOG("the old is %{public}s", oldId.c_str());
367         break;
368     }
369     std::pair<bool, OHOS::AccountSA::OhosAccountInfo> ret =
370         OHOS::AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
371     if (ret.first) {
372         OHOS::AccountSA::OhosAccountInfo& resultInfo = ret.second;
373         newId = resultInfo.uid_;
374     } else {
375         MEDIA_ERR_LOG("new account logins failed");
376         return;
377     }
378     MEDIA_INFO_LOG("clone the old id is %{public}s, new id is %{public}s",
379         BackupFileUtils::GarbleFilePath(oldId, sceneCode_).c_str(),
380         BackupFileUtils::GarbleFilePath(newId, sceneCode_).c_str());
381     isAccountValid_ = (oldId != "" && oldId == newId);
382 }
383 
AddToPhotosFailedOffsets(int32_t offset)384 void CloneRestore::AddToPhotosFailedOffsets(int32_t offset)
385 {
386     std::lock_guard<ffrt::mutex> lock(photosFailedMutex_);
387     photosFailedOffsets_.push_back(offset);
388 }
389 
ProcessPhotosBatchFailedOffsets(int32_t isRelatedToPhotoMap)390 void CloneRestore::ProcessPhotosBatchFailedOffsets(int32_t isRelatedToPhotoMap)
391 {
392     std::lock_guard<ffrt::mutex> lock(photosFailedMutex_);
393     size_t vectorLen = photosFailedOffsets_.size();
394     needReportFailed_ = true;
395     for (size_t offset = 0; offset < vectorLen; offset++) {
396         RestorePhotoBatch(photosFailedOffsets_[offset], isRelatedToPhotoMap);
397     }
398     photosFailedOffsets_.clear();
399 }
400 
ProcessCloudPhotosFailedOffsets(int32_t isRelatedToPhotoMap)401 void CloneRestore::ProcessCloudPhotosFailedOffsets(int32_t isRelatedToPhotoMap)
402 {
403     std::lock_guard<ffrt::mutex> lock(photosFailedMutex_);
404     size_t vectorLen = photosFailedOffsets_.size();
405     needReportFailed_ = true;
406     for (size_t offset = 0; offset < vectorLen; offset++) {
407         RestoreBatchForCloud(photosFailedOffsets_[offset], isRelatedToPhotoMap);
408     }
409     photosFailedOffsets_.clear();
410 }
411 
RestorePhotoForCloud()412 void CloneRestore::RestorePhotoForCloud()
413 {
414     MEDIA_INFO_LOG("singleClone start clone restore: photos");
415     CHECK_AND_RETURN_LOG(IsReadyForRestore(PhotoColumn::PHOTOS_TABLE),
416         "singleClone column status is not ready for restore photo, quit");
417     unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_,
418         PhotoColumn::PHOTOS_TABLE);
419     unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
420         PhotoColumn::PHOTOS_TABLE);
421     CHECK_AND_RETURN_LOG(PrepareCommonColumnInfoMap(PhotoColumn::PHOTOS_TABLE, srcColumnInfoMap, dstColumnInfoMap),
422         "singleClone Prepare common column info failed");
423 
424     this->photosClone_.LoadPhotoAlbums();
425     int totalNumberInPhotoMap = this->photosClone_.GetCloudPhotosRowCountInPhotoMap();
426     MEDIA_INFO_LOG("singleClone getPhotosRowCountInPhotoMap, totalNumber = %{public}d", totalNumberInPhotoMap);
427     totalNumber_ += static_cast<uint64_t>(totalNumberInPhotoMap);
428     MEDIA_INFO_LOG("singleClone onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
429     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
430     for (int32_t offset = 0; offset < totalNumberInPhotoMap; offset += CLONE_QUERY_COUNT) {
431         ffrt::submit([this, offset]() { RestoreBatchForCloud(offset, RELEATED_TO_PHOTO_MAP); }, {&offset}, {},
432             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
433     }
434     ffrt::wait();
435     ProcessCloudPhotosFailedOffsets(RELEATED_TO_PHOTO_MAP);
436     needReportFailed_ = false;
437     int32_t totalNumber = this->photosClone_.GetCloudPhotosRowCountNotInPhotoMap();
438     MEDIA_INFO_LOG("singleClone queryTotalNumberNot, totalNumber = %{public}d", totalNumber);
439     totalNumber_ += static_cast<uint64_t>(totalNumber);
440     MEDIA_INFO_LOG("singleClone onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
441     for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
442         ffrt::submit([this, offset]() { RestoreBatchForCloud(offset); }, { &offset }, {},
443             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
444     }
445     ffrt::wait();
446     ProcessCloudPhotosFailedOffsets();
447     this->photosClone_.OnStop(otherTotalNumber_, otherProcessStatus_);
448 
449     BackupDatabaseUtils::UpdateFaceAnalysisTblStatus(mediaLibraryRdb_);
450     BackupDatabaseUtils::UpdateAnalysisPhotoMapStatus(mediaLibraryRdb_);
451     ReportPortraitCloneStat(sceneCode_);
452 }
453 
RestoreAlbum()454 void CloneRestore::RestoreAlbum()
455 {
456     MEDIA_INFO_LOG("Start clone restore: albums");
457     maxSearchId_ = BackupDatabaseUtils::QueryMaxId(mediaLibraryRdb_,
458         ANALYSIS_SEARCH_INDEX_TABLE, SEARCH_IDX_COL_ID);
459     maxAnalysisAlbumId_ = BackupDatabaseUtils::QueryMaxId(mediaLibraryRdb_,
460         ANALYSIS_ALBUM_TABLE, ANALYSIS_COL_ALBUM_ID);
461     maxBeautyFileId_ = BackupDatabaseUtils::QueryMaxId(mediaLibraryRdb_,
462         ANALYSIS_BEAUTY_SCORE_TABLE, BEAUTY_SCORE_COL_FILE_ID);
463 
464     for (const auto &tableName : CLONE_ALBUMS) {
465         if (!IsReadyForRestore(tableName)) {
466             MEDIA_ERR_LOG("Column status of %{public}s is not ready for restore album, quit",
467                 BackupDatabaseUtils::GarbleInfoName(tableName).c_str());
468             continue;
469         }
470         unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_, tableName);
471         unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
472             tableName);
473         if (!PrepareCommonColumnInfoMap(tableName, srcColumnInfoMap, dstColumnInfoMap)) {
474             MEDIA_ERR_LOG("Prepare common column info failed");
475             continue;
476         }
477         GetAlbumExtraQueryWhereClause(tableName);
478         int32_t totalNumber = QueryTotalNumber(tableName);
479         MEDIA_INFO_LOG(
480             "QueryAlbumTotalNumber, tableName=%{public}s, totalNumber=%{public}d", tableName.c_str(), totalNumber);
481         for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
482             vector<AlbumInfo> albumInfos = QueryAlbumInfos(tableName, offset);
483             this->photoAlbumClone_.TRACE_LOG(tableName, albumInfos);
484             InsertAlbum(albumInfos, tableName);
485         }
486         UpdateSystemAlbumColumns(tableName);
487     }
488 
489     RestoreFromGalleryPortraitAlbum();
490     RestorePortraitClusteringInfo();
491     cloneRestoreGeoDictionary_.RestoreAlbums();
492 }
493 
GetHighlightCloudMediaCnt()494 int32_t CloneRestore::GetHighlightCloudMediaCnt()
495 {
496     const std::string QUERY_SQL = "SELECT COUNT(1) AS count FROM AnalysisAlbum AS a "
497         "INNER JOIN AnalysisPhotoMap AS m ON a.album_id = m.map_album "
498         "INNER JOIN Photos AS p ON p.file_id = m.map_asset "
499         "WHERE a.album_subtype IN (4104, 4105) AND p.position = 2";
500     std::shared_ptr<NativeRdb::ResultSet> resultSet = BackupDatabaseUtils::QuerySql(this->mediaRdb_, QUERY_SQL, {});
501     bool cond = (resultSet == nullptr);
502     CHECK_AND_RETURN_RET_LOG(!cond, -1, "query count of highlight cloud media failed.");
503     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
504         resultSet->Close();
505         return -1;
506     }
507     int32_t cnt = GetInt32Val("count", resultSet);
508     MEDIA_INFO_LOG("GetHighlightCloudMediaCnt is %{public}d", cnt);
509     resultSet->Close();
510     return cnt;
511 }
512 
RestoreHighlightAlbums()513 void CloneRestore::RestoreHighlightAlbums()
514 {
515     int32_t highlightCloudMediaCnt = GetHighlightCloudMediaCnt();
516     UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_)
517         .Report("CLONE_RESTORE_HIGHLIGHT_CHECK", "",
518             "highlightCloudMediaCnt: " + std::to_string(highlightCloudMediaCnt) +
519             ", isCloudRestoreSatisfied: " + std::to_string(IsCloudRestoreSatisfied()));
520     CHECK_AND_RETURN(highlightCloudMediaCnt == 0 || IsCloudRestoreSatisfied());
521 
522     CloneRestoreHighlight cloneRestoreHighlight;
523     CloneRestoreHighlight::InitInfo initInfo = { sceneCode_, taskId_, mediaLibraryRdb_, mediaRdb_, backupRestoreDir_,
524         photoInfoMap_ };
525     cloneRestoreHighlight.Init(initInfo);
526     cloneRestoreHighlight.Restore();
527 
528     CloneRestoreCVAnalysis cloneRestoreCVAnalysis;
529     cloneRestoreCVAnalysis.Init(sceneCode_, taskId_, mediaLibraryRdb_, mediaRdb_, backupRestoreDir_);
530     cloneRestoreCVAnalysis.RestoreAlbums(cloneRestoreHighlight);
531 
532     cloneRestoreHighlight.ReportCloneRestoreHighlightTask();
533 }
534 
MoveMigrateFile(std::vector<FileInfo> & fileInfos,int64_t & fileMoveCount,int64_t & videoFileMoveCount)535 void CloneRestore::MoveMigrateFile(std::vector<FileInfo> &fileInfos, int64_t &fileMoveCount,
536     int64_t &videoFileMoveCount)
537 {
538     vector<std::string> moveFailedData;
539     for (size_t i = 0; i < fileInfos.size(); i++) {
540         bool cond = (!MediaFileUtils::IsFileExists(fileInfos[i].filePath) ||
541             fileInfos[i].cloudPath.empty() || !fileInfos[i].needMove);
542         CHECK_AND_CONTINUE(!cond);
543         int32_t errCode = MoveAsset(fileInfos[i]);
544         if (errCode != E_OK) {
545             fileInfos[i].needUpdate = false;
546             fileInfos[i].needVisible = false;
547             MEDIA_ERR_LOG("MoveFile failed, filePath = %{public}s, error:%{public}s",
548                 BackupFileUtils::GarbleFilePath(fileInfos[i].filePath, CLONE_RESTORE_ID, garbagePath_).c_str(),
549                 strerror(errno));
550             UpdateFailedFiles(fileInfos[i].fileType, fileInfos[i], RestoreError::MOVE_FAILED);
551             ErrorInfo errorInfo(RestoreError::MOVE_FAILED, 1, std::to_string(errCode),
552                 BackupLogUtils::FileInfoToString(sceneCode_, fileInfos[i]));
553             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
554             moveFailedData.push_back(fileInfos[i].cloudPath);
555             continue;
556         }
557         fileMoveCount++;
558         videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
559     }
560     DeleteMoveFailedData(moveFailedData);
561     SetVisiblePhoto(fileInfos);
562     migrateFileNumber_ += fileMoveCount;
563     migrateVideoFileNumber_ += videoFileMoveCount;
564 }
565 
UpdateThumbnailStatusToFailed(std::shared_ptr<NativeRdb::RdbStore> & rdbStore,std::string id,bool isThumbnailStatusNeedUpdate,bool isLcdStatusNeedUpdate)566 static void UpdateThumbnailStatusToFailed(std::shared_ptr<NativeRdb::RdbStore> &rdbStore, std::string id,
567     bool isThumbnailStatusNeedUpdate, bool isLcdStatusNeedUpdate)
568 {
569     bool cond = (rdbStore == nullptr || id.empty());
570     CHECK_AND_RETURN_LOG(!cond, "singleClone rdb is nullptr or id is empty");
571 
572     NativeRdb::ValuesBucket values;
573     int changedRows;
574     if (isThumbnailStatusNeedUpdate) {
575         values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, RESTORE_THUMBNAIL_READY_NO_THUMBNAIL);
576         values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
577     }
578     if (isLcdStatusNeedUpdate) {
579         values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, RESTORE_LCD_VISIT_TIME_NO_LCD);
580     }
581     int32_t err = rdbStore->Update(changedRows, PhotoColumn::PHOTOS_TABLE,
582         values, MEDIA_DATA_DB_ID + " = ?", vector<string> { id });
583     CHECK_AND_PRINT_LOG(err == NativeRdb::E_OK, "singleClone rdbStore Update failed! %{public}d", err);
584 }
585 
GetCloudPhotoFileExistFlag(const FileInfo & fileInfo,CloudPhotoFileExistFlag & resultExistFlag)586 void CloneRestore::GetCloudPhotoFileExistFlag(const FileInfo &fileInfo, CloudPhotoFileExistFlag &resultExistFlag)
587 {
588     std::string dirPath = GetThumbnailLocalPath(fileInfo.cloudPath);
589     CHECK_AND_RETURN_LOG(MediaFileUtils::IsFileExists(dirPath),
590         "GetCloudPhotoFileExistFlag %{public}s not exist!", fileInfo.cloudPath.c_str());
591 
592     std::string lcdPath = dirPath + "/LCD.jpg";
593     resultExistFlag.isLcdExist = MediaFileUtils::IsFileExists(lcdPath) ? true : false;
594     std::string thmPath = dirPath + "/THM.jpg";
595     resultExistFlag.isThmExist = MediaFileUtils::IsFileExists(thmPath) ? true : false;
596     std::string astcPath = dirPath + "/THM_ASTC.astc";
597     resultExistFlag.isDayAstcExist = MediaFileUtils::IsFileExists(astcPath) ? true : false;
598 
599     if (HasExThumbnail(fileInfo)) {
600         std::string exLcdPath = dirPath + "/THM_EX/LCD.jpg";
601         resultExistFlag.isExLcdExist = MediaFileUtils::IsFileExists(exLcdPath) ? true : false;
602         std::string exThmPath = dirPath + "/THM_EX/THM.jpg";
603         resultExistFlag.isExThmExist = MediaFileUtils::IsFileExists(exThmPath) ? true : false;
604     }
605     MEDIA_DEBUG_LOG("%{public}s, isexist lcd:%{public}d, thm:%{public}d, astc:%{public}d,"
606         "yearastc:%{public}d, exlcd:%{public}d, exthm:%{public}d",
607         dirPath.c_str(), resultExistFlag.isLcdExist, resultExistFlag.isThmExist,
608         resultExistFlag.isDayAstcExist, resultExistFlag.isYearAstcExist,
609         resultExistFlag.isExLcdExist, resultExistFlag.isExThmExist);
610 }
611 
CloudPhotoFilesVerify(const std::vector<FileInfo> & fileInfos,std::vector<FileInfo> & LCDNotFound,std::vector<FileInfo> & THMNotFound,unordered_map<string,CloudPhotoFileExistFlag> & resultExistMap)612 void CloneRestore::CloudPhotoFilesVerify(const std::vector<FileInfo> &fileInfos, std::vector<FileInfo> &LCDNotFound,
613     std::vector<FileInfo> &THMNotFound, unordered_map<string, CloudPhotoFileExistFlag> &resultExistMap)
614 {
615     for (size_t i = 0; i < fileInfos.size(); i++) {
616         CHECK_AND_CONTINUE(fileInfos[i].needMove);
617         CloudPhotoFileExistFlag fileExistFlag;
618         unordered_map<string, CloudPhotoFileExistFlag>::iterator iter = resultExistMap.find(fileInfos[i].cloudPath);
619         CHECK_AND_EXECUTE(iter == resultExistMap.end(), fileExistFlag = iter->second);
620         GetCloudPhotoFileExistFlag(fileInfos[i], fileExistFlag);
621         resultExistMap[fileInfos[i].cloudPath] = fileExistFlag;
622         if (HasExThumbnail(fileInfos[i])) {
623             CHECK_AND_EXECUTE(fileExistFlag.isExLcdExist, LCDNotFound.push_back(fileInfos[i]));
624             CHECK_AND_EXECUTE(fileExistFlag.isExThmExist, THMNotFound.push_back(fileInfos[i]));
625         } else {
626             CHECK_AND_EXECUTE(fileExistFlag.isLcdExist, LCDNotFound.push_back(fileInfos[i]));
627             CHECK_AND_EXECUTE(fileExistFlag.isThmExist, THMNotFound.push_back(fileInfos[i]));
628         }
629     }
630 }
631 
MoveMigrateCloudFile(std::vector<FileInfo> & fileInfos,int32_t & fileMoveCount,int32_t & videoFileMoveCount,int32_t sceneCode)632 void CloneRestore::MoveMigrateCloudFile(std::vector<FileInfo> &fileInfos, int32_t &fileMoveCount,
633     int32_t &videoFileMoveCount, int32_t sceneCode)
634 {
635     MEDIA_INFO_LOG("singleClone MoveMigrateCloudFile start");
636     unordered_map<string, CloudPhotoFileExistFlag> resultExistMap;
637     for (size_t i = 0; i < fileInfos.size(); i++) {
638         CHECK_AND_CONTINUE(fileInfos[i].needMove);
639         MoveCloudThumbnailDir(fileInfos[i]);
640         CHECK_AND_CONTINUE_ERR_LOG(isInitKvstoreSuccess_,
641             "singleClone isInitKvstoreSuccess_ false, id:%{public}d, path:%{public}s",
642             fileInfos[i].fileIdNew, MediaFileUtils::DesensitizePath(fileInfos[i].cloudPath).c_str());
643 
644         CHECK_AND_CONTINUE_ERR_LOG(fileInfos[i].thumbnailReady >= RESTORE_THUMBNAIL_READY_SUCCESS,
645             "singleClone Astc does not exist, id:%{public}d, path:%{public}s",
646                 fileInfos[i].fileIdNew, MediaFileUtils::DesensitizePath(fileInfos[i].cloudPath).c_str());
647         if (MoveAstc(fileInfos[i]) != E_OK) {
648             UpdateThumbnailStatusToFailed(mediaLibraryRdb_, to_string(fileInfos[i].fileIdNew), true, false);
649             MEDIA_ERR_LOG("Move astc failed, id:%{public}d, path:%{public}s",
650                 fileInfos[i].fileIdNew, MediaFileUtils::DesensitizePath(fileInfos[i].cloudPath).c_str());
651         }
652         CloudPhotoFileExistFlag tmpFlag;
653         tmpFlag.isYearAstcExist = true;
654         resultExistMap[fileInfos[i].cloudPath] = tmpFlag;
655         videoFileMoveCount += fileInfos[i].fileType == MediaType::MEDIA_TYPE_VIDEO;
656     }
657     std::vector<FileInfo> LCDNotFound;
658     std::vector<FileInfo> THMNotFound;
659     CloudPhotoFilesVerify(fileInfos, LCDNotFound, THMNotFound, resultExistMap);
660     MEDIA_INFO_LOG("singleClone LCDNotFound:%{public}zu, THMNotFound:%{public}zu",
661         LCDNotFound.size(), THMNotFound.size());
662     std::vector<std::string> dentryFailedLCD;
663     std::vector<std::string> dentryFailedThumb;
664     CHECK_AND_EXECUTE(BatchCreateDentryFile(LCDNotFound, dentryFailedLCD, DENTRY_INFO_LCD) != E_OK,
665         HandleFailData(fileInfos, dentryFailedLCD, DENTRY_INFO_LCD));
666     CHECK_AND_EXECUTE(BatchCreateDentryFile(THMNotFound, dentryFailedThumb, DENTRY_INFO_THM) != E_OK,
667         HandleFailData(fileInfos, dentryFailedThumb, DENTRY_INFO_THM));
668 
669     BatchUpdateFileInfoData(fileInfos, resultExistMap);
670     fileMoveCount = SetVisiblePhoto(fileInfos);
671     successCloudMetaNumber_ += fileMoveCount;
672     migrateFileNumber_ += fileMoveCount;
673     migrateVideoFileNumber_ += videoFileMoveCount;
674     MEDIA_INFO_LOG("singleClone MoveMigrateCloudFile end");
675 }
676 
InsertPhoto(vector<FileInfo> & fileInfos)677 int CloneRestore::InsertPhoto(vector<FileInfo> &fileInfos)
678 {
679     CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, E_OK, "mediaLibraryRdb_ is null");
680     CHECK_AND_RETURN_RET_LOG(!fileInfos.empty(), E_OK, "fileInfos are empty");
681     int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
682     vector<NativeRdb::ValuesBucket> values = GetInsertValues(CLONE_RESTORE_ID, fileInfos, SourceType::PHOTOS);
683     int64_t startInsertPhoto = MediaFileUtils::UTCTimeMilliSeconds();
684     int64_t photoRowNum = 0;
685     int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, photoRowNum);
686     if (errCode != E_OK) {
687         if (needReportFailed_) {
688             UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
689             ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(fileInfos.size()), errCode);
690             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
691         }
692         return errCode;
693     }
694     migrateDatabaseNumber_ += photoRowNum;
695 
696     int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
697     InsertPhotoRelated(fileInfos, SourceType::PHOTOS);
698 
699     int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
700     int64_t fileMoveCount = 0;
701     int64_t videoFileMoveCount = 0;
702     MoveMigrateFile(fileInfos, fileMoveCount, videoFileMoveCount);
703     int64_t startUpdate = MediaFileUtils::UTCTimeMilliSeconds();
704     UpdatePhotosByFileInfoMap(mediaLibraryRdb_, fileInfos);
705     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
706     MEDIA_INFO_LOG("generate cost %{public}ld, insert %{public}ld assets cost %{public}ld, insert photo related cost "
707         "%{public}ld, and move %{public}ld files (%{public}ld + %{public}ld) cost %{public}ld. update cost %{public}ld",
708         (long)(startInsertPhoto - startGenerate), (long)photoRowNum, (long)(startInsertRelated - startInsertPhoto),
709         (long)(startMove - startInsertRelated), (long)fileMoveCount, (long)(fileMoveCount - videoFileMoveCount),
710         (long)videoFileMoveCount, (long)(startUpdate - startMove), (long)(end - startUpdate));
711     return E_OK;
712 }
713 
GetInsertValues(int32_t sceneCode,vector<FileInfo> & fileInfos,int32_t sourceType)714 vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(int32_t sceneCode, vector<FileInfo> &fileInfos,
715     int32_t sourceType)
716 {
717     vector<NativeRdb::ValuesBucket> values;
718     for (size_t i = 0; i < fileInfos.size(); i++) {
719         int32_t errCode = BackupFileUtils::IsFileValid(fileInfos[i].filePath, CLONE_RESTORE_ID);
720         if (errCode != E_OK) {
721             ErrorInfo errorInfo(RestoreError::FILE_INVALID, 1, std::to_string(errCode),
722                 BackupLogUtils::FileInfoToString(sceneCode, fileInfos[i]));
723             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
724             continue;
725         }
726         CHECK_AND_CONTINUE(PrepareCloudPath(PhotoColumn::PHOTOS_TABLE, fileInfos[i]));
727         if (fileInfos[i].isNew) {
728             NativeRdb::ValuesBucket value = GetInsertValue(fileInfos[i], fileInfos[i].cloudPath, sourceType);
729             values.emplace_back(value);
730         }
731     }
732     return values;
733 }
734 
GetCloudInsertValues(int32_t sceneCode,vector<FileInfo> & fileInfos,int32_t sourceType)735 vector<NativeRdb::ValuesBucket> CloneRestore::GetCloudInsertValues(int32_t sceneCode, vector<FileInfo> &fileInfos,
736     int32_t sourceType)
737 {
738     MEDIA_INFO_LOG("singleClone GetCloudInsertValues: %{public}zu", fileInfos.size());
739     vector<NativeRdb::ValuesBucket> values;
740     for (size_t i = 0; i < fileInfos.size(); i++) {
741         CHECK_AND_CONTINUE(PrepareCloudPath(PhotoColumn::PHOTOS_TABLE, fileInfos[i]));
742         NativeRdb::ValuesBucket value = GetCloudInsertValue(fileInfos[i], fileInfos[i].cloudPath, sourceType);
743         fileInfos[i].isNew = true;
744         values.emplace_back(value);
745     }
746     return values;
747 }
748 
HandleRestData(void)749 void CloneRestore::HandleRestData(void)
750 {
751     MEDIA_INFO_LOG("Start to handle rest data in native.");
752 }
753 
QueryFileInfos(int32_t offset,int32_t isRelatedToPhotoMap)754 vector<FileInfo> CloneRestore::QueryFileInfos(int32_t offset, int32_t isRelatedToPhotoMap)
755 {
756     vector<FileInfo> result;
757     result.reserve(CLONE_QUERY_COUNT);
758     std::shared_ptr<NativeRdb::ResultSet> resultSet;
759     if (isRelatedToPhotoMap == 1) {
760         resultSet = this->photosClone_.GetPhotosInPhotoMap(offset, CLONE_QUERY_COUNT);
761     } else {
762         resultSet = this->photosClone_.GetPhotosNotInPhotoMap(offset, CLONE_QUERY_COUNT);
763     }
764     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
765     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
766         FileInfo fileInfo;
767         fileInfo.isRelatedToPhotoMap = isRelatedToPhotoMap;
768         CHECK_AND_EXECUTE(!ParseResultSet(resultSet, fileInfo), result.emplace_back(fileInfo));
769     }
770     return result;
771 }
772 
QueryCloudFileInfos(int32_t offset,int32_t isRelatedToPhotoMap)773 vector<FileInfo> CloneRestore::QueryCloudFileInfos(int32_t offset, int32_t isRelatedToPhotoMap)
774 {
775     MEDIA_INFO_LOG("singleClone QueryCloudFileInfos");
776     vector<FileInfo> result;
777     result.reserve(CLONE_QUERY_COUNT);
778     std::shared_ptr<NativeRdb::ResultSet> resultSet;
779     if (isRelatedToPhotoMap == 1) {
780         resultSet = this->photosClone_.GetCloudPhotosInPhotoMap(offset, CLONE_QUERY_COUNT);
781     } else {
782         resultSet = this->photosClone_.GetCloudPhotosNotInPhotoMap(offset, CLONE_QUERY_COUNT);
783     }
784     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "singleClone Query resultSql is null.");
785     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
786         FileInfo fileInfo;
787         fileInfo.isRelatedToPhotoMap = isRelatedToPhotoMap;
788         CHECK_AND_EXECUTE(!ParseResultSet(resultSet, fileInfo), result.emplace_back(fileInfo));
789     }
790     return result;
791 }
792 
ParseResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo,string dbName)793 bool CloneRestore::ParseResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &fileInfo,
794     string dbName)
795 {
796     return ParseResultSet(PhotoColumn::PHOTOS_TABLE, resultSet, fileInfo);
797 }
798 
QueryTotalNumber(const string & tableName)799 int32_t CloneRestore::QueryTotalNumber(const string &tableName)
800 {
801     CHECK_AND_RETURN_RET(tableName != PhotoAlbumColumns::TABLE,
802         this->photoAlbumClone_.GetPhotoAlbumCountInOriginalDb());
803     CHECK_AND_RETURN_RET(tableName != PhotoColumn::PHOTOS_TABLE,
804         this->photosClone_.GetPhotosRowCountNotInPhotoMap());
805     string querySql = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + tableName;
806     string whereClause = GetQueryWhereClauseByTable(tableName);
807     querySql += whereClause.empty() ? "" : " WHERE " + whereClause;
808     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
809     if (resultSet == nullptr) {
810         return 0;
811     }
812     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
813         resultSet->Close();
814         return 0;
815     }
816     int32_t result = GetInt32Val(MEDIA_COLUMN_COUNT_1, resultSet);
817     resultSet->Close();
818     return result;
819 }
820 
QueryAlbumInfos(const string & tableName,int32_t offset)821 vector<AlbumInfo> CloneRestore::QueryAlbumInfos(const string &tableName, int32_t offset)
822 {
823     vector<AlbumInfo> result;
824     result.reserve(CLONE_QUERY_COUNT);
825     std::shared_ptr<NativeRdb::ResultSet> resultSet = nullptr;
826     if (tableName == PhotoAlbumColumns::TABLE) {
827         resultSet = this->photoAlbumClone_.GetPhotoAlbumInOriginalDb(offset, CLONE_QUERY_COUNT);
828     } else {
829         string querySql = "SELECT * FROM " + tableName;
830         string whereClause = GetQueryWhereClauseByTable(tableName);
831         querySql += whereClause.empty() ? "" : " WHERE " + whereClause;
832         querySql += " LIMIT " + to_string(offset) + ", " + to_string(CLONE_QUERY_COUNT);
833         resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
834     }
835     if (resultSet == nullptr) {
836         MEDIA_ERR_LOG("Query resultSql is null.");
837         return result;
838     }
839     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
840         AlbumInfo albumInfo;
841         if (ParseAlbumResultSet(tableName, resultSet, albumInfo)) {
842             result.emplace_back(albumInfo);
843         }
844     }
845     resultSet->Close();
846     return result;
847 }
848 
ParseAlbumResultSet(const string & tableName,const shared_ptr<NativeRdb::ResultSet> & resultSet,AlbumInfo & albumInfo)849 bool CloneRestore::ParseAlbumResultSet(const string &tableName, const shared_ptr<NativeRdb::ResultSet> &resultSet,
850     AlbumInfo &albumInfo)
851 {
852     albumInfo.albumIdOld = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
853     albumInfo.albumName = GetStringVal(PhotoAlbumColumns::ALBUM_NAME, resultSet);
854     albumInfo.albumType = static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet));
855     albumInfo.albumSubType = static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet));
856     albumInfo.lPath = GetStringVal(PhotoAlbumColumns::ALBUM_LPATH, resultSet);
857     albumInfo.albumBundleName = GetStringVal(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, resultSet);
858     albumInfo.dateModified = GetInt64Val(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, resultSet);
859 
860     auto commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
861     for (auto it = commonColumnInfoMap.begin(); it != commonColumnInfoMap.end(); ++it) {
862         string columnName = it->first;
863         string columnType = it->second;
864         GetValFromResultSet(resultSet, albumInfo.valMap, columnName, columnType);
865     }
866     return true;
867 }
868 
AnalyzeSource()869 void CloneRestore::AnalyzeSource()
870 {
871     MEDIA_INFO_LOG("analyze source later");
872 }
873 
MovePicture(FileInfo & fileInfo)874 int32_t CloneRestore::MovePicture(FileInfo &fileInfo)
875 {
876     bool deleteOriginalFile = fileInfo.isRelatedToPhotoMap == 1 ? false : true;
877     string localPath = BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL,
878         fileInfo.cloudPath);
879     int32_t opRet = E_FAIL;
880     if (deleteOriginalFile) {
881         opRet = this->MoveFile(fileInfo.filePath, localPath);
882     } else {
883         opRet = this->CopyFile(fileInfo.filePath, localPath);
884     }
885     CHECK_AND_RETURN_RET_LOG(opRet == E_OK, E_FAIL,
886         "Move photo file failed, filePath = %{public}s, deleteOriginalFile = %{public}d",
887         BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str(),
888         deleteOriginalFile);
889     return E_OK;
890 }
891 
MoveMovingPhotoVideo(FileInfo & fileInfo)892 int32_t CloneRestore::MoveMovingPhotoVideo(FileInfo &fileInfo)
893 {
894     CHECK_AND_RETURN_RET(fileInfo.subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO), E_OK);
895     bool deleteOriginalFile = fileInfo.isRelatedToPhotoMap == 1 ? false : true;
896     std::string localPath = BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL,
897         fileInfo.cloudPath);
898     std::string srcLocalVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(fileInfo.filePath);
899     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(srcLocalVideoPath), E_OK,
900         "video of moving photo does not exist: %{private}s", srcLocalVideoPath.c_str());
901     std::string localVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(localPath);
902     int32_t opVideoRet = E_FAIL;
903     if (deleteOriginalFile) {
904         opVideoRet = this->MoveFile(srcLocalVideoPath, localVideoPath);
905     } else {
906         opVideoRet = this->CopyFile(srcLocalVideoPath, localVideoPath);
907     }
908     CHECK_AND_RETURN_RET_LOG(opVideoRet == E_OK, E_FAIL, "Move video of moving photo failed");
909     BackupFileUtils::ModifyFile(localVideoPath, fileInfo.dateModified / MSEC_TO_SEC);
910     return E_OK;
911 }
912 
MoveEditedData(FileInfo & fileInfo)913 int32_t CloneRestore::MoveEditedData(FileInfo &fileInfo)
914 {
915     bool deleteOriginalFile = fileInfo.isRelatedToPhotoMap == 1 ? false : true;
916     string localPath =
917         BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL, fileInfo.cloudPath);
918     string srcEditDataPath = this->backupRestoreDir_ +
919         BackupFileUtils::GetFullPathByPrefixType(PrefixType::LOCAL_EDIT_DATA, fileInfo.relativePath);
920     string dstEditDataPath = BackupFileUtils::GetReplacedPathByPrefixType(
921         PrefixType::CLOUD, PrefixType::LOCAL_EDIT_DATA, fileInfo.cloudPath);
922     bool cond = (this->IsFilePathExist(srcEditDataPath) &&
923         this->MoveDirectory(srcEditDataPath, dstEditDataPath, deleteOriginalFile) != E_OK);
924     CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "Move editData file failed");
925     return E_OK;
926 }
927 
GetThumbnailLocalPath(const string path)928 std::string CloneRestore::GetThumbnailLocalPath(const string path)
929 {
930     size_t cloudDirLength = RESTORE_FILES_CLOUD_DIR.length();
931     if (path.length() <= cloudDirLength || path.substr(0, cloudDirLength).compare(RESTORE_FILES_CLOUD_DIR) != 0) {
932         return "";
933     }
934 
935     std::string suffixStr = path.substr(cloudDirLength);
936     return RESTORE_FILES_LOCAL_DIR + ".thumbs/" + suffixStr;
937 }
938 
MoveAstc(FileInfo & fileInfo)939 int32_t CloneRestore::MoveAstc(FileInfo &fileInfo)
940 {
941     bool cond = (oldMonthKvStorePtr_ == nullptr || oldYearKvStorePtr_ == nullptr ||
942         newMonthKvStorePtr_ == nullptr || newYearKvStorePtr_ == nullptr);
943     CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "Kvstore is nullptr");
944     if (fileInfo.fileIdOld <= 0 || fileInfo.fileIdNew <= 0) {
945         MEDIA_ERR_LOG("Old fileId:%{public}d or new fileId:%{public}d is invalid",
946             fileInfo.fileIdOld, fileInfo.fileIdNew);
947         return E_FAIL;
948     }
949 
950     string oldKey;
951     string newKey;
952     if (!MediaFileUtils::GenerateKvStoreKey(to_string(fileInfo.fileIdOld), fileInfo.oldAstcDateKey, oldKey) ||
953         !MediaFileUtils::GenerateKvStoreKey(to_string(fileInfo.fileIdNew), fileInfo.newAstcDateKey, newKey)) {
954         return E_FAIL;
955     }
956 
957     std::vector<uint8_t> monthValue;
958     std::vector<uint8_t> yearValue;
959     if (oldMonthKvStorePtr_->Query(oldKey, monthValue) != E_OK ||
960         newMonthKvStorePtr_->Insert(newKey, monthValue) != E_OK) {
961         MEDIA_ERR_LOG("MonthValue move failed, fileID %{public}s", newKey.c_str());
962         return E_FAIL;
963     }
964     if (oldYearKvStorePtr_->Query(oldKey, yearValue) != E_OK ||
965         newYearKvStorePtr_->Insert(newKey, yearValue) != E_OK) {
966         MEDIA_ERR_LOG("YearValue move failed, fileID %{public}s", newKey.c_str());
967         return E_FAIL;
968     }
969     if (fileInfo.isRelatedToPhotoMap != 1) {
970         oldMonthKvStorePtr_->Delete(oldKey);
971         oldYearKvStorePtr_->Delete(oldKey);
972     }
973     return E_OK;
974 }
975 
MoveThumbnailDir(FileInfo & fileInfo)976 int32_t CloneRestore::MoveThumbnailDir(FileInfo &fileInfo)
977 {
978     string thumbnailOldDir = backupRestoreDir_ + RESTORE_FILES_LOCAL_DIR + ".thumbs" + fileInfo.relativePath;
979     string thumbnailNewDir = GetThumbnailLocalPath(fileInfo.cloudPath);
980     if (fileInfo.relativePath.empty() || thumbnailNewDir.empty()) {
981         MEDIA_ERR_LOG("Old path:%{public}s or new path:%{public}s is invalid",
982             fileInfo.relativePath.c_str(), MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
983         return E_FAIL;
984     }
985     if (!MediaFileUtils::IsDirectory(thumbnailOldDir)) {
986         MEDIA_ERR_LOG("Old dir is not a direcrory or does not exist, errno:%{public}d, dir:%{public}s",
987             errno, MediaFileUtils::DesensitizePath(thumbnailOldDir).c_str());
988         return E_FAIL;
989     }
990     CHECK_AND_RETURN_RET_LOG(BackupFileUtils::PreparePath(thumbnailNewDir) == E_OK, E_FAIL,
991         "Prepare thumbnail dir path failed");
992     bool cond = (MediaFileUtils::IsFileExists(thumbnailNewDir) && !MediaFileUtils::DeleteDir(thumbnailNewDir));
993     CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "Delete thumbnail new dir failed, errno:%{public}d", errno);
994 
995     int32_t opRet = E_FAIL;
996     if (fileInfo.isRelatedToPhotoMap != 1) {
997         opRet = MediaFileUtils::ModifyAsset(thumbnailOldDir, thumbnailNewDir);
998     } else {
999         opRet = MediaFileUtils::CopyDirectory(thumbnailOldDir, thumbnailNewDir);
1000     }
1001     if (opRet != E_OK) {
1002         CHECK_AND_RETURN_RET(MediaFileUtils::IsFileExists(thumbnailNewDir), opRet);
1003         MEDIA_WARN_LOG("MoveThumbnailDir failed but thumbnailNewDir exists");
1004         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteDir(thumbnailNewDir),
1005             "Delete existential thumbnailNewDir failed, errno:%{public}d", errno);
1006         return opRet;
1007     }
1008     return E_OK;
1009 }
1010 
MoveCloudThumbnailDir(FileInfo & fileInfo)1011 int32_t CloneRestore::MoveCloudThumbnailDir(FileInfo &fileInfo)
1012 {
1013     string thumbnailOldDir = backupRestoreDir_ + RESTORE_FILES_LOCAL_DIR + ".thumbs" + fileInfo.relativePath;
1014     string thumbnailNewDir = GetThumbnailLocalPath(fileInfo.cloudPath);
1015     bool cond = (fileInfo.relativePath.empty() || thumbnailNewDir.empty());
1016     CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "singleCloud Old path:%{public}s or new path:%{public}s is invalid",
1017         fileInfo.relativePath.c_str(), MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1018 
1019     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsDirectory(thumbnailOldDir), E_FAIL,
1020         "singleCloud Old dir is not a direcrory or does not exist, errno:%{public}d, dir:%{public}s",
1021         errno, MediaFileUtils::DesensitizePath(thumbnailOldDir).c_str());
1022 
1023     CHECK_AND_RETURN_RET_LOG(BackupFileUtils::PreparePath(thumbnailNewDir) == E_OK, E_FAIL,
1024         "singleCloud Prepare thumbnail dir path failed");
1025     cond = (MediaFileUtils::IsFileExists(thumbnailNewDir) && !MediaFileUtils::DeleteDir(thumbnailNewDir));
1026     CHECK_AND_RETURN_RET_LOG(!cond, E_FAIL, "singleCloud Delete thumbnail new dir failed, errno:%{public}d", errno);
1027 
1028     int32_t opRet = E_FAIL;
1029     if (fileInfo.isRelatedToPhotoMap != 1) {
1030         opRet = MediaFileUtils::ModifyAsset(thumbnailOldDir, thumbnailNewDir);
1031     } else {
1032         opRet = MediaFileUtils::CopyDirectory(thumbnailOldDir, thumbnailNewDir);
1033     }
1034     if (opRet != E_OK) {
1035         CHECK_AND_RETURN_RET(MediaFileUtils::IsFileExists(thumbnailNewDir), opRet);
1036         MEDIA_WARN_LOG("singleCloud MoveThumbnailDir failed but thumbnailNewDir exists");
1037         return opRet;
1038     }
1039     return E_OK;
1040 }
1041 
1042 /**
1043  * The processing logic of the MoveThumbnail function must match the logic of the GetThumbnailInsertValue function.
1044  * If the status indicates that the thumbnail does not exist, the thumbnail does not need to be cloned and
1045  * the status of the thumbnail needs to be set to the initial status in the GetThumbnailInsertValue function.
1046  * If the status indicates that the thumbnail exists but the thumbnail fails to be transferred,
1047  * the thumbnail status needs to be set to the initial status.
1048 */
MoveThumbnail(FileInfo & fileInfo)1049 int32_t CloneRestore::MoveThumbnail(FileInfo &fileInfo)
1050 {
1051     CHECK_AND_RETURN_RET(hasCloneThumbnailDir_, E_NO_SUCH_FILE);
1052     if (fileInfo.thumbnailReady < RESTORE_THUMBNAIL_READY_SUCCESS &&
1053         fileInfo.lcdVisitTime < RESTORE_LCD_VISIT_TIME_SUCCESS) {
1054         MEDIA_INFO_LOG("Thumbnail dose not exist, id:%{public}d, path:%{public}s",
1055             fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1056         return E_NO_SUCH_FILE;
1057     }
1058     if (MoveThumbnailDir(fileInfo) != E_OK) {
1059         UpdateThumbnailStatusToFailed(mediaLibraryRdb_, to_string(fileInfo.fileIdNew), true, true);
1060         MEDIA_ERR_LOG("Move thumbnail failed, id:%{public}d, path:%{public}s",
1061             fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1062         return E_FAIL;
1063     }
1064 
1065     CHECK_AND_RETURN_RET(isInitKvstoreSuccess_, E_NO_SUCH_FILE);
1066     CHECK_AND_RETURN_RET_LOG(fileInfo.thumbnailReady >= RESTORE_THUMBNAIL_READY_SUCCESS, E_NO_SUCH_FILE,
1067         "Astc does not exist, id:%{public}d, path:%{public}s",
1068         fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1069     if (MoveAstc(fileInfo) != E_OK) {
1070         UpdateThumbnailStatusToFailed(mediaLibraryRdb_, to_string(fileInfo.fileIdNew), true, false);
1071         MEDIA_ERR_LOG("Move astc failed, id:%{public}d, path:%{public}s",
1072             fileInfo.fileIdNew, MediaFileUtils::DesensitizePath(fileInfo.cloudPath).c_str());
1073         return E_FAIL;
1074     }
1075 
1076     return E_OK;
1077 }
1078 
MoveAsset(FileInfo & fileInfo)1079 int32_t CloneRestore::MoveAsset(FileInfo &fileInfo)
1080 {
1081     // Picture files.
1082     int32_t optRet = this->MovePicture(fileInfo);
1083     CHECK_AND_RETURN_RET(optRet == E_OK, E_FAIL);
1084     // Video files of moving photo.
1085     optRet = this->MoveMovingPhotoVideo(fileInfo);
1086     CHECK_AND_RETURN_RET(optRet == E_OK, E_FAIL);
1087     // Edit Data.
1088     optRet = this->MoveEditedData(fileInfo);
1089     CHECK_AND_RETURN_RET(optRet == E_OK, E_FAIL);
1090     // Thumbnail of photos.
1091     this->MoveThumbnail(fileInfo);
1092 
1093     MediaLibraryPhotoOperations::StoreThumbnailAndEditSize(to_string(fileInfo.fileIdNew), fileInfo.cloudPath);
1094     return E_OK;
1095 }
1096 
IsFilePathExist(const string & filePath) const1097 bool CloneRestore::IsFilePathExist(const string &filePath) const
1098 {
1099     if (!MediaFileUtils::IsFileExists(filePath)) {
1100         MEDIA_DEBUG_LOG("%{private}s doesn't exist", filePath.c_str());
1101         return false;
1102     }
1103     bool cond = (MediaFileUtils::IsDirectory(filePath) && MediaFileUtils::IsDirEmpty(filePath));
1104     CHECK_AND_RETURN_RET_LOG(!cond, false, "%{private}s is an empty directory", filePath.c_str());
1105     return true;
1106 }
1107 
GetThumbnailInsertValue(const FileInfo & fileInfo,NativeRdb::ValuesBucket & values)1108 void CloneRestore::GetThumbnailInsertValue(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values)
1109 {
1110     if (!hasCloneThumbnailDir_) {
1111         // If there is no thumbnail directory, all statuses of thumbnail are set to the initial status.
1112         values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, RESTORE_LCD_VISIT_TIME_NO_LCD);
1113         values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, RESTORE_THUMBNAIL_READY_NO_THUMBNAIL);
1114         values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
1115         return;
1116     }
1117 
1118     // The LCD status is same as the origin status.
1119     values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, fileInfo.lcdVisitTime);
1120     if (!isInitKvstoreSuccess_ || fileInfo.thumbnailReady < RESTORE_THUMBNAIL_READY_SUCCESS) {
1121         // The kvdb does not exist or the THM status indicates that there is no THM.
1122         // Therefore, the THM status needs to be set to the initial status.
1123         values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, RESTORE_THUMBNAIL_READY_NO_THUMBNAIL);
1124         values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
1125         return;
1126     }
1127     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, fileInfo.thumbnailReady);
1128     values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_TRUE);
1129 }
1130 
GetCloudThumbnailInsertValue(const FileInfo & fileInfo,NativeRdb::ValuesBucket & values)1131 void CloneRestore::GetCloudThumbnailInsertValue(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values)
1132 {
1133     values.PutInt(PhotoColumn::PHOTO_POSITION, fileInfo.position);
1134     values.PutString(PhotoColumn::PHOTO_CLOUD_ID, fileInfo.cloudId);
1135     values.PutInt(PhotoColumn::PHOTO_CLOUD_VERSION, fileInfo.cloudVersion);
1136     values.PutInt(PhotoColumn::PHOTO_DIRTY, 0);
1137     values.PutInt(PhotoColumn::PHOTO_CLEAN_FLAG, 0);
1138     values.PutInt(PhotoColumn::PHOTO_THUMB_STATUS, RESTORE_THUMBNAIL_STATUS_NOT_ALL);
1139     values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
1140     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, 0);
1141     values.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, RESTORE_THUMBNAIL_VISIBLE_FALSE);
1142     values.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, 0);
1143 }
1144 
PrepareShootingModeVal(const FileInfo & fileInfo,NativeRdb::ValuesBucket & values)1145 void CloneRestore::PrepareShootingModeVal(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values)
1146 {
1147     values.Delete(PhotoColumn::PHOTO_SHOOTING_MODE);
1148     auto it = fileInfo.valMap.find(PhotoColumn::PHOTO_SHOOTING_MODE_TAG);
1149     if (it == fileInfo.valMap.end()) {
1150         values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, "");
1151         return;
1152     }
1153     string shootingModeTag = get<string>(it->second);
1154     values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE,
1155         ShootingModeAlbum::MapShootingModeTagToShootingMode(shootingModeTag));
1156 }
1157 
GetInsertValueFromValMap(const FileInfo & fileInfo,NativeRdb::ValuesBucket & values)1158 void CloneRestore::GetInsertValueFromValMap(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values)
1159 {
1160     unordered_map<string, string> commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_,
1161         PhotoColumn::PHOTOS_TABLE);
1162     for (auto it = fileInfo.valMap.begin(); it != fileInfo.valMap.end(); ++it) {
1163         string columnName = it->first;
1164         auto columnVal = it->second;
1165         if (columnName == PhotoColumn::PHOTO_EDIT_TIME) {
1166             PrepareEditTimeVal(values, get<int64_t>(columnVal), fileInfo, commonColumnInfoMap);
1167             continue;
1168         }
1169         if (columnName == PhotoColumn::MEDIA_DATE_TAKEN) {
1170             if (get<int64_t>(columnVal) > SECONDS_LEVEL_LIMIT) {
1171                 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, get<int64_t>(columnVal));
1172             } else {
1173                 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, get<int64_t>(columnVal) * MSEC_TO_SEC);
1174             }
1175             continue;
1176         }
1177         PrepareCommonColumnVal(values, columnName, columnVal, commonColumnInfoMap);
1178     }
1179     PrepareShootingModeVal(fileInfo, values);
1180 }
1181 
GetInsertValue(const FileInfo & fileInfo,const string & newPath,int32_t sourceType)1182 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const FileInfo &fileInfo, const string &newPath,
1183     int32_t sourceType)
1184 {
1185     NativeRdb::ValuesBucket values;
1186     values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
1187     values.PutLong(MediaColumn::MEDIA_SIZE, fileInfo.fileSize);
1188     values.PutInt(MediaColumn::MEDIA_TYPE, fileInfo.fileType);
1189     values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
1190     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(fileInfo.displayName));
1191     values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateAdded);
1192     values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, fileInfo.dateModified);
1193     values.PutInt(PhotoColumn::PHOTO_ORIENTATION, fileInfo.orientation); // photos need orientation
1194     values.PutInt(PhotoColumn::PHOTO_EXIF_ROTATE, fileInfo.exifRotate);
1195     values.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileInfo.subtype);
1196     // use owner_album_id to mark the album id which the photo is in.
1197     values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, fileInfo.ownerAlbumId);
1198     // Only SOURCE album has package_name and owner_package.
1199     values.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileInfo.packageName);
1200     values.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileInfo.bundleName);
1201     if (fileInfo.packageName.empty() && fileInfo.bundleName.empty()) {
1202     // package_name and owner_package are empty, clear owner_appid
1203         values.PutString(MediaColumn::MEDIA_OWNER_APPID, "");
1204     }
1205     values.PutInt(PhotoColumn::PHOTO_QUALITY, fileInfo.photoQuality);
1206     values.PutInt(PhotoColumn::STAGE_VIDEO_TASK_STATUS, static_cast<int32_t>(StageVideoTaskStatus::NO_NEED_TO_STAGE));
1207     values.PutLong(MediaColumn::MEDIA_DATE_TRASHED, fileInfo.recycledTime);
1208     values.PutInt(MediaColumn::MEDIA_HIDDEN, fileInfo.hidden);
1209     values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, fileInfo.sourcePath);
1210     values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
1211     GetThumbnailInsertValue(fileInfo, values);
1212     GetInsertValueFromValMap(fileInfo, values);
1213     return values;
1214 }
1215 
GetCloudInsertValue(const FileInfo & fileInfo,const string & newPath,int32_t sourceType)1216 NativeRdb::ValuesBucket CloneRestore::GetCloudInsertValue(const FileInfo &fileInfo, const string &newPath,
1217     int32_t sourceType)
1218 {
1219     NativeRdb::ValuesBucket values;
1220     values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
1221     values.PutLong(MediaColumn::MEDIA_SIZE, fileInfo.fileSize);
1222     values.PutInt(MediaColumn::MEDIA_TYPE, fileInfo.fileType);
1223     values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
1224     values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateAdded);
1225     values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, fileInfo.dateModified);
1226     values.PutInt(PhotoColumn::PHOTO_ORIENTATION, fileInfo.orientation); // photos need orientation
1227     values.PutInt(PhotoColumn::PHOTO_EXIF_ROTATE, fileInfo.exifRotate);
1228     values.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileInfo.subtype);
1229     // use owner_album_id to mark the album id which the photo is in.
1230     values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, fileInfo.ownerAlbumId);
1231     // Only SOURCE album has package_name and owner_package.
1232     values.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileInfo.packageName);
1233     values.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileInfo.bundleName);
1234 
1235     bool cond = (fileInfo.packageName.empty() && fileInfo.bundleName.empty());
1236     // package_name and owner_package are empty, clear owner_appid
1237     CHECK_AND_EXECUTE(!cond, values.PutString(MediaColumn::MEDIA_OWNER_APPID, ""));
1238     values.PutInt(PhotoColumn::PHOTO_QUALITY, fileInfo.photoQuality);
1239     values.PutLong(MediaColumn::MEDIA_DATE_TRASHED, fileInfo.recycledTime);
1240     values.PutInt(MediaColumn::MEDIA_HIDDEN, fileInfo.hidden);
1241     values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, fileInfo.sourcePath);
1242     values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
1243     GetCloudThumbnailInsertValue(fileInfo, values);
1244     GetInsertValueFromValMap(fileInfo, values);
1245     return values;
1246 }
1247 
PrepareCommonColumnInfoMap(const string & tableName,const unordered_map<string,string> & srcColumnInfoMap,const unordered_map<string,string> & dstColumnInfoMap)1248 bool CloneRestore::PrepareCommonColumnInfoMap(const string &tableName,
1249     const unordered_map<string, string> &srcColumnInfoMap, const unordered_map<string, string> &dstColumnInfoMap)
1250 {
1251     auto neededColumns = GetValueFromMap(NEEDED_COLUMNS_MAP, tableName);
1252     auto neededColumnsException = GetValueFromMap(NEEDED_COLUMNS_EXCEPTION_MAP, tableName);
1253     auto excludedColumns = GetValueFromMap(EXCLUDED_COLUMNS_MAP, tableName);
1254     auto &commonColumnInfoMap = tableCommonColumnInfoMap_[tableName];
1255     CHECK_AND_RETURN_RET_LOG(HasColumns(dstColumnInfoMap, neededColumns), false, "Destination lack needed columns");
1256     for (auto it = dstColumnInfoMap.begin(); it != dstColumnInfoMap.end(); ++it) {
1257         if (!HasSameColumn(srcColumnInfoMap, it->first, it->second) || excludedColumns.count(it->first) > 0) {
1258             continue;
1259         }
1260         if (neededColumns.count(it->first) > 0 && (neededColumnsException.empty() ||
1261             neededColumnsException.count(it->first) == 0)) {
1262             continue;
1263         }
1264         commonColumnInfoMap[it->first] = it->second;
1265     }
1266     MEDIA_INFO_LOG("Table %{public}s has %{public}zu common columns",
1267         BackupDatabaseUtils::GarbleInfoName(tableName).c_str(), commonColumnInfoMap.size());
1268     return true;
1269 }
1270 
HasSameColumn(const unordered_map<string,string> & columnInfoMap,const string & columnName,const string & columnType)1271 bool CloneRestore::HasSameColumn(const unordered_map<string, string> &columnInfoMap, const string &columnName,
1272     const string &columnType)
1273 {
1274     auto it = columnInfoMap.find(columnName);
1275     return it != columnInfoMap.end() && it->second == columnType;
1276 }
1277 
GetValFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,unordered_map<string,variant<int32_t,int64_t,double,string>> & valMap,const string & columnName,const string & columnType)1278 void CloneRestore::GetValFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
1279     unordered_map<string, variant<int32_t, int64_t, double, string>> &valMap, const string &columnName,
1280     const string &columnType)
1281 {
1282     int32_t columnIndex = 0;
1283     int32_t errCode = resultSet->GetColumnIndex(columnName, columnIndex);
1284     CHECK_AND_RETURN_LOG(errCode == 0, "Get column index errCode: %{public}d", errCode);
1285     bool isNull = false;
1286     errCode = resultSet->IsColumnNull(columnIndex, isNull);
1287     if (errCode || isNull) {
1288         return;
1289     }
1290     ResultSetDataType dataType = GetValueFromMap(COLUMN_TYPE_MAP, columnType, ResultSetDataType::TYPE_NULL);
1291     switch (dataType) {
1292         case ResultSetDataType::TYPE_INT32: {
1293             int32_t int32Val;
1294             if (resultSet->GetInt(columnIndex, int32Val) == E_OK) {
1295                 valMap[columnName] = int32Val;
1296             }
1297             break;
1298         }
1299         case ResultSetDataType::TYPE_INT64: {
1300             int64_t int64Val;
1301             if (resultSet->GetLong(columnIndex, int64Val) == E_OK) {
1302                 valMap[columnName] = int64Val;
1303             }
1304             break;
1305         }
1306         case ResultSetDataType::TYPE_DOUBLE: {
1307             double doubleVal;
1308             if (resultSet->GetDouble(columnIndex, doubleVal) == E_OK) {
1309                 valMap[columnName] = doubleVal;
1310             }
1311             break;
1312         }
1313         case ResultSetDataType::TYPE_STRING: {
1314             string stringVal;
1315             if (resultSet->GetString(columnIndex, stringVal) == E_OK) {
1316                 valMap[columnName] = stringVal;
1317             }
1318             break;
1319         }
1320         default:
1321             MEDIA_ERR_LOG("No such column type: %{public}s", columnType.c_str());
1322     }
1323 }
1324 
PrepareCommonColumnVal(NativeRdb::ValuesBucket & values,const string & columnName,const variant<int32_t,int64_t,double,string> & columnVal,const unordered_map<string,string> & commonColumnInfoMap) const1325 void CloneRestore::PrepareCommonColumnVal(NativeRdb::ValuesBucket &values, const string &columnName,
1326     const variant<int32_t, int64_t, double, string> &columnVal,
1327     const unordered_map<string, string> &commonColumnInfoMap) const
1328 {
1329     string columnType = GetValueFromMap(commonColumnInfoMap, columnName);
1330     CHECK_AND_RETURN_LOG(!columnType.empty(), "No such column %{public}s", columnName.c_str());
1331     ResultSetDataType dataType = GetValueFromMap(COLUMN_TYPE_MAP, columnType, ResultSetDataType::TYPE_NULL);
1332     switch (dataType) {
1333         case ResultSetDataType::TYPE_INT32: {
1334             values.PutInt(columnName, get<int32_t>(columnVal));
1335             break;
1336         }
1337         case ResultSetDataType::TYPE_INT64: {
1338             values.PutLong(columnName, get<int64_t>(columnVal));
1339             break;
1340         }
1341         case ResultSetDataType::TYPE_DOUBLE: {
1342             values.PutDouble(columnName, get<double>(columnVal));
1343             break;
1344         }
1345         case ResultSetDataType::TYPE_STRING: {
1346             values.PutString(columnName, get<string>(columnVal));
1347             break;
1348         }
1349         default:
1350             MEDIA_ERR_LOG("No such column type: %{public}s", columnType.c_str());
1351     }
1352 }
1353 
GetQueryWhereClause(const string & tableName,const unordered_map<string,string> & columnInfoMap)1354 void CloneRestore::GetQueryWhereClause(const string &tableName, const unordered_map<string, string> &columnInfoMap)
1355 {
1356     unordered_map<string, string> queryWhereClauseMap;
1357     if (IsCloudRestoreSatisfied()) {
1358         queryWhereClauseMap = GetValueFromMap(TABLE_QUERY_WHERE_CLAUSE_MAP_WITH_CLOUD, tableName);
1359     } else {
1360         queryWhereClauseMap = GetValueFromMap(TABLE_QUERY_WHERE_CLAUSE_MAP, tableName);
1361     }
1362 
1363     if (queryWhereClauseMap.empty()) {
1364         return;
1365     }
1366     string &queryWhereClause = tableQueryWhereClauseMap_[tableName];
1367     queryWhereClause.clear();
1368     for (auto it = queryWhereClauseMap.begin(); it != queryWhereClauseMap.end(); ++it) {
1369         CHECK_AND_CONTINUE(columnInfoMap.count(it->first) != 0);
1370         if (!queryWhereClause.empty()) {
1371             queryWhereClause += " AND ";
1372         }
1373         queryWhereClause += it->second + " ";
1374     }
1375 }
1376 
GetAlbumExtraQueryWhereClause(const string & tableName)1377 void CloneRestore::GetAlbumExtraQueryWhereClause(const string &tableName)
1378 {
1379     string mapTableName = GetValueFromMap(CLONE_ALBUM_MAP, tableName);
1380     CHECK_AND_RETURN_LOG(!mapTableName.empty(), "Get map of table %{public}s failed",
1381         BackupDatabaseUtils::GarbleInfoName(tableName).c_str());
1382     string albumQueryWhereClause = "EXISTS (SELECT " + PhotoMap::ASSET_ID + " FROM " + mapTableName + " WHERE " +
1383         PhotoMap::ALBUM_ID + " = " + PhotoAlbumColumns::ALBUM_ID + " AND EXISTS (SELECT " + MediaColumn::MEDIA_ID +
1384         " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_ID + " = " + PhotoMap::ASSET_ID;
1385     string photoQueryWhereClause = GetValueFromMap(tableQueryWhereClauseMap_, PhotoColumn::PHOTOS_TABLE);
1386     if (!photoQueryWhereClause.empty()) {
1387         albumQueryWhereClause += " AND " + photoQueryWhereClause;
1388     }
1389     albumQueryWhereClause += "))";
1390     tableExtraQueryWhereClauseMap_[tableName] = albumQueryWhereClause;
1391 }
1392 
GetInsertValue(const AlbumInfo & albumInfo,const string & tableName) const1393 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const AlbumInfo &albumInfo, const string &tableName) const
1394 {
1395     NativeRdb::ValuesBucket values;
1396     values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, static_cast<int32_t>(albumInfo.albumType));
1397     values.PutInt(PhotoAlbumColumns::ALBUM_SUBTYPE, static_cast<int32_t>(albumInfo.albumSubType));
1398     values.PutString(PhotoAlbumColumns::ALBUM_NAME, albumInfo.albumName);
1399 
1400     if (tableName == PhotoAlbumColumns::TABLE) {
1401         values.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED,
1402             (albumInfo.dateModified ? albumInfo.dateModified : MediaFileUtils::UTCTimeMilliSeconds()));
1403     }
1404 
1405     unordered_map<string, string> commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
1406     for (auto it = albumInfo.valMap.begin(); it != albumInfo.valMap.end(); ++it) {
1407         string columnName = it->first;
1408         auto columnVal = it->second;
1409         PrepareCommonColumnVal(values, columnName, columnVal, commonColumnInfoMap);
1410     }
1411     return values;
1412 }
1413 
BatchQueryPhoto(vector<FileInfo> & fileInfos)1414 void CloneRestore::BatchQueryPhoto(vector<FileInfo> &fileInfos)
1415 {
1416     string selection;
1417     unordered_map<string, size_t> fileIndexMap;
1418     for (size_t index = 0; index < fileInfos.size(); index++) {
1419         CHECK_AND_CONTINUE(!fileInfos[index].cloudPath.empty());
1420         BackupDatabaseUtils::UpdateSelection(selection, fileInfos[index].cloudPath, true);
1421         fileIndexMap[fileInfos[index].cloudPath] = index;
1422     }
1423     string querySql = "SELECT " + MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + ", " +
1424         MediaColumn::MEDIA_DATE_TAKEN + " FROM " + PhotoColumn::PHOTOS_TABLE +
1425         " WHERE " + MediaColumn::MEDIA_FILE_PATH + " IN (" + selection + ")";
1426     querySql += " LIMIT " + to_string(fileIndexMap.size());
1427     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1428     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Query resultSql is null.");
1429     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1430         int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
1431         string cloudPath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
1432         string dateTaken = GetStringVal(MediaColumn::MEDIA_DATE_TAKEN, resultSet);
1433         CHECK_AND_CONTINUE_ERR_LOG(fileId > 0, "Get fileId invalid: %{public}d", fileId);
1434         CHECK_AND_CONTINUE(fileIndexMap.count(cloudPath) != 0);
1435         size_t index = fileIndexMap.at(cloudPath);
1436         fileInfos[index].fileIdNew = fileId;
1437         fileInfos[index].newAstcDateKey = dateTaken;
1438     }
1439     resultSet->Close();
1440     BackupDatabaseUtils::UpdateAssociateFileId(mediaLibraryRdb_, fileInfos);
1441 }
1442 
UpdateAlbumOrderColumns(const AlbumInfo & albumInfo,const string & tableName)1443 void CloneRestore::UpdateAlbumOrderColumns(const AlbumInfo &albumInfo, const string &tableName)
1444 {
1445     CHECK_AND_RETURN(tableName == PhotoAlbumColumns::TABLE);
1446     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "rdbStore is null");
1447 
1448     std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
1449         make_unique<NativeRdb::AbsRdbPredicates>(PhotoAlbumColumns::TABLE);
1450     predicates->EqualTo(PhotoAlbumColumns::ALBUM_ID, albumInfo.albumIdNew);
1451 
1452     NativeRdb::ValuesBucket values;
1453     unordered_map<string, string> commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
1454     for (const auto &columns : PhotoAlbumColumns::ORDER_COLUMN_STYLE_MAP) {
1455         for (const auto &columnName : columns.second) {
1456             auto iter = albumInfo.valMap.find(columnName);
1457             CHECK_AND_EXECUTE(iter == albumInfo.valMap.end(),
1458                 PrepareCommonColumnVal(values, columnName, iter->second, commonColumnInfoMap));
1459         }
1460     }
1461 
1462     int32_t changeRows = 0;
1463     int32_t ret = BackupDatabaseUtils::Update(mediaLibraryRdb_, changeRows, values, predicates);
1464     bool cond = (changeRows < 0 || ret < 0);
1465     CHECK_AND_RETURN_LOG(!cond,
1466         "Failed to update albumOrder columns, ret: %{public}d, updateRows: %{public}d", ret, changeRows);
1467 }
1468 
UpdateSystemAlbumColumns(const string & tableName)1469 void CloneRestore::UpdateSystemAlbumColumns(const string &tableName)
1470 {
1471     CHECK_AND_RETURN(tableName == PhotoAlbumColumns::TABLE);
1472     CHECK_AND_RETURN_LOG(this->mediaRdb_ != nullptr, "original rdbStore is null");
1473 
1474     const std::string querySql =
1475         "SELECT PhotoAlbum.* FROM PhotoAlbum WHERE PhotoAlbum.album_type = 1024 ORDER BY PhotoAlbum.album_id";
1476     const vector<string> bindArgs = {};
1477     auto resultSet = this->mediaRdb_->QuerySql(querySql, bindArgs);
1478     CHECK_AND_RETURN_LOG(resultSet != nullptr,
1479         "Failed to query system album! querySql = %{public}s", querySql.c_str());
1480 
1481     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1482         AlbumInfo albumInfo;
1483         bool ret = ParseAlbumResultSet(tableName, resultSet, albumInfo);
1484         CHECK_AND_CONTINUE_INFO_LOG(ret == true, "Update system album columns failed");
1485         albumInfo.albumIdNew = albumInfo.albumIdOld;
1486         UpdateAlbumOrderColumns(albumInfo, tableName);
1487     }
1488     resultSet->Close();
1489 }
1490 
InsertAlbum(vector<AlbumInfo> & albumInfos,const string & tableName)1491 void CloneRestore::InsertAlbum(vector<AlbumInfo> &albumInfos, const string &tableName)
1492 {
1493     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
1494     CHECK_AND_RETURN_LOG(!albumInfos.empty(), "albumInfos are empty");
1495     int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
1496     vector<string> albumIds{};
1497     vector<NativeRdb::ValuesBucket> values = GetInsertValues(albumInfos, albumIds, tableName);
1498     UpdatePhotoAlbumDateModified(albumIds, tableName);
1499     int64_t rowNum = 0;
1500     int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
1501     CHECK_AND_RETURN_LOG(errCode == E_OK, "Batc insert failed");
1502     migrateDatabaseAlbumNumber_ += rowNum;
1503     int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1504     BatchQueryAlbum(albumInfos, tableName);
1505     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1506     MEDIA_INFO_LOG("insert %{public}ld albums cost %{public}ld, query cost %{public}ld.", (long)rowNum,
1507         (long)(startQuery - startInsert), (long)(end - startQuery));
1508 }
1509 
GetInsertValues(vector<AlbumInfo> & albumInfos,vector<string> & albumIds,const string & tableName)1510 vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(vector<AlbumInfo> &albumInfos, vector<string> &albumIds,
1511     const string &tableName)
1512 {
1513     vector<NativeRdb::ValuesBucket> values;
1514     for (size_t i = 0; i < albumInfos.size(); i++) {
1515         if (HasSameAlbum(albumInfos[i], tableName)) {
1516             albumIds.emplace_back(to_string(albumInfos[i].albumIdNew));
1517             UpdateAlbumOrderColumns(albumInfos[i], tableName);
1518             MEDIA_WARN_LOG("Album (%{public}d, %{public}d, %{public}d, %{public}s) already exists.",
1519                 albumInfos[i].albumIdOld, static_cast<int32_t>(albumInfos[i].albumType),
1520                 static_cast<int32_t>(albumInfos[i].albumSubType), albumInfos[i].albumName.c_str());
1521             continue;
1522         }
1523         NativeRdb::ValuesBucket value = GetInsertValue(albumInfos[i], tableName);
1524         values.emplace_back(value);
1525     }
1526     return values;
1527 }
1528 
HasSameAlbum(AlbumInfo & albumInfo,const string & tableName)1529 bool CloneRestore::HasSameAlbum(AlbumInfo &albumInfo, const string &tableName)
1530 {
1531     // check if the album already exists
1532     CHECK_AND_RETURN_RET(tableName != PhotoAlbumColumns::TABLE,
1533         this->photoAlbumClone_.HasSameAlbum(albumInfo.lPath, albumInfo.albumIdNew));
1534     string querySql = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + tableName + " WHERE " +
1535         PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(albumInfo.albumType) + " AND " +
1536         PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(albumInfo.albumSubType) + " AND " +
1537         PhotoAlbumColumns::ALBUM_NAME + " = '" + albumInfo.albumName + "'";
1538     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1539     bool cond = (resultSet == nullptr);
1540     CHECK_AND_RETURN_RET(!cond, false);
1541     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1542         resultSet->Close();
1543         return false;
1544     }
1545     int32_t count = GetInt32Val(MEDIA_COLUMN_COUNT_1, resultSet);
1546     resultSet->Close();
1547     return count > 0;
1548 }
1549 
BatchQueryAlbum(vector<AlbumInfo> & albumInfos,const string & tableName)1550 void CloneRestore::BatchQueryAlbum(vector<AlbumInfo> &albumInfos, const string &tableName)
1551 {
1552     auto &albumIdMap = tableAlbumIdMap_[tableName];
1553     for (auto &albumInfo : albumInfos) {
1554         CHECK_AND_CONTINUE(albumInfo.albumIdOld > 0);
1555         string querySql = "SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " + tableName + " WHERE " +
1556             PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(albumInfo.albumType) + " AND " +
1557             PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(albumInfo.albumSubType) + " AND " +
1558             PhotoAlbumColumns::ALBUM_NAME + " = '" + albumInfo.albumName + "'";
1559         auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1560         CHECK_AND_CONTINUE(resultSet != nullptr);
1561         if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1562             resultSet->Close();
1563             continue;
1564         }
1565         albumInfo.albumIdNew = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
1566         CHECK_AND_CONTINUE(albumInfo.albumIdNew > 0);
1567         albumIdMap[albumInfo.albumIdOld] = albumInfo.albumIdNew;
1568         resultSet->Close();
1569     }
1570 }
1571 
BatchInsertMap(const vector<FileInfo> & fileInfos,int64_t & totalRowNum)1572 void CloneRestore::BatchInsertMap(const vector<FileInfo> &fileInfos, int64_t &totalRowNum)
1573 {
1574     string selection;
1575     unordered_map<int32_t, int32_t> fileIdMap;
1576     SetFileIdReference(fileInfos, selection, fileIdMap);
1577     std::string tableName = ANALYSIS_ALBUM_TABLE;
1578     string garbledTableName = BackupDatabaseUtils::GarbleInfoName(tableName);
1579     string mapTableName = GetValueFromMap(CLONE_ALBUM_MAP, tableName);
1580     CHECK_AND_RETURN_LOG(!mapTableName.empty(),
1581         "Get map of table %{public}s failed", garbledTableName.c_str());
1582     auto albumIdMap = GetValueFromMap(tableAlbumIdMap_, tableName);
1583     CHECK_AND_RETURN_LOG(!albumIdMap.empty(),
1584         "Get album id map of table %{public}s empty, skip", garbledTableName.c_str());
1585     string albumSelection = GetValueFromMap(tableQueryWhereClauseMap_, tableName);
1586     unordered_set<int32_t> currentTableAlbumSet;
1587     string baseQuerySql = mapTableName + " INNER JOIN " + tableName + " ON " +
1588         mapTableName + "." + PhotoMap::ALBUM_ID + " = " + tableName + "." + PhotoAlbumColumns::ALBUM_ID +
1589         " WHERE " + mapTableName + "." + PhotoMap::ASSET_ID + " IN (" + selection + ")";
1590     baseQuerySql += albumSelection.empty() ? "" : " AND " + albumSelection;
1591     int32_t totalNumber = QueryMapTotalNumber(baseQuerySql);
1592     MEDIA_INFO_LOG("QueryMapTotalNumber of table %{public}s, totalNumber = %{public}d", garbledTableName.c_str(),
1593         totalNumber);
1594     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
1595         int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1596         vector<MapInfo> mapInfos = QueryMapInfos(mapTableName, baseQuerySql, offset, fileIdMap, albumIdMap);
1597         int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
1598         int64_t rowNum = InsertMapByTable(mapTableName, mapInfos, currentTableAlbumSet);
1599         totalRowNum += rowNum;
1600         int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1601         MEDIA_INFO_LOG("query %{public}zu map infos cost %{public}ld, insert %{public}ld maps cost %{public}ld",
1602             mapInfos.size(), (long)(startInsert - startQuery), (long)rowNum, (long)(end - startInsert));
1603     }
1604 }
1605 
GetInsertValue(const MapInfo & mapInfo) const1606 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const MapInfo &mapInfo) const
1607 {
1608     NativeRdb::ValuesBucket values;
1609     values.PutInt(PhotoMap::ASSET_ID, mapInfo.fileId);
1610     values.PutInt(PhotoMap::ALBUM_ID, mapInfo.albumId);
1611     return values;
1612 }
1613 
CheckTableColumnStatus(shared_ptr<NativeRdb::RdbStore> rdbStore,const vector<vector<string>> & cloneTableList)1614 void CloneRestore::CheckTableColumnStatus(shared_ptr<NativeRdb::RdbStore> rdbStore,
1615     const vector<vector<string>> &cloneTableList)
1616 {
1617     unordered_map<string, unordered_map<string, string>> tableColumnInfoMap;
1618     for (const auto &tableList : cloneTableList) {
1619         bool columnStatusGlobal = true;
1620         for (const auto &tableName : tableList) {
1621             auto &columnInfoMap = tableColumnInfoMap[tableName];
1622             columnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(rdbStore, tableName);
1623             auto neededColumns = GetValueFromMap(NEEDED_COLUMNS_MAP, tableName);
1624             columnStatusGlobal = columnStatusGlobal && HasColumns(columnInfoMap, neededColumns);
1625         }
1626         for (const auto &tableName : tableList) {
1627             tableColumnStatusMap_[tableName] = columnStatusGlobal;
1628         }
1629     }
1630     for (const auto &tableList : cloneTableList) {
1631         for (const auto &tableName : tableList) {
1632             if (!IsReadyForRestore(tableName)) {
1633                 MEDIA_ERR_LOG("Column status is false");
1634                 break;
1635             }
1636             auto columnInfoMap = GetValueFromMap(tableColumnInfoMap, tableName);
1637             GetQueryWhereClause(tableName, columnInfoMap);
1638         }
1639     }
1640 }
1641 
HasColumns(const unordered_map<string,string> & columnInfoMap,const unordered_set<string> & columnSet)1642 bool CloneRestore::HasColumns(const unordered_map<string, string> &columnInfoMap,
1643     const unordered_set<string> &columnSet)
1644 {
1645     for (const auto &columnName : columnSet) {
1646         if (!HasColumn(columnInfoMap, columnName)) {
1647             MEDIA_ERR_LOG("Lack of column %{public}s", columnName.c_str());
1648             return false;
1649         }
1650     }
1651     return true;
1652 }
1653 
HasColumn(const unordered_map<string,string> & columnInfoMap,const string & columnName)1654 bool CloneRestore::HasColumn(const unordered_map<string, string> &columnInfoMap, const string &columnName)
1655 {
1656     return columnInfoMap.count(columnName) > 0;
1657 }
1658 
IsReadyForRestore(const string & tableName)1659 bool CloneRestore::IsReadyForRestore(const string &tableName)
1660 {
1661     return GetValueFromMap(tableColumnStatusMap_, tableName, false);
1662 }
1663 
PrepareEditTimeVal(NativeRdb::ValuesBucket & values,int64_t editTime,const FileInfo & fileInfo,const unordered_map<string,string> & commonColumnInfoMap) const1664 void CloneRestore::PrepareEditTimeVal(NativeRdb::ValuesBucket &values, int64_t editTime, const FileInfo &fileInfo,
1665     const unordered_map<string, string> &commonColumnInfoMap) const
1666 {
1667     string editDataPath = backupRestoreDir_ +
1668         BackupFileUtils::GetFullPathByPrefixType(PrefixType::LOCAL_EDIT_DATA, fileInfo.relativePath);
1669     int64_t newEditTime = editTime > 0 && IsFilePathExist(editDataPath) ? editTime : 0;
1670     PrepareCommonColumnVal(values, PhotoColumn::PHOTO_EDIT_TIME, newEditTime, commonColumnInfoMap);
1671 }
1672 
RestoreGallery()1673 void CloneRestore::RestoreGallery()
1674 {
1675     CheckTableColumnStatus(mediaRdb_, CLONE_TABLE_LISTS_PHOTO);
1676     // Upgrade original MediaLibrary Database
1677     DataTransfer::MediaLibraryDbUpgrade medialibraryDbUpgrade;
1678     medialibraryDbUpgrade.OnUpgrade(*this->mediaRdb_);
1679     // Report the old db info.
1680     DatabaseReport()
1681         .SetSceneCode(this->sceneCode_)
1682         .SetTaskId(this->taskId_)
1683         .ReportMedia(this->mediaRdb_, DatabaseReport::PERIOD_OLD)
1684         .ReportMedia(this->mediaLibraryRdb_, DatabaseReport::PERIOD_BEFORE);
1685     UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_)
1686         .Report("RESTORE_CLOUD_STATUS", "",
1687             "isAccountValid_: " + std::to_string(isAccountValid_) +
1688             ", syncSwitchType_: " + std::to_string(syncSwitchType_) +
1689             ", isSyncSwitchOpen: " + std::to_string(isSyncSwitchOn_));
1690     // Restore the backup db info.
1691     RestoreAlbum();
1692     RestorePhoto();
1693     if (IsCloudRestoreSatisfied()) {
1694         MEDIA_INFO_LOG("singlCloud cloud clone");
1695         RestorePhotoForCloud();
1696     }
1697     MEDIA_INFO_LOG("singlCloud migrate database photo number: %{public}lld, file number: %{public}lld (%{public}lld + "
1698         "%{public}lld), duplicate number: %{public}lld + %{public}lld, album number: %{public}lld, map number: "
1699         "%{public}lld", (long long)migrateDatabaseNumber_, (long long)migrateFileNumber_,
1700         (long long)(migrateFileNumber_ - migrateVideoFileNumber_), (long long)migrateVideoFileNumber_,
1701         (long long)migratePhotoDuplicateNumber_, (long long)migrateVideoDuplicateNumber_,
1702         (long long)migrateDatabaseAlbumNumber_, (long long)migrateDatabaseMapNumber_);
1703     MEDIA_INFO_LOG("singlCloud Start update group tags");
1704     BackupDatabaseUtils::UpdateFaceGroupTagsUnion(mediaLibraryRdb_);
1705     BackupDatabaseUtils::UpdateFaceAnalysisTblStatus(mediaLibraryRdb_);
1706     BackupDatabaseUtils::UpdateAnalysisPhotoMapStatus(mediaLibraryRdb_);
1707     RestoreAnalysisClassify();
1708     RestoreAnalysisGeo();
1709     cloneRestoreGeoDictionary_.ReportGeoRestoreTask();
1710     RestoreAnalysisData();
1711     ReportPortraitCloneStat(sceneCode_);
1712     InheritManualCover();
1713 }
1714 
RestoreAnalysisTablesData()1715 void CloneRestore::RestoreAnalysisTablesData()
1716 {
1717     cloneRestoreAnalysisData_.Init(this->sceneCode_, this->taskId_, mediaRdb_, mediaLibraryRdb_);
1718     std::unordered_set<std::string> excludedColumns = {"id", "file_id"};
1719     vector<std::string> analysisTables = {
1720         "tab_analysis_head",
1721         "tab_analysis_pose",
1722         "tab_analysis_composition",
1723         "tab_analysis_ocr",
1724         "tab_analysis_segmentation",
1725         "tab_analysis_object",
1726         "tab_analysis_saliency_detect",
1727         "tab_analysis_recommendation"
1728     };
1729 
1730     vector<std::string> totalTypes = {
1731         "head",
1732         "pose",
1733         "composition",
1734         "ocr",
1735         "segmentation",
1736         "object",
1737         "saliency",
1738         "recommendation"
1739     };
1740 
1741     for (size_t index = 0; index < analysisTables.size(); index++) {
1742         std::string table = analysisTables[index];
1743         std::string type = totalTypes[index];
1744         cloneRestoreAnalysisData_.CloneAnalysisData(table, type, photoInfoMap_, excludedColumns);
1745     }
1746 }
1747 
RestoreAnalysisData()1748 void CloneRestore::RestoreAnalysisData()
1749 {
1750     RestoreSearchIndexData();
1751     RestoreBeautyScoreData();
1752     RestoreVideoFaceData();
1753     RestoreAnalysisTablesData();
1754     RestoreHighlightAlbums();
1755 }
1756 
RestoreSearchIndexData()1757 void CloneRestore::RestoreSearchIndexData()
1758 {
1759     SearchIndexClone searchIndexClone(mediaRdb_, mediaLibraryRdb_, photoInfoMap_, maxSearchId_);
1760     searchIndexClone.Clone();
1761 }
1762 
RestoreBeautyScoreData()1763 void CloneRestore::RestoreBeautyScoreData()
1764 {
1765     BeautyScoreClone beautyScoreClone(mediaRdb_, mediaLibraryRdb_, photoInfoMap_, maxBeautyFileId_);
1766     beautyScoreClone.CloneBeautyScoreInfo();
1767 }
1768 
RestoreVideoFaceData()1769 void CloneRestore::RestoreVideoFaceData()
1770 {
1771     VideoFaceClone videoFaceClone(mediaRdb_, mediaLibraryRdb_, photoInfoMap_);
1772     videoFaceClone.CloneVideoFaceInfo();
1773 }
1774 
PrepareCloudPath(const string & tableName,FileInfo & fileInfo)1775 bool CloneRestore::PrepareCloudPath(const string &tableName, FileInfo &fileInfo)
1776 {
1777     fileInfo.cloudPath = BackupFileUtils::GetFullPathByPrefixType(PrefixType::CLOUD, fileInfo.relativePath);
1778     CHECK_AND_RETURN_RET_LOG(!fileInfo.cloudPath.empty(), false, "Get cloudPath empty");
1779     if (IsSameFileForClone(tableName, fileInfo)) {
1780         // should not delete the file, if the FileInfo is came from PhotoMap.
1781         if (fileInfo.isRelatedToPhotoMap != 1) {
1782             MEDIA_INFO_LOG("File (%{public}s) already exists. delete it.",
1783                 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str());
1784             (void)MediaFileUtils::DeleteFile(fileInfo.filePath);
1785         }
1786         UpdateDuplicateNumber(fileInfo.fileType);
1787         return false;
1788     }
1789     // If the device originally has dentry file in the cloud path, no need to generate new cloud path.
1790     if (fileInfo.isNew && (MediaFileUtils::IsFileExists(fileInfo.cloudPath) || fileInfo.isRelatedToPhotoMap == 1)) {
1791         int32_t uniqueId = GetUniqueId(fileInfo.fileType);
1792         int32_t errCode = BackupFileUtils::CreateAssetPathById(uniqueId, fileInfo.fileType,
1793             MediaFileUtils::GetExtensionFromPath(fileInfo.displayName), fileInfo.cloudPath);
1794         if (errCode != E_OK) {
1795             ErrorInfo errorInfo(RestoreError::CREATE_PATH_FAILED, 1, std::to_string(errCode),
1796                 BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1797             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1798             fileInfo.cloudPath.clear();
1799             return false;
1800         }
1801     }
1802     int32_t errCode = BackupFileUtils::PreparePath(
1803         BackupFileUtils::GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL, fileInfo.cloudPath));
1804     if (errCode != E_OK) {
1805         MEDIA_ERR_LOG("Prepare cloudPath failed, path: %{public}s, cloudPath: %{public}s",
1806             BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str(),
1807             BackupFileUtils::GarbleFilePath(fileInfo.cloudPath, DEFAULT_RESTORE_ID, garbagePath_).c_str());
1808         ErrorInfo errorInfo(RestoreError::PREPARE_PATH_FAILED, 1, std::to_string(errCode),
1809             BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1810         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1811         fileInfo.cloudPath.clear();
1812         return false;
1813     }
1814     return true;
1815 }
1816 
RestoreMusic()1817 void CloneRestore::RestoreMusic()
1818 {
1819     CheckTableColumnStatus(mediaRdb_, CLONE_TABLE_LISTS_AUDIO);
1820     RestoreAudio();
1821     MEDIA_INFO_LOG("migrate database audio number: %{public}lld, file number: %{public}lld, duplicate number: "
1822         "%{public}lld", (long long)migrateAudioDatabaseNumber_, (long long)migrateAudioFileNumber_,
1823         (long long)migrateAudioDuplicateNumber_);
1824 }
1825 
RestoreAudio(void)1826 void CloneRestore::RestoreAudio(void)
1827 {
1828     MEDIA_INFO_LOG("Start clone restore: audio");
1829     CHECK_AND_RETURN_LOG(IsReadyForRestore(AudioColumn::AUDIOS_TABLE),
1830         "Column status is not ready for restore audio, quit");
1831     unordered_map<string, string> srcColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaRdb_,
1832         AudioColumn::AUDIOS_TABLE);
1833     unordered_map<string, string> dstColumnInfoMap = BackupDatabaseUtils::GetColumnInfoMap(mediaLibraryRdb_,
1834         AudioColumn::AUDIOS_TABLE);
1835     CHECK_AND_RETURN_LOG(PrepareCommonColumnInfoMap(AudioColumn::AUDIOS_TABLE, srcColumnInfoMap,
1836         dstColumnInfoMap), "Prepare common column info failed");
1837     int32_t totalNumber = QueryTotalNumber(AudioColumn::AUDIOS_TABLE);
1838     MEDIA_INFO_LOG("QueryAudioTotalNumber, totalNumber = %{public}d", totalNumber);
1839     CHECK_AND_RETURN(totalNumber > 0);
1840 
1841     audioTotalNumber_ += static_cast<uint64_t>(totalNumber);
1842     MEDIA_INFO_LOG("onProcess Update audioTotalNumber_: %{public}lld", (long long)audioTotalNumber_);
1843     if (!MediaFileUtils::IsFileExists(RESTORE_MUSIC_LOCAL_DIR)) {
1844         MEDIA_INFO_LOG("music dir is not exists!!!");
1845         MediaFileUtils::CreateDirectory(RESTORE_MUSIC_LOCAL_DIR);
1846     }
1847     for (int32_t offset = 0; offset < totalNumber; offset += CLONE_QUERY_COUNT) {
1848         ffrt::submit([this, offset]() { RestoreAudioBatch(offset); }, { &offset }, {},
1849             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
1850     }
1851     ffrt::wait();
1852 }
1853 
QueryFileInfos(const string & tableName,int32_t offset)1854 vector<FileInfo> CloneRestore::QueryFileInfos(const string &tableName, int32_t offset)
1855 {
1856     vector<FileInfo> result;
1857     result.reserve(CLONE_QUERY_COUNT);
1858     string querySql = "SELECT * FROM " + tableName;
1859     string whereClause = GetQueryWhereClauseByTable(tableName);
1860     querySql += whereClause.empty() ? "" : " WHERE " + whereClause;
1861     querySql += " LIMIT " + to_string(offset) + ", " + to_string(CLONE_QUERY_COUNT);
1862     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
1863     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
1864     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1865         FileInfo fileInfo;
1866         if (ParseResultSet(tableName, resultSet, fileInfo)) {
1867             result.emplace_back(fileInfo);
1868         }
1869     }
1870     resultSet->Close();
1871     return result;
1872 }
1873 
ParseResultSet(const string & tableName,const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)1874 bool CloneRestore::ParseResultSet(const string &tableName, const shared_ptr<NativeRdb::ResultSet> &resultSet,
1875     FileInfo &fileInfo)
1876 {
1877     fileInfo.fileType = GetInt32Val(MediaColumn::MEDIA_TYPE, resultSet);
1878     fileInfo.fileIdOld = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
1879     fileInfo.displayName = GetStringVal(MediaColumn::MEDIA_NAME, resultSet);
1880     fileInfo.oldPath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
1881     if (!ConvertPathToRealPath(fileInfo.oldPath, filePath_, fileInfo.filePath, fileInfo.relativePath)) {
1882         ErrorInfo errorInfo(RestoreError::PATH_INVALID, 1, "", BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1883         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1884         return false;
1885     }
1886     fileInfo.fileSize = GetInt64Val(MediaColumn::MEDIA_SIZE, resultSet);
1887     if (fileInfo.fileSize <= 0) {
1888         ErrorInfo errorInfo(RestoreError::SIZE_INVALID, 1, "Db size <= 0",
1889             BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
1890         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1891         return false;
1892     }
1893 
1894     fileInfo.dateAdded = GetInt64Val(MediaColumn::MEDIA_DATE_ADDED, resultSet);
1895     fileInfo.dateModified = GetInt64Val(MediaColumn::MEDIA_DATE_MODIFIED, resultSet);
1896     fileInfo.dateTaken = GetInt64Val(MediaColumn::MEDIA_DATE_TAKEN, resultSet);
1897     fileInfo.thumbnailReady = GetInt64Val(PhotoColumn::PHOTO_THUMBNAIL_READY, resultSet);
1898     fileInfo.lcdVisitTime = GetInt32Val(PhotoColumn::PHOTO_LCD_VISIT_TIME, resultSet);
1899     fileInfo.position = GetInt32Val(PhotoColumn::PHOTO_POSITION, resultSet);
1900     fileInfo.cloudVersion = GetInt32Val(PhotoColumn::PHOTO_CLOUD_VERSION, resultSet);
1901     fileInfo.cloudId = GetStringVal(PhotoColumn::PHOTO_CLOUD_ID, resultSet);
1902     fileInfo.oldAstcDateKey = to_string(fileInfo.dateTaken);
1903     SetSpecialAttributes(tableName, resultSet, fileInfo);
1904 
1905     auto commonColumnInfoMap = GetValueFromMap(tableCommonColumnInfoMap_, tableName);
1906     for (auto it = commonColumnInfoMap.begin(); it != commonColumnInfoMap.end(); ++it) {
1907         string columnName = it->first;
1908         string columnType = it->second;
1909         GetValFromResultSet(resultSet, fileInfo.valMap, columnName, columnType);
1910     }
1911     return true;
1912 }
1913 
ParseResultSetForAudio(const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)1914 bool CloneRestore::ParseResultSetForAudio(const shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &fileInfo)
1915 {
1916     return ParseResultSet(AudioColumn::AUDIOS_TABLE, resultSet, fileInfo);
1917 }
1918 
InsertAudio(vector<FileInfo> & fileInfos)1919 void CloneRestore::InsertAudio(vector<FileInfo> &fileInfos)
1920 {
1921     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
1922     CHECK_AND_RETURN_LOG(!fileInfos.empty(), "fileInfos are empty");
1923     int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
1924     int64_t fileMoveCount = 0;
1925     for (auto& fileInfo : fileInfos) {
1926         CHECK_AND_CONTINUE_ERR_LOG(BackupFileUtils::IsFileValid(fileInfo.filePath, CLONE_RESTORE_ID) == E_OK,
1927             "File is invalid: size: %{public}lld, name: %{public}s, filePath: %{public}s",
1928             (long long)fileInfo.fileSize, BackupFileUtils::GarbleFileName(fileInfo.displayName).c_str(),
1929             BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str());
1930         CHECK_AND_CONTINUE(PrepareCloudPath(AudioColumn::AUDIOS_TABLE, fileInfo));
1931         string localPath = RESTORE_MUSIC_LOCAL_DIR + fileInfo.displayName;
1932         if (MediaFileUtils::IsFileExists(localPath)) {
1933             MEDIA_INFO_LOG("localPath %{public}s already exists.",
1934                 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str());
1935             UpdateDuplicateNumber(fileInfo.fileType);
1936             continue;
1937         }
1938 
1939         int32_t moveErrCode = MoveFile(fileInfo.filePath, localPath);
1940         if (moveErrCode != E_OK) {
1941             MEDIA_ERR_LOG("MoveFile failed, filePath: %{public}s, errCode: %{public}d, errno: %{public}d",
1942                 BackupFileUtils::GarbleFilePath(fileInfo.filePath, CLONE_RESTORE_ID, garbagePath_).c_str(), moveErrCode,
1943                 errno);
1944             UpdateFailedFiles(fileInfo.fileType, fileInfo, RestoreError::MOVE_FAILED);
1945             continue;
1946         }
1947         BackupFileUtils::ModifyFile(localPath, fileInfo.dateModified / MSEC_TO_SEC);
1948         fileMoveCount++;
1949     }
1950     migrateAudioFileNumber_ += fileMoveCount;
1951     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1952     MEDIA_INFO_LOG("move %{public}ld files cost %{public}ld.", (long)fileMoveCount, (long)(end - startMove));
1953 }
1954 
StatClonetotalSize(std::shared_ptr<NativeRdb::RdbStore> mediaRdb)1955 size_t CloneRestore::StatClonetotalSize(std::shared_ptr<NativeRdb::RdbStore> mediaRdb)
1956 {
1957     CHECK_AND_RETURN_RET_LOG(mediaRdb != nullptr, 0, "rdbStore is nullptr");
1958 
1959     string thumbSizeSql {};
1960     thumbSizeSql = "SELECT SUM(CAST(" + PhotoExtColumn::THUMBNAIL_SIZE + " AS BIGINT)) AS " + MEDIA_DATA_DB_SIZE +
1961                           ", -1 AS " + MediaColumn::MEDIA_TYPE +
1962                           " FROM " + PhotoExtColumn::PHOTOS_EXT_TABLE;
1963 
1964     string mediaVolumeQuery = PhotoColumn::QUERY_MEDIA_VOLUME + " UNION ALL " +
1965                               AudioColumn::QUERY_MEDIA_VOLUME + " UNION ALL " +
1966                               thumbSizeSql;
1967 
1968     auto resultSet = mediaRdb->QuerySql(mediaVolumeQuery);
1969     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, 0, "Failed to execute media volume query");
1970 
1971     int64_t totalVolume = 0;
1972     MEDIA_INFO_LOG("Initial totalVolume: %{public}" PRId64, totalVolume);
1973 
1974     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1975         int64_t mediaSize = GetInt64Val(MediaColumn::MEDIA_SIZE, resultSet);
1976         int32_t mediatype = GetInt32Val(MediaColumn::MEDIA_TYPE, resultSet);
1977         MEDIA_INFO_LOG("mediatype is %{public}d, current media asset size is: %{public}" PRId64, mediatype, mediaSize);
1978         if (mediaSize < 0) {
1979             MEDIA_ERR_LOG("ill mediaSize: %{public}" PRId64 " for mediatype: %{public}d", mediaSize, mediatype);
1980         }
1981 
1982         totalVolume += mediaSize;
1983         MEDIA_INFO_LOG("current totalVolume: %{public}" PRId64, totalVolume);
1984     }
1985     resultSet->Close();
1986     MEDIA_INFO_LOG("media db media asset size is: %{public}" PRId64, totalVolume);
1987 
1988     if (totalVolume < 0) {
1989         MEDIA_ERR_LOG("totalVolume is negative: %{public}" PRId64 ". Returning 0.", totalVolume);
1990         return 0;
1991     }
1992 
1993     size_t totalAssetSize = static_cast<size_t>(totalVolume);
1994     // other meta data dir size
1995     size_t editDataTotalSize {0};
1996     size_t rdbTotalSize {0};
1997     size_t kvdbTotalSize {0};
1998     size_t highlightTotalSize {0};
1999     MediaFileUtils::StatDirSize(CLONE_STAT_EDIT_DATA_DIR, editDataTotalSize);
2000     MediaFileUtils::StatDirSize(CLONE_STAT_RDB_DIR, rdbTotalSize);
2001     MediaFileUtils::StatDirSize(CLONE_STAT_KVDB_DIR, kvdbTotalSize);
2002     MediaFileUtils::StatDirSize(CLONE_STAT_HIGHLIGHT_DIR, highlightTotalSize);
2003     size_t totalSize = totalAssetSize + editDataTotalSize + rdbTotalSize + kvdbTotalSize + highlightTotalSize;
2004     return totalSize;
2005 }
2006 
GetBackupInfo()2007 string CloneRestore::GetBackupInfo()
2008 {
2009     CHECK_AND_RETURN_RET_LOG(BaseRestore::Init() == E_OK, "", "GetBackupInfo init failed");
2010     CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, "", "GetBackupInfo Rdbstore is null");
2011 
2012     CheckTableColumnStatus(mediaLibraryRdb_, CLONE_TABLE_LISTS_OLD_DEVICE);
2013     int32_t photoCount = QueryTotalNumberByMediaType(mediaLibraryRdb_, PhotoColumn::PHOTOS_TABLE,
2014         MediaType::MEDIA_TYPE_IMAGE);
2015     int32_t videoCount = QueryTotalNumberByMediaType(mediaLibraryRdb_, PhotoColumn::PHOTOS_TABLE,
2016         MediaType::MEDIA_TYPE_VIDEO);
2017     int32_t audioCount = QueryTotalNumberByMediaType(mediaLibraryRdb_, AudioColumn::AUDIOS_TABLE,
2018         MediaType::MEDIA_TYPE_AUDIO);
2019 
2020     size_t totalSize = StatClonetotalSize(mediaLibraryRdb_);
2021     MEDIA_INFO_LOG("QueryTotalNumber, photo: %{public}d, video: %{public}d, audio: %{public}d, totalSize: "
2022         "%{public}lld bytes", photoCount, videoCount, audioCount, static_cast<long long>(totalSize));
2023 
2024     return GetBackupInfoByCount(photoCount, videoCount, audioCount, totalSize);
2025 }
2026 
QueryTotalNumberByMediaType(shared_ptr<NativeRdb::RdbStore> rdbStore,const string & tableName,MediaType mediaType)2027 int32_t CloneRestore::QueryTotalNumberByMediaType(shared_ptr<NativeRdb::RdbStore> rdbStore, const string &tableName,
2028     MediaType mediaType)
2029 {
2030     string querySql = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + tableName + " WHERE " + MediaColumn::MEDIA_TYPE +
2031         " = " + to_string(static_cast<int32_t>(mediaType));
2032     string whereClause = GetQueryWhereClauseByTable(tableName);
2033     querySql += whereClause.empty() ? "" : " AND " + whereClause;
2034     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(rdbStore, querySql);
2035     bool cond = (resultSet == nullptr);
2036     CHECK_AND_RETURN_RET(!cond, 0);
2037     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2038         resultSet->Close();
2039         return 0;
2040     }
2041     int32_t result = GetInt32Val(MEDIA_COLUMN_COUNT_1, resultSet);
2042     resultSet->Close();
2043     return result;
2044 }
2045 
GetBackupInfoByCount(int32_t photoCount,int32_t videoCount,int32_t audioCount,size_t totalSize)2046 string CloneRestore::GetBackupInfoByCount(int32_t photoCount, int32_t videoCount, int32_t audioCount, size_t totalSize)
2047 {
2048     nlohmann::json jsonObject = {
2049         {
2050             { STAT_KEY_BACKUP_INFO, STAT_TYPE_PHOTO },
2051             { STAT_KEY_NUMBER, photoCount }
2052         },
2053         {
2054             { STAT_KEY_BACKUP_INFO, STAT_TYPE_VIDEO },
2055             { STAT_KEY_NUMBER, videoCount }
2056         },
2057         {
2058             { STAT_KEY_BACKUP_INFO, STAT_TYPE_AUDIO },
2059             { STAT_KEY_NUMBER, audioCount }
2060         },
2061         {
2062             { STAT_KEY_BACKUP_INFO, STAT_TYPE_TOTAL_SIZE },
2063             { STAT_KEY_NUMBER, totalSize }
2064         }
2065     };
2066     return jsonObject.dump();
2067 }
2068 
RestorePhotoBatch(int32_t offset,int32_t isRelatedToPhotoMap)2069 void CloneRestore::RestorePhotoBatch(int32_t offset, int32_t isRelatedToPhotoMap)
2070 {
2071     MEDIA_INFO_LOG(
2072         "start restore photo, offset: %{public}d, isRelatedToPhotoMap: %{public}d", offset, isRelatedToPhotoMap);
2073     vector<FileInfo> fileInfos = QueryFileInfos(offset, isRelatedToPhotoMap);
2074     CHECK_AND_EXECUTE(InsertPhoto(fileInfos) == E_OK, AddToPhotosFailedOffsets(offset));
2075     RestoreImageFaceInfo(fileInfos);
2076 
2077     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2078     BackupDatabaseUtils::UpdateAnalysisTotalTblNoFaceStatus(mediaLibraryRdb_, mediaRdb_, fileIdPairs);
2079     BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
2080     MEDIA_INFO_LOG("end restore photo, offset: %{public}d", offset);
2081 }
2082 
RestoreBatchForCloud(int32_t offset,int32_t isRelatedToPhotoMap)2083 void CloneRestore::RestoreBatchForCloud(int32_t offset, int32_t isRelatedToPhotoMap)
2084 {
2085     MEDIA_INFO_LOG(
2086         "singlCloud restore photo, offset: %{public}d, isRelated: %{public}d", offset, isRelatedToPhotoMap);
2087     vector<FileInfo> fileInfos = QueryCloudFileInfos(offset, isRelatedToPhotoMap);
2088     CHECK_AND_EXECUTE(InsertCloudPhoto(sceneCode_, fileInfos, SourceType::PHOTOS) == E_OK,
2089         AddToPhotosFailedOffsets(offset));
2090     RestoreImageFaceInfo(fileInfos);
2091 
2092     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2093     BackupDatabaseUtils::UpdateAnalysisTotalTblNoFaceStatus(mediaLibraryRdb_, mediaRdb_, fileIdPairs);
2094     BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
2095     MEDIA_INFO_LOG("singleCloud end restore photo, offset: %{public}d", offset);
2096 }
2097 
InsertCloudPhoto(int32_t sceneCode,std::vector<FileInfo> & fileInfos,int32_t sourceType)2098 int CloneRestore::InsertCloudPhoto(int32_t sceneCode, std::vector<FileInfo> &fileInfos, int32_t sourceType)
2099 {
2100     MEDIA_INFO_LOG("singleCloud start insert cloud %{public}zu photos", fileInfos.size());
2101     CHECK_AND_RETURN_RET_LOG(mediaLibraryRdb_ != nullptr, E_OK,
2102         "singleCloud mediaLibraryRdb_ iS null in cloud clone");
2103     CHECK_AND_RETURN_RET_LOG(!fileInfos.empty(), E_OK, "singleCloud fileInfos are empty in cloud clone");
2104     int64_t startGenerate = MediaFileUtils::UTCTimeMilliSeconds();
2105     vector<NativeRdb::ValuesBucket> values = GetCloudInsertValues(sceneCode, fileInfos, sourceType);
2106     int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
2107     int64_t rowNum = 0;
2108     int32_t errCode = BatchInsertWithRetry(PhotoColumn::PHOTOS_TABLE, values, rowNum);
2109     MEDIA_INFO_LOG("singleCloud insertCloudPhoto is %{public}d, the rowNum is %{public}" PRId64, errCode, rowNum);
2110     migrateCloudSuccessNumber_ += rowNum;
2111     if (errCode != E_OK) {
2112         if (needReportFailed_) {
2113             UpdateFailedFiles(fileInfos, RestoreError::INSERT_FAILED);
2114             ErrorInfo errorInfo(RestoreError::INSERT_FAILED, static_cast<int32_t>(fileInfos.size()), errCode);
2115             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
2116         }
2117         return errCode;
2118     }
2119 
2120     int64_t startInsertRelated = MediaFileUtils::UTCTimeMilliSeconds();
2121     InsertPhotoRelated(fileInfos, SourceType::PHOTOS);
2122 
2123     // create dentry file for cloud origin, save failed cloud id
2124     std::vector<std::string> dentryFailedOrigin;
2125     CHECK_AND_EXECUTE(BatchCreateDentryFile(fileInfos, dentryFailedOrigin, DENTRY_INFO_ORIGIN) != E_OK,
2126         HandleFailData(fileInfos, dentryFailedOrigin, DENTRY_INFO_ORIGIN));
2127 
2128     int64_t startMove = MediaFileUtils::UTCTimeMilliSeconds();
2129     migrateDatabaseNumber_ += rowNum;
2130     int32_t fileMoveCount = 0;
2131     int32_t videoFileMoveCount = 0;
2132     MoveMigrateCloudFile(fileInfos, fileMoveCount, videoFileMoveCount, sceneCode);
2133     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2134     MEDIA_INFO_LOG("singleCloud generate values cost %{public}ld, insert %{public}ld assets cost %{public}ld, insert"
2135         " photo related cost %{public}ld, and move %{public}ld files (%{public}ld + %{public}ld) cost %{public}ld.",
2136         (long)(startInsert - startGenerate), (long)rowNum, (long)(startInsertRelated - startInsert),
2137         (long)(startMove - startInsertRelated), (long)fileMoveCount, (long)(fileMoveCount - videoFileMoveCount),
2138         (long)videoFileMoveCount, (long)(end - startMove));
2139     MEDIA_INFO_LOG("singleCLoud  insert cloud end");
2140     return E_OK;
2141 }
2142 
RestoreAudioBatch(int32_t offset)2143 void CloneRestore::RestoreAudioBatch(int32_t offset)
2144 {
2145     MEDIA_INFO_LOG("start restore audio, offset: %{public}d", offset);
2146     vector<FileInfo> fileInfos = QueryFileInfos(AudioColumn::AUDIOS_TABLE, offset);
2147     InsertAudio(fileInfos);
2148     MEDIA_INFO_LOG("end restore audio, offset: %{public}d", offset);
2149 }
2150 
AddToPhotoInfoMaps(std::vector<FileInfo> & fileInfos)2151 void CloneRestore::AddToPhotoInfoMaps(std::vector<FileInfo> &fileInfos)
2152 {
2153     std::lock_guard<ffrt::mutex> lock(photosInfoMutex_);
2154     for (auto fileInfo: fileInfos) {
2155         PhotoInfo photoInfo;
2156         photoInfo.fileIdNew = fileInfo.fileIdNew;
2157         photoInfo.fileType = fileInfo.fileType;
2158         photoInfo.displayName = fileInfo.displayName;
2159         photoInfo.cloudPath = fileInfo.cloudPath;
2160         photoInfoMap_.insert(std::make_pair(fileInfo.fileIdOld, photoInfo));
2161     }
2162 }
2163 
InsertPhotoRelated(vector<FileInfo> & fileInfos,int32_t sourceType)2164 void CloneRestore::InsertPhotoRelated(vector<FileInfo> &fileInfos, int32_t sourceType)
2165 {
2166     int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
2167     BatchQueryPhoto(fileInfos);
2168     AddToPhotoInfoMaps(fileInfos);
2169     int64_t startInsert = MediaFileUtils::UTCTimeMilliSeconds();
2170     int64_t mapRowNum = 0;
2171     BatchInsertMap(fileInfos, mapRowNum);
2172     migrateDatabaseMapNumber_ += mapRowNum;
2173     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2174     MEDIA_INFO_LOG("query new file_id cost %{public}ld, insert %{public}ld maps cost %{public}ld",
2175         (long)(startInsert - startQuery), (long)mapRowNum, (long)(end - startInsert));
2176 }
2177 
SetFileIdReference(const vector<FileInfo> & fileInfos,string & selection,unordered_map<int32_t,int32_t> & fileIdMap)2178 void CloneRestore::SetFileIdReference(const vector<FileInfo> &fileInfos, string &selection,
2179     unordered_map<int32_t, int32_t> &fileIdMap)
2180 {
2181     for (const auto &fileInfo : fileInfos) {
2182         if (fileInfo.fileIdOld <= 0 || fileInfo.fileIdNew <= 0) {
2183             continue;
2184         }
2185         BackupDatabaseUtils::UpdateSelection(selection, to_string(fileInfo.fileIdOld), false);
2186         fileIdMap[fileInfo.fileIdOld] = fileInfo.fileIdNew;
2187     }
2188 }
2189 
QueryMapTotalNumber(const string & baseQuerySql)2190 int32_t CloneRestore::QueryMapTotalNumber(const string &baseQuerySql)
2191 {
2192     string querySql = "SELECT count(1) as count FROM " + baseQuerySql;
2193     return BackupDatabaseUtils::QueryInt(mediaRdb_, querySql, CUSTOM_COUNT);
2194 }
2195 
QueryMapInfos(const string & tableName,const string & baseQuerySql,int32_t offset,const unordered_map<int32_t,int32_t> & fileIdMap,const unordered_map<int32_t,int32_t> & albumIdMap)2196 vector<MapInfo> CloneRestore::QueryMapInfos(const string &tableName, const string &baseQuerySql, int32_t offset,
2197     const unordered_map<int32_t, int32_t> &fileIdMap, const unordered_map<int32_t, int32_t> &albumIdMap)
2198 {
2199     vector<MapInfo> mapInfos;
2200     mapInfos.reserve(CLONE_QUERY_COUNT);
2201     string columnMapAlbum = tableName + "." + PhotoMap::ALBUM_ID;
2202     string columnMapAsset = tableName + "." + PhotoMap::ASSET_ID;
2203     string querySql = "SELECT " + columnMapAlbum + ", " + columnMapAsset + " FROM " + baseQuerySql;
2204     querySql += " LIMIT " + to_string(offset) + ", " + to_string(CLONE_QUERY_COUNT);
2205     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2206     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, mapInfos, "Query resultSql is null.");
2207     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2208         int32_t albumIdOld = GetInt32Val(columnMapAlbum, resultSet);
2209         int32_t fileIdOld = GetInt32Val(columnMapAsset, resultSet);
2210         if (albumIdOld <= 0 || albumIdMap.count(albumIdOld) == 0 || fileIdOld <= 0 || fileIdMap.count(fileIdOld) <= 0) {
2211             continue;
2212         }
2213         MapInfo mapInfo;
2214         mapInfo.albumId = albumIdMap.at(albumIdOld);
2215         mapInfo.fileId = fileIdMap.at(fileIdOld);
2216         mapInfos.emplace_back(mapInfo);
2217     }
2218     resultSet->Close();
2219     return mapInfos;
2220 }
2221 
InsertMapByTable(const string & tableName,const vector<MapInfo> & mapInfos,unordered_set<int32_t> & albumSet)2222 int64_t CloneRestore::InsertMapByTable(const string &tableName, const vector<MapInfo> &mapInfos,
2223     unordered_set<int32_t> &albumSet)
2224 {
2225     vector<NativeRdb::ValuesBucket> values = GetInsertValues(mapInfos);
2226     int64_t rowNum = 0;
2227     int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
2228     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, 0,
2229         "Batch insert map failed, errCode: %{public}d", errCode);
2230     for (const auto &mapInfo : mapInfos) {
2231         albumSet.insert(mapInfo.albumId);
2232     }
2233     return rowNum;
2234 }
2235 
GetInsertValues(const vector<MapInfo> & mapInfos)2236 vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(const vector<MapInfo> &mapInfos)
2237 {
2238     vector<NativeRdb::ValuesBucket> values;
2239     for (const auto &mapInfo : mapInfos) {
2240         NativeRdb::ValuesBucket value = GetInsertValue(mapInfo);
2241         values.emplace_back(value);
2242     }
2243     return values;
2244 }
2245 
GetQueryWhereClauseByTable(const string & tableName)2246 string CloneRestore::GetQueryWhereClauseByTable(const string &tableName)
2247 {
2248     string whereClause;
2249     if (tableQueryWhereClauseMap_.count(tableName)) {
2250         whereClause += tableQueryWhereClauseMap_.at(tableName);
2251     }
2252     if (tableExtraQueryWhereClauseMap_.count(tableName)) {
2253         whereClause += whereClause.empty() ? "" : " AND " + tableExtraQueryWhereClauseMap_.at(tableName);
2254     }
2255     return whereClause;
2256 }
2257 
SetSpecialAttributes(const string & tableName,const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)2258 void CloneRestore::SetSpecialAttributes(const string &tableName, const shared_ptr<NativeRdb::ResultSet> &resultSet,
2259     FileInfo &fileInfo)
2260 {
2261     if (tableName != PhotoColumn::PHOTOS_TABLE) {
2262         return;
2263     }
2264     fileInfo.lPath = GetStringVal(PhotoAlbumColumns::ALBUM_LPATH, resultSet);
2265     fileInfo.sourcePath = GetStringVal(PhotoColumn::PHOTO_SOURCE_PATH, resultSet);
2266     fileInfo.subtype = GetInt32Val(PhotoColumn::PHOTO_SUBTYPE, resultSet);
2267     fileInfo.associateFileId = GetInt32Val(PhotoColumn::PHOTO_ASSOCIATE_FILE_ID, resultSet);
2268     fileInfo.photoQuality = GetInt32Val(PhotoColumn::PHOTO_QUALITY, resultSet);
2269     fileInfo.recycledTime = GetInt64Val(MediaColumn::MEDIA_DATE_TRASHED, resultSet);
2270     fileInfo.hidden = GetInt32Val(MediaColumn::MEDIA_HIDDEN, resultSet);
2271     // find PhotoAlbum info in target database. PackageName and BundleName should be fixed after clone.
2272     fileInfo.lPath = this->photosClone_.FindlPath(fileInfo);
2273     fileInfo.ownerAlbumId = this->photosClone_.FindAlbumId(fileInfo);
2274     fileInfo.packageName = this->photosClone_.FindPackageName(fileInfo);
2275     fileInfo.bundleName = this->photosClone_.FindBundleName(fileInfo);
2276     fileInfo.photoQuality = this->photosClone_.FindPhotoQuality(fileInfo);
2277     fileInfo.sourcePath = this->photosClone_.FindSourcePath(fileInfo);
2278     fileInfo.latitude = GetDoubleVal("latitude", resultSet);
2279     fileInfo.longitude = GetDoubleVal("longitude", resultSet);
2280     GetOrientationAndExifRotateValue(resultSet, fileInfo);
2281 }
2282 
IsSameFileForClone(const string & tableName,FileInfo & fileInfo)2283 bool CloneRestore::IsSameFileForClone(const string &tableName, FileInfo &fileInfo)
2284 {
2285     CHECK_AND_RETURN_RET(tableName == PhotoColumn::PHOTOS_TABLE,
2286         IsSameAudioFile(mediaLibraryRdb_, tableName, fileInfo));
2287     PhotosDao::PhotosRowData rowData = this->photosClone_.FindSameFile(fileInfo);
2288     int32_t fileId = rowData.fileId;
2289     std::string cloudPath = rowData.data;
2290     bool cond = (fileId <= 0 || cloudPath.empty());
2291     CHECK_AND_RETURN_RET(!cond, false);
2292     // Meed extra check to determine whether or not to drop the duplicate file.
2293     return ExtraCheckForCloneSameFile(fileInfo, rowData);
2294 }
2295 
RestoreFromGalleryPortraitAlbum()2296 void CloneRestore::RestoreFromGalleryPortraitAlbum()
2297 {
2298     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2299     RecordOldPortraitAlbumDfx();
2300 
2301     std::string querySql =   "SELECT count(1) AS count FROM " + ANALYSIS_ALBUM_TABLE + " WHERE ";
2302     std::string whereClause = "(" + SMARTALBUM_DB_ALBUM_TYPE + " = " + std::to_string(SMART) + " AND " +
2303         "album_subtype" + " = " + std::to_string(PORTRAIT) + ")";
2304     AppendExtraWhereClause(whereClause, ANALYSIS_ALBUM_TABLE);
2305     querySql += whereClause;
2306 
2307     int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb_, querySql, CUSTOM_COUNT);
2308     MEDIA_INFO_LOG("QueryPortraitAlbum totalNumber = %{public}d", totalNumber);
2309 
2310     std::vector<std::string> commonColumn = BackupDatabaseUtils::GetCommonColumnInfos(mediaRdb_, mediaLibraryRdb_,
2311         ANALYSIS_ALBUM_TABLE);
2312     std::vector<std::string> commonColumns = BackupDatabaseUtils::filterColumns(commonColumn,
2313         EXCLUDED_PORTRAIT_COLUMNS);
2314 
2315     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
2316         std::vector<AnalysisAlbumTbl> analysisAlbumTbl = QueryPortraitAlbumTbl(offset, commonColumns);
2317         for (const auto& album : analysisAlbumTbl) {
2318             if (album.tagId.has_value() && album.coverUri.has_value()) {
2319                 coverUriInfo_.emplace_back(album.tagId.value(),
2320                     std::make_pair(album.coverUri.value(),
2321                     album.isCoverSatisfied.value_or(INVALID_COVER_SATISFIED_STATUS)));
2322             }
2323         }
2324 
2325         InsertPortraitAlbum(analysisAlbumTbl, maxAnalysisAlbumId_);
2326     }
2327 
2328     LogPortraitCloneDfx();
2329     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2330     migratePortraitTotalTimeCost_ += end - start;
2331 }
2332 
QueryPortraitAlbumTbl(int32_t offset,const std::vector<std::string> & commonColumns)2333 vector<AnalysisAlbumTbl> CloneRestore::QueryPortraitAlbumTbl(int32_t offset,
2334     const std::vector<std::string>& commonColumns)
2335 {
2336     vector<AnalysisAlbumTbl> result;
2337     result.reserve(QUERY_COUNT);
2338 
2339     std::string inClause = BackupDatabaseUtils::JoinValues<string>(commonColumns, ", ");
2340     std::string querySql =
2341         "SELECT " + inClause +
2342         " FROM " + ANALYSIS_ALBUM_TABLE +
2343         " WHERE ";
2344     std::string whereClause = "(" +
2345         SMARTALBUM_DB_ALBUM_TYPE + " = " + std::to_string(SMART) + " AND " +
2346         "album_subtype" + " = " + std::to_string(PORTRAIT) + ")";
2347     AppendExtraWhereClause(whereClause, ANALYSIS_ALBUM_TABLE);
2348     querySql += whereClause;
2349     querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
2350 
2351     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2352     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
2353 
2354     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2355         AnalysisAlbumTbl analysisAlbumTbl;
2356         ParsePortraitAlbumResultSet(resultSet, analysisAlbumTbl);
2357         result.emplace_back(analysisAlbumTbl);
2358     }
2359     resultSet->Close();
2360     return result;
2361 }
2362 
ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,AnalysisAlbumTbl & analysisAlbumTbl)2363 void CloneRestore::ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
2364     AnalysisAlbumTbl &analysisAlbumTbl)
2365 {
2366     analysisAlbumTbl.albumType = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_ALBUM_TYPE);
2367     analysisAlbumTbl.albumSubtype = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2368         ANALYSIS_COL_ALBUM_SUBTYPE);
2369     analysisAlbumTbl.albumName = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_ALBUM_NAME);
2370     analysisAlbumTbl.coverUri = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_COVER_URI);
2371     analysisAlbumTbl.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_TAG_ID);
2372     analysisAlbumTbl.userOperation = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2373         ANALYSIS_COL_USER_OPERATION);
2374     analysisAlbumTbl.groupTag = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_GROUP_TAG);
2375     analysisAlbumTbl.userDisplayLevel = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2376         ANALYSIS_COL_USER_DISPLAY_LEVEL);
2377     analysisAlbumTbl.isMe = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_IS_ME);
2378     analysisAlbumTbl.isRemoved = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_IS_REMOVED);
2379     analysisAlbumTbl.renameOperation = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2380         ANALYSIS_COL_RENAME_OPERATION);
2381     analysisAlbumTbl.isLocal = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_IS_LOCAL);
2382     analysisAlbumTbl.isCoverSatisfied = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2383         ANALYSIS_COL_IS_COVER_SATISFIED);
2384 }
2385 
ParseFaceTagResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FaceTagTbl & faceTagTbl)2386 void CloneRestore::ParseFaceTagResultSet(const std::shared_ptr<NativeRdb::ResultSet>& resultSet, FaceTagTbl& faceTagTbl)
2387 {
2388     faceTagTbl.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_TAG_ID);
2389     faceTagTbl.tagName = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_TAG_NAME);
2390     faceTagTbl.groupTag = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_GROUP_TAG);
2391     faceTagTbl.centerFeatures = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2392         FACE_TAG_COL_CENTER_FEATURES);
2393     faceTagTbl.tagVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, FACE_TAG_COL_TAG_VERSION);
2394     faceTagTbl.analysisVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2395         FACE_TAG_COL_ANALYSIS_VERSION);
2396 }
2397 
InsertPortraitAlbum(std::vector<AnalysisAlbumTbl> & analysisAlbumTbl,int64_t maxAlbumId)2398 void CloneRestore::InsertPortraitAlbum(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl, int64_t maxAlbumId)
2399 {
2400     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
2401     CHECK_AND_RETURN_LOG(!analysisAlbumTbl.empty(), "analysisAlbumTbl are empty");
2402 
2403     std::vector<std::string> albumNames;
2404     std::vector<std::string> tagIds;
2405 
2406     for (const auto &album : analysisAlbumTbl) {
2407         CHECK_AND_EXECUTE(!album.albumName.has_value(), albumNames.emplace_back(album.albumName.value()));
2408         CHECK_AND_EXECUTE(!album.tagId.has_value(), tagIds.emplace_back(album.tagId.value()));
2409     }
2410     MEDIA_INFO_LOG("Total albums: %{public}zu, Albums with names: %{public}zu, Albums with tagIds: %{public}zu",
2411                    analysisAlbumTbl.size(), albumNames.size(), tagIds.size());
2412 
2413     CHECK_AND_RETURN_LOG(BackupDatabaseUtils::DeleteDuplicatePortraitAlbum(maxAlbumId, albumNames,
2414         tagIds, mediaLibraryRdb_), "Batch delete failed.");
2415 
2416     int32_t albumRowNum = InsertPortraitAlbumByTable(analysisAlbumTbl);
2417     CHECK_AND_PRINT_LOG(albumRowNum != E_ERR, "Failed to insert album");
2418 
2419     migratePortraitAlbumNumber_ += static_cast<uint64_t>(albumRowNum);
2420     return;
2421 }
2422 
InsertPortraitAlbumByTable(std::vector<AnalysisAlbumTbl> & analysisAlbumTbl)2423 int32_t CloneRestore::InsertPortraitAlbumByTable(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl)
2424 {
2425     std::vector<NativeRdb::ValuesBucket> valuesBuckets = GetInsertValues(analysisAlbumTbl);
2426 
2427     int64_t rowNum = 0;
2428     int32_t ret = BatchInsertWithRetry(ANALYSIS_ALBUM_TABLE, valuesBuckets, rowNum);
2429     CHECK_AND_RETURN_RET(ret == E_OK, E_ERR);
2430     return rowNum;
2431 }
2432 
GetInsertValues(std::vector<AnalysisAlbumTbl> & analysisAlbumTbl)2433 std::vector<NativeRdb::ValuesBucket> CloneRestore::GetInsertValues(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl)
2434 {
2435     std::vector<NativeRdb::ValuesBucket> values;
2436     for (auto &portraitAlbumInfo : analysisAlbumTbl) {
2437         NativeRdb::ValuesBucket value = GetInsertValue(portraitAlbumInfo);
2438         values.emplace_back(value);
2439     }
2440     return values;
2441 }
2442 
GetInsertValue(const AnalysisAlbumTbl & portraitAlbumInfo)2443 NativeRdb::ValuesBucket CloneRestore::GetInsertValue(const AnalysisAlbumTbl &portraitAlbumInfo)
2444 {
2445     NativeRdb::ValuesBucket values;
2446 
2447     PutIfPresent(values, ANALYSIS_COL_ALBUM_TYPE, portraitAlbumInfo.albumType);
2448     PutIfPresent(values, ANALYSIS_COL_ALBUM_SUBTYPE, portraitAlbumInfo.albumSubtype);
2449     PutIfPresent(values, ANALYSIS_COL_ALBUM_NAME, portraitAlbumInfo.albumName);
2450     PutIfPresent(values, ANALYSIS_COL_TAG_ID, portraitAlbumInfo.tagId);
2451     PutIfPresent(values, ANALYSIS_COL_USER_OPERATION, portraitAlbumInfo.userOperation);
2452     PutIfPresent(values, ANALYSIS_COL_GROUP_TAG, portraitAlbumInfo.groupTag);
2453     PutIfPresent(values, ANALYSIS_COL_USER_DISPLAY_LEVEL, portraitAlbumInfo.userDisplayLevel);
2454     PutIfPresent(values, ANALYSIS_COL_IS_ME, portraitAlbumInfo.isMe);
2455     PutIfPresent(values, ANALYSIS_COL_IS_REMOVED, portraitAlbumInfo.isRemoved);
2456     PutIfPresent(values, ANALYSIS_COL_RENAME_OPERATION, portraitAlbumInfo.renameOperation);
2457     PutIfPresent(values, ANALYSIS_COL_IS_LOCAL, portraitAlbumInfo.isLocal);
2458 
2459     return values;
2460 }
2461 
CreateValuesBucketFromFaceTagTbl(const FaceTagTbl & faceTagTbl)2462 NativeRdb::ValuesBucket CloneRestore::CreateValuesBucketFromFaceTagTbl(const FaceTagTbl& faceTagTbl)
2463 {
2464     NativeRdb::ValuesBucket values;
2465 
2466     PutIfPresent(values, FACE_TAG_COL_TAG_ID, faceTagTbl.tagId);
2467     PutIfPresent(values, FACE_TAG_COL_TAG_NAME, faceTagTbl.tagName);
2468     PutIfPresent(values, FACE_TAG_COL_CENTER_FEATURES, faceTagTbl.centerFeatures);
2469     PutIfPresent(values, FACE_TAG_COL_TAG_VERSION, faceTagTbl.tagVersion);
2470     PutIfPresent(values, FACE_TAG_COL_ANALYSIS_VERSION, faceTagTbl.analysisVersion);
2471 
2472     return values;
2473 }
2474 
QueryAllPortraitAlbum(int32_t & offset,int32_t & rowCount)2475 std::vector<PortraitAlbumDfx> CloneRestore::QueryAllPortraitAlbum(int32_t& offset, int32_t& rowCount)
2476 {
2477     std::vector<PortraitAlbumDfx> result;
2478     result.reserve(QUERY_COUNT);
2479 
2480     const std::string querySql = "SELECT album_name, cover_uri, tag_id, count "
2481         "FROM AnalysisAlbum "
2482         "WHERE album_type = ? "
2483         "AND album_subtype = ? "
2484         "LIMIT ?, ?";
2485 
2486     std::vector<NativeRdb::ValueObject> bindArgs = { SMART, PORTRAIT, offset, QUERY_COUNT };
2487     CHECK_AND_RETURN_RET_LOG(this->mediaRdb_ != nullptr, result, "Media_Restore: mediaRdb_ is null.");
2488     auto resultSet = mediaRdb_->QuerySql(querySql, bindArgs);
2489     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
2490 
2491     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2492         PortraitAlbumDfx dfxInfo;
2493         dfxInfo.albumName = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_ALBUM_NAME);
2494         dfxInfo.coverUri = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_COVER_URI);
2495         dfxInfo.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_TAG_ID);
2496         dfxInfo.count = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, ANALYSIS_COL_COUNT);
2497 
2498         result.push_back(dfxInfo);
2499     }
2500     resultSet->GetRowCount(rowCount);
2501     resultSet->Close();
2502     return result;
2503 }
2504 
RecordOldPortraitAlbumDfx()2505 void CloneRestore::RecordOldPortraitAlbumDfx()
2506 {
2507     int32_t offset {0};
2508     int32_t rowCount {0};
2509     std::vector<PortraitAlbumDfx> albums;
2510 
2511     do {
2512         auto batchResults =  QueryAllPortraitAlbum(offset, rowCount);
2513         if (!batchResults.empty()) {
2514             albums.insert(albums.end(), batchResults.begin(), batchResults.end());
2515         }
2516 
2517         offset += QUERY_COUNT;
2518     } while (rowCount > 0);
2519 
2520     for (const auto& album : albums) {
2521         PortraitAlbumDfx dfxInfo;
2522         if (album.albumName.has_value()) {
2523             dfxInfo.albumName = album.albumName.value();
2524         }
2525         if (album.coverUri.has_value()) {
2526             auto uriParts = BackupDatabaseUtils::SplitString(album.coverUri.value(), '/');
2527             if (uriParts.size() >= COVER_URI_NUM) {
2528                 std::string fileName = uriParts[uriParts.size() - 1];
2529                 dfxInfo.coverUri = BackupFileUtils::GarbleFileName(fileName);
2530             }
2531         }
2532         if (album.tagId.has_value()) {
2533             dfxInfo.tagId = album.tagId.value();
2534         }
2535         if (album.count.has_value()) {
2536             dfxInfo.count = album.count.value();
2537         }
2538 
2539         portraitAlbumDfx_.push_back(dfxInfo);
2540     }
2541 }
2542 
QueryAllPortraitAlbum()2543 std::unordered_set<std::string> CloneRestore::QueryAllPortraitAlbum()
2544 {
2545     std::unordered_set<std::string> result;
2546     std::vector<std::string> tagIds;
2547     for (const auto& oldAlbum : portraitAlbumDfx_) {
2548         if (oldAlbum.tagId.has_value()) {
2549             tagIds.push_back(oldAlbum.tagId.value());
2550         }
2551     }
2552 
2553     CHECK_AND_RETURN_RET_LOG(!tagIds.empty(), result, "No valid tag_ids found in old albums");
2554 
2555     std::string querySql = "SELECT tag_id FROM " + ANALYSIS_ALBUM_TABLE +
2556         " WHERE tag_id IN (" + BackupDatabaseUtils::JoinSQLValues<string>(tagIds, ", ") + ")";
2557 
2558     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
2559     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
2560 
2561     std::string dfxInfo;
2562     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2563         dfxInfo =
2564             BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, ANALYSIS_COL_TAG_ID).value_or("");
2565         result.insert(dfxInfo);
2566     }
2567 
2568     resultSet->Close();
2569     return result;
2570 }
2571 
LogPortraitCloneDfx()2572 void CloneRestore::LogPortraitCloneDfx()
2573 {
2574     std::vector<std::string> failedAlbums;
2575     std::unordered_set<std::string> existingTagIds = QueryAllPortraitAlbum();
2576 
2577     for (const auto& oldAlbum : portraitAlbumDfx_) {
2578         if (!oldAlbum.tagId.has_value()) {
2579             continue;
2580         }
2581 
2582         if (existingTagIds.find(oldAlbum.tagId.value()) == existingTagIds.end()) {
2583             std::string albumInfo = "Album: " + oldAlbum.albumName.value_or("Unknown") +
2584                 ", TagId: " + oldAlbum.tagId.value() +
2585                 ", Cover: " + oldAlbum.coverUri.value_or("Unknown") +
2586                 ", Count: " + std::to_string(oldAlbum.count.value_or(0));
2587             failedAlbums.push_back(albumInfo);
2588         }
2589     }
2590 
2591     if (!failedAlbums.empty()) {
2592         MEDIA_ERR_LOG("Following portrait albums failed to clone completely:");
2593         for (const auto& failedAlbum : failedAlbums) {
2594             MEDIA_ERR_LOG("%{public}s", failedAlbum.c_str());
2595         }
2596     } else {
2597         MEDIA_INFO_LOG("All portrait albums cloned successfully");
2598     }
2599 
2600     MEDIA_INFO_LOG("Stat: Total albums: %{public}zu, Failed albums count: %{public}zu",
2601         portraitAlbumDfx_.size(), failedAlbums.size());
2602 }
2603 
RestorePortraitClusteringInfo()2604 void CloneRestore::RestorePortraitClusteringInfo()
2605 {
2606     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2607     int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb_, QUERY_FACE_TAG_COUNT, CUSTOM_COUNT);
2608     MEDIA_INFO_LOG("QueryPortraitClustering totalNumber = %{public}d", totalNumber);
2609 
2610     std::vector<std::string> commonColumn = BackupDatabaseUtils::GetCommonColumnInfos(mediaRdb_, mediaLibraryRdb_,
2611         VISION_FACE_TAG_TABLE);
2612     std::vector<std::string> commonColumns = BackupDatabaseUtils::filterColumns(commonColumn,
2613         EXCLUDED_FACE_TAG_COLUMNS);
2614     BackupDatabaseUtils::LeftJoinValues<string>(commonColumns, "vft.");
2615     std::string inClause = BackupDatabaseUtils::JoinValues<string>(commonColumns, ", ");
2616     BackupDatabaseUtils::ExecuteSQL(mediaRdb_, CREATE_FACE_TAG_INDEX);
2617     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
2618         vector<FaceTagTbl> faceTagTbls = QueryFaceTagTbl(offset, inClause);
2619         BatchInsertFaceTags(faceTagTbls);
2620         if (static_cast<std::int32_t>(faceTagTbls.size()) < QUERY_COUNT) {
2621             break;
2622         }
2623     }
2624     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2625     migratePortraitTotalTimeCost_ += end - start;
2626 }
2627 
QueryFaceTagTbl(int32_t offset,const std::string & inClause)2628 std::vector<FaceTagTbl> CloneRestore::QueryFaceTagTbl(int32_t offset, const std::string &inClause)
2629 {
2630     std::vector<FaceTagTbl> result;
2631 
2632     std::string querySql = "SELECT DISTINCT " + inClause +
2633         " FROM " + VISION_FACE_TAG_TABLE + " vft" +
2634         " LEFT JOIN AnalysisAlbum aa ON aa.tag_id = vft.tag_id" +
2635         " LEFT JOIN AnalysisPhotoMap apm ON aa.album_id = apm.map_album" +
2636         " LEFT JOIN Photos ph ON ph.file_id = apm.map_asset" +
2637         " WHERE " +
2638         (IsCloudRestoreSatisfied() ? "ph.position IN (1, 2, 3)" : "ph.position IN (1, 3)");
2639 
2640     querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
2641 
2642     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2643     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSet is null.");
2644     int resultRowCount = 0;
2645     resultSet->GetRowCount(resultRowCount);
2646     result.reserve(resultRowCount);
2647     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2648         FaceTagTbl faceTagTbl;
2649         ParseFaceTagResultSet(resultSet, faceTagTbl);
2650         result.emplace_back(faceTagTbl);
2651     }
2652 
2653     resultSet->Close();
2654     return result;
2655 }
2656 
BatchInsertFaceTags(const std::vector<FaceTagTbl> & faceTagTbls)2657 void CloneRestore::BatchInsertFaceTags(const std::vector<FaceTagTbl>& faceTagTbls)
2658 {
2659     std::vector<NativeRdb::ValuesBucket> valuesBuckets;
2660     for (const auto& faceTagTbl : faceTagTbls) {
2661         valuesBuckets.push_back(CreateValuesBucketFromFaceTagTbl(faceTagTbl));
2662     }
2663 
2664     int64_t rowNum = 0;
2665     int32_t ret = BatchInsertWithRetry(VISION_FACE_TAG_TABLE, valuesBuckets, rowNum);
2666     CHECK_AND_RETURN_LOG(ret == E_OK, "Failed to batch insert face tags");
2667 }
2668 
RestoreImageFaceInfo(std::vector<FileInfo> & fileInfos)2669 void CloneRestore::RestoreImageFaceInfo(std::vector<FileInfo> &fileInfos)
2670 {
2671     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2672     auto uniqueFileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2673     auto [oldFileIds, newFileIds] = BackupDatabaseUtils::UnzipFileIdPairs(uniqueFileIdPairs);
2674 
2675     std::string fileIdOldInClause = "(" + BackupDatabaseUtils::JoinValues<int>(oldFileIds, ", ") + ")";
2676 
2677     std::string querySql = QUERY_IMAGE_FACE_COUNT;
2678     querySql += " WHERE " + IMAGE_FACE_COL_FILE_ID + " IN " + fileIdOldInClause;
2679     int32_t totalNumber = BackupDatabaseUtils::QueryInt(mediaRdb_, querySql, CUSTOM_COUNT);
2680     MEDIA_INFO_LOG("QueryImageFaceTotalNumber, totalNumber = %{public}d", totalNumber);
2681     if (totalNumber == 0) {
2682         int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2683         migratePortraitTotalTimeCost_ += end - start;
2684         return;
2685     }
2686 
2687     std::vector<std::string> commonColumn = BackupDatabaseUtils::GetCommonColumnInfos(mediaRdb_, mediaLibraryRdb_,
2688         VISION_IMAGE_FACE_TABLE);
2689     std::vector<std::string> commonColumns = BackupDatabaseUtils::filterColumns(commonColumn,
2690         EXCLUDED_IMAGE_FACE_COLUMNS);
2691 
2692     BackupDatabaseUtils::DeleteExistingImageFaceData(mediaLibraryRdb_, uniqueFileIdPairs);
2693     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
2694         std::vector<ImageFaceTbl> imageFaceTbls = QueryImageFaceTbl(offset, fileIdOldInClause, commonColumns);
2695         auto imageFaces = ProcessImageFaceTbls(imageFaceTbls, uniqueFileIdPairs);
2696         BatchInsertImageFaces(imageFaces);
2697     }
2698 
2699     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2700     migratePortraitTotalTimeCost_ += end - start;
2701 
2702     GenNewCoverUris(coverUriInfo_, fileInfos);
2703 }
2704 
QueryImageFaceTbl(int32_t offset,std::string & fileIdClause,const std::vector<std::string> & commonColumns)2705 std::vector<ImageFaceTbl> CloneRestore::QueryImageFaceTbl(int32_t offset, std::string &fileIdClause,
2706     const std::vector<std::string> &commonColumns)
2707 {
2708     std::vector<ImageFaceTbl> result;
2709     result.reserve(QUERY_COUNT);
2710 
2711     std::string inClause = BackupDatabaseUtils::JoinValues<string>(commonColumns, ", ");
2712     std::string querySql =
2713         "SELECT " + inClause +
2714         " FROM " + VISION_IMAGE_FACE_TABLE;
2715     querySql += " WHERE " + IMAGE_FACE_COL_FILE_ID + " IN " + fileIdClause;
2716     querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
2717 
2718     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
2719     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSet is null.");
2720 
2721     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2722         ImageFaceTbl imageFaceTbl;
2723         ParseImageFaceResultSet(resultSet, imageFaceTbl);
2724         result.emplace_back(imageFaceTbl);
2725     }
2726 
2727     resultSet->Close();
2728     return result;
2729 }
2730 
GetFileInfoByFileId(int32_t fileId,const std::vector<FileInfo> & fileInfos,FileInfo & outFileInfo)2731 bool CloneRestore::GetFileInfoByFileId(int32_t fileId, const std::vector<FileInfo>& fileInfos, FileInfo& outFileInfo)
2732 {
2733     auto it = std::find_if(fileInfos.begin(), fileInfos.end(),
2734         [fileId](const FileInfo& info) { return info.fileIdNew == fileId; });
2735     if (it != fileInfos.end()) {
2736         outFileInfo = *it;
2737         return true;
2738     }
2739 
2740     return false;
2741 }
2742 
GenNewCoverUris(const std::vector<CloneRestore::CoverUriInfo> & coverUriInfo,std::vector<FileInfo> & fileInfos)2743 void CloneRestore::GenNewCoverUris(const std::vector<CloneRestore::CoverUriInfo>& coverUriInfo,
2744     std::vector<FileInfo> &fileInfos)
2745 {
2746     bool cond = (coverUriInfo.empty() && fileInfos.empty());
2747     CHECK_AND_RETURN_LOG(!cond, "Empty coverUriInfo or fileIdPairs, skipping.");
2748 
2749     std::unordered_map<std::string, std::pair<std::string, int32_t>> tagIdToCoverInfo;
2750     for (const auto& [tagId, coverInfo] : coverUriInfo) {
2751         tagIdToCoverInfo[tagId] = coverInfo;
2752     }
2753 
2754     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
2755     std::unordered_map<std::string, int32_t> oldToNewFileId;
2756     for (const auto& [oldId, newId] : fileIdPairs) {
2757         oldToNewFileId[std::to_string(oldId)] = newId;
2758     }
2759 
2760     std::vector<std::string> tagIds;
2761     std::string updateSql = GenCoverUriUpdateSql(tagIdToCoverInfo, oldToNewFileId, fileInfos, tagIds);
2762     if (updateSql.empty()) {
2763         return;
2764     }
2765 
2766     BackupDatabaseUtils::ExecuteSQL(mediaLibraryRdb_, updateSql);
2767 }
2768 
GenCoverUriUpdateSql(const std::unordered_map<std::string,std::pair<std::string,int32_t>> & tagIdToCoverInfo,const std::unordered_map<std::string,int32_t> & oldToNewFileId,const std::vector<FileInfo> & fileInfos,std::vector<std::string> & tagIds)2769 std::string CloneRestore::GenCoverUriUpdateSql(const std::unordered_map<std::string, std::pair<std::string, int32_t>>&
2770     tagIdToCoverInfo, const std::unordered_map<std::string, int32_t>& oldToNewFileId,
2771     const std::vector<FileInfo>& fileInfos, std::vector<std::string>& tagIds)
2772 {
2773     std::unordered_map<std::string, std::string> coverUriUpdates;
2774     std::unordered_map<std::string, int32_t> isCoverSatisfiedUpdates;
2775 
2776     for (const auto& [tagId, coverInfo] : tagIdToCoverInfo) {
2777         const auto& [oldCoverUri, isCoverSatisfied] = coverInfo;
2778         std::string newUri = ProcessUriAndGenNew(tagId, oldCoverUri, oldToNewFileId, fileInfos);
2779         if (!newUri.empty()) {
2780             coverUriUpdates[tagId] = newUri;
2781             isCoverSatisfiedUpdates[tagId] = isCoverSatisfied;
2782             tagIds.push_back(tagId);
2783         }
2784     }
2785 
2786     bool cond = (coverUriUpdates.empty() || isCoverSatisfiedUpdates.empty());
2787     CHECK_AND_RETURN_RET(!cond, "");
2788 
2789     std::string updateSql = "UPDATE AnalysisAlbum SET ";
2790 
2791     updateSql += "cover_uri = CASE ";
2792     for (const auto& [tagId, newUri] : coverUriUpdates) {
2793         updateSql += "WHEN tag_id = '" + tagId + "' THEN '" + newUri + "' ";
2794     }
2795     updateSql += "ELSE cover_uri END";
2796 
2797     bool hasValidIsCoverSatisfied = false;
2798     std::string isCoverSatisfiedSql = ", is_cover_satisfied = CASE ";
2799     for (const auto& [tagId, isCoverSatisfied] : isCoverSatisfiedUpdates) {
2800         if (isCoverSatisfied != INVALID_COVER_SATISFIED_STATUS) {
2801             hasValidIsCoverSatisfied = true;
2802             isCoverSatisfiedSql += "WHEN tag_id = '" + tagId + "' THEN " + std::to_string(isCoverSatisfied) + " ";
2803         }
2804     }
2805 
2806     isCoverSatisfiedSql += "ELSE is_cover_satisfied END ";
2807     CHECK_AND_EXECUTE(!hasValidIsCoverSatisfied, updateSql += isCoverSatisfiedSql);
2808 
2809     updateSql += "WHERE tag_id IN ('" +
2810         BackupDatabaseUtils::JoinValues(tagIds, "','") + "')";
2811 
2812     return updateSql;
2813 }
2814 
ProcessUriAndGenNew(const std::string & tagId,const std::string & oldCoverUri,const std::unordered_map<std::string,int32_t> & oldToNewFileId,const std::vector<FileInfo> & fileInfos)2815 std::string CloneRestore::ProcessUriAndGenNew(const std::string& tagId, const std::string& oldCoverUri,
2816     const std::unordered_map<std::string, int32_t>& oldToNewFileId, const std::vector<FileInfo>& fileInfos)
2817 {
2818     auto uriParts = BackupDatabaseUtils::SplitString(oldCoverUri, '/');
2819     if (uriParts.size() >= COVER_URI_NUM) {
2820         std::string fileIdOld = uriParts[uriParts.size() - 3];
2821         auto it = oldToNewFileId.find(fileIdOld);
2822         if (it != oldToNewFileId.end()) {
2823             int32_t fileIdNew = it->second;
2824             FileInfo fileInfo {};
2825             if (GetFileInfoByFileId(fileIdNew, fileInfos, fileInfo)) {
2826                 std::string extraUri = MediaFileUtils::GetExtraUri(fileInfo.displayName, fileInfo.cloudPath);
2827                 return MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
2828                     std::to_string(fileIdNew), extraUri);
2829             }
2830         }
2831     }
2832     return "";
2833 }
2834 
ProcessImageFaceTbls(const std::vector<ImageFaceTbl> & imageFaceTbls,const std::vector<FileIdPair> & fileIdPairs)2835 std::vector<ImageFaceTbl> CloneRestore::ProcessImageFaceTbls(const std::vector<ImageFaceTbl>& imageFaceTbls,
2836     const std::vector<FileIdPair>& fileIdPairs)
2837 {
2838     CHECK_AND_RETURN_RET_LOG(!imageFaceTbls.empty(), {}, "image faces tbl empty");
2839 
2840     std::vector<ImageFaceTbl> imageFaceNewTbls;
2841     imageFaceNewTbls.reserve(imageFaceTbls.size());
2842 
2843     for (const auto& imageFaceTbl : imageFaceTbls) {
2844         if (imageFaceTbl.fileId.has_value()) {
2845             int32_t oldFileId = imageFaceTbl.fileId.value();
2846             auto it = std::find_if(fileIdPairs.begin(), fileIdPairs.end(),
2847                 [oldFileId](const FileIdPair& pair) { return pair.first == oldFileId; });
2848             if (it != fileIdPairs.end()) {
2849                 ImageFaceTbl updatedFace = imageFaceTbl;
2850                 updatedFace.fileId = it->second;
2851                 imageFaceNewTbls.push_back(std::move(updatedFace));
2852             }
2853         }
2854     }
2855 
2856     return imageFaceNewTbls;
2857 }
2858 
BatchInsertImageFaces(const std::vector<ImageFaceTbl> & imageFaceTbls)2859 void CloneRestore::BatchInsertImageFaces(const std::vector<ImageFaceTbl>& imageFaceTbls)
2860 {
2861     std::vector<NativeRdb::ValuesBucket> valuesBuckets;
2862     std::unordered_set<int32_t> fileIdSet;
2863     for (const auto& imageFaceTbl : imageFaceTbls) {
2864         valuesBuckets.push_back(CreateValuesBucketFromImageFaceTbl(imageFaceTbl));
2865     }
2866 
2867     int64_t rowNum = 0;
2868     int32_t ret = BatchInsertWithRetry(VISION_IMAGE_FACE_TABLE, valuesBuckets, rowNum);
2869     CHECK_AND_RETURN_LOG(ret == E_OK, "Failed to batch insert image faces");
2870 
2871     for (const auto& imageFaceTbl : imageFaceTbls) {
2872         if (imageFaceTbl.fileId.has_value()) {
2873             fileIdSet.insert(imageFaceTbl.fileId.value());
2874         }
2875     }
2876 
2877     migratePortraitFaceNumber_ += rowNum;
2878     migratePortraitPhotoNumber_ += fileIdSet.size();
2879 }
2880 
CreateValuesBucketFromImageFaceTbl(const ImageFaceTbl & imageFaceTbl)2881 NativeRdb::ValuesBucket CloneRestore::CreateValuesBucketFromImageFaceTbl(const ImageFaceTbl& imageFaceTbl)
2882 {
2883     NativeRdb::ValuesBucket values;
2884 
2885     PutIfPresent(values, IMAGE_FACE_COL_FILE_ID, imageFaceTbl.fileId);
2886     PutIfPresent(values, IMAGE_FACE_COL_FACE_ID, imageFaceTbl.faceId);
2887     PutIfPresent(values, IMAGE_FACE_COL_TAG_ID, imageFaceTbl.tagId);
2888     PutIfPresent(values, IMAGE_FACE_COL_SCALE_X, imageFaceTbl.scaleX);
2889     PutIfPresent(values, IMAGE_FACE_COL_SCALE_Y, imageFaceTbl.scaleY);
2890     PutIfPresent(values, IMAGE_FACE_COL_SCALE_WIDTH, imageFaceTbl.scaleWidth);
2891     PutIfPresent(values, IMAGE_FACE_COL_SCALE_HEIGHT, imageFaceTbl.scaleHeight);
2892     PutIfPresent(values, IMAGE_FACE_COL_LANDMARKS, imageFaceTbl.landmarks);
2893     PutIfPresent(values, IMAGE_FACE_COL_PITCH, imageFaceTbl.pitch);
2894     PutIfPresent(values, IMAGE_FACE_COL_YAW, imageFaceTbl.yaw);
2895     PutIfPresent(values, IMAGE_FACE_COL_ROLL, imageFaceTbl.roll);
2896     PutIfPresent(values, IMAGE_FACE_COL_PROB, imageFaceTbl.prob);
2897     PutIfPresent(values, IMAGE_FACE_COL_TOTAL_FACES, imageFaceTbl.totalFaces);
2898     PutIfPresent(values, IMAGE_FACE_COL_FACE_VERSION, imageFaceTbl.faceVersion);
2899     PutIfPresent(values, IMAGE_FACE_COL_FEATURES_VERSION, imageFaceTbl.featuresVersion);
2900     PutIfPresent(values, IMAGE_FACE_COL_FEATURES, imageFaceTbl.features);
2901     PutIfPresent(values, IMAGE_FACE_COL_FACE_OCCLUSION, imageFaceTbl.faceOcclusion);
2902     PutIfPresent(values, IMAGE_FACE_COL_ANALYSIS_VERSION, imageFaceTbl.analysisVersion);
2903     PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_X, imageFaceTbl.beautyBounderX);
2904     PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_Y, imageFaceTbl.beautyBounderY);
2905     PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_WIDTH, imageFaceTbl.beautyBounderWidth);
2906     PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_HEIGHT, imageFaceTbl.beautyBounderHeight);
2907     PutIfPresent(values, IMAGE_FACE_COL_AESTHETICS_SCORE, imageFaceTbl.aestheticsScore);
2908     PutIfPresent(values, IMAGE_FACE_COL_BEAUTY_BOUNDER_VERSION, imageFaceTbl.beautyBounderVersion);
2909     PutWithDefault<int>(values, IMAGE_FACE_COL_IS_EXCLUDED, imageFaceTbl.isExcluded, 0);
2910     PutIfPresent(values, IMAGE_FACE_COL_FACE_CLARITY, imageFaceTbl.faceClarity);
2911     PutIfPresent(values, IMAGE_FACE_COL_FACE_LUMINANCE, imageFaceTbl.faceLuminance);
2912     PutIfPresent(values, IMAGE_FACE_COL_FACE_SATURATION, imageFaceTbl.faceSaturation);
2913     PutIfPresent(values, IMAGE_FACE_COL_FACE_EYE_CLOSE, imageFaceTbl.faceEyeClose);
2914     PutIfPresent(values, IMAGE_FACE_COL_FACE_EXPRESSION, imageFaceTbl.faceExpression);
2915     PutIfPresent(values, IMAGE_FACE_COL_PREFERRED_GRADE, imageFaceTbl.preferredGrade);
2916     PutIfPresent(values, IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_X, imageFaceTbl.jointBeautyBounderX);
2917     PutIfPresent(values, IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_Y, imageFaceTbl.jointBeautyBounderY);
2918     PutIfPresent(values, IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_WIDTH, imageFaceTbl.jointBeautyBounderWidth);
2919     PutIfPresent(values, IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_HEIGHT, imageFaceTbl.jointBeautyBounderHeight);
2920     return values;
2921 }
2922 
ParseImageFaceResultSet1(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,ImageFaceTbl & imageFaceTbl)2923 void ParseImageFaceResultSet1(const std::shared_ptr<NativeRdb::ResultSet>& resultSet, ImageFaceTbl& imageFaceTbl)
2924 {
2925     imageFaceTbl.preferredGrade = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2926         IMAGE_FACE_COL_PREFERRED_GRADE);
2927     imageFaceTbl.jointBeautyBounderX = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2928         IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_X);
2929     imageFaceTbl.jointBeautyBounderY = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2930         IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_Y);
2931     imageFaceTbl.jointBeautyBounderWidth = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2932         IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_WIDTH);
2933     imageFaceTbl.jointBeautyBounderHeight = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2934         IMAGE_FACE_COL_JOINT_BEAUTY_BOUNDER_HEIGHT);
2935     imageFaceTbl.groupVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2936         IMAGE_FACE_COL_GROUP_VERSION);
2937 }
2938 
ParseImageFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,ImageFaceTbl & imageFaceTbl)2939 void CloneRestore::ParseImageFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
2940     ImageFaceTbl& imageFaceTbl)
2941 {
2942     imageFaceTbl.fileId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, IMAGE_FACE_COL_FILE_ID);
2943     imageFaceTbl.faceId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_FACE_ID);
2944     imageFaceTbl.tagId = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_TAG_ID);
2945     imageFaceTbl.scaleX = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_X);
2946     imageFaceTbl.scaleY = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_Y);
2947     imageFaceTbl.scaleWidth = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_WIDTH);
2948     imageFaceTbl.scaleHeight = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_SCALE_HEIGHT);
2949     imageFaceTbl.landmarks = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, IMAGE_FACE_COL_LANDMARKS);
2950     imageFaceTbl.pitch = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_PITCH);
2951     imageFaceTbl.yaw = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_YAW);
2952     imageFaceTbl.roll = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_ROLL);
2953     imageFaceTbl.prob = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_PROB);
2954     imageFaceTbl.totalFaces = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, IMAGE_FACE_COL_TOTAL_FACES);
2955     imageFaceTbl.faceVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2956         IMAGE_FACE_COL_FACE_VERSION);
2957     imageFaceTbl.featuresVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2958         IMAGE_FACE_COL_FEATURES_VERSION);
2959     imageFaceTbl.features = BackupDatabaseUtils::GetOptionalValue<std::vector<uint8_t>>(resultSet,
2960         IMAGE_FACE_COL_FEATURES);
2961     imageFaceTbl.faceOcclusion = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2962         IMAGE_FACE_COL_FACE_OCCLUSION);
2963     imageFaceTbl.analysisVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2964         IMAGE_FACE_COL_ANALYSIS_VERSION);
2965     imageFaceTbl.beautyBounderX = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2966         IMAGE_FACE_COL_BEAUTY_BOUNDER_X);
2967     imageFaceTbl.beautyBounderY = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2968         IMAGE_FACE_COL_BEAUTY_BOUNDER_Y);
2969     imageFaceTbl.beautyBounderWidth = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2970         IMAGE_FACE_COL_BEAUTY_BOUNDER_WIDTH);
2971     imageFaceTbl.beautyBounderHeight = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2972         IMAGE_FACE_COL_BEAUTY_BOUNDER_HEIGHT);
2973     imageFaceTbl.aestheticsScore = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2974         IMAGE_FACE_COL_AESTHETICS_SCORE);
2975     imageFaceTbl.beautyBounderVersion = BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet,
2976         IMAGE_FACE_COL_BEAUTY_BOUNDER_VERSION);
2977     imageFaceTbl.isExcluded = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, IMAGE_FACE_COL_IS_EXCLUDED);
2978     imageFaceTbl.faceClarity = BackupDatabaseUtils::GetOptionalValue<double>(resultSet, IMAGE_FACE_COL_FACE_CLARITY);
2979     imageFaceTbl.faceLuminance = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2980         IMAGE_FACE_COL_FACE_LUMINANCE);
2981     imageFaceTbl.faceSaturation = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2982         IMAGE_FACE_COL_FACE_SATURATION);
2983     imageFaceTbl.faceEyeClose = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet,
2984         IMAGE_FACE_COL_FACE_EYE_CLOSE);
2985     imageFaceTbl.faceExpression = BackupDatabaseUtils::GetOptionalValue<double>(resultSet,
2986         IMAGE_FACE_COL_FACE_EXPRESSION);
2987     ParseImageFaceResultSet1(resultSet, imageFaceTbl);
2988 }
2989 
ReportPortraitCloneStat(int32_t sceneCode)2990 void CloneRestore::ReportPortraitCloneStat(int32_t sceneCode)
2991 {
2992     CHECK_AND_RETURN_LOG(sceneCode == CLONE_RESTORE_ID, "err scenecode %{public}d", sceneCode);
2993 
2994     MEDIA_INFO_LOG("PortraitStat: album %{public}lld, photo %{public}lld, face %{public}lld, cost %{public}lld",
2995         (long long)migratePortraitAlbumNumber_, (long long)migratePortraitPhotoNumber_,
2996         (long long)migratePortraitFaceNumber_, (long long)migratePortraitTotalTimeCost_);
2997 
2998     BackupDfxUtils::PostPortraitStat(static_cast<uint32_t>(migratePortraitAlbumNumber_), migratePortraitPhotoNumber_,
2999         migratePortraitFaceNumber_, migratePortraitTotalTimeCost_);
3000 }
3001 
AppendExtraWhereClause(std::string & whereClause,const std::string & tableName)3002 void CloneRestore::AppendExtraWhereClause(std::string& whereClause, const std::string& tableName)
3003 {
3004     auto it = tableExtraQueryWhereClauseMap_.find(tableName);
3005     if (it != tableExtraQueryWhereClauseMap_.end()) {
3006         whereClause += whereClause.empty() ? "" : " AND ";
3007         whereClause += it->second;
3008     }
3009 }
3010 
InitAllKvStore()3011 bool CloneRestore::InitAllKvStore()
3012 {
3013     std::string oldBaseDir = backupRestoreDir_ + CLONE_KVDB_BACKUP_DIR;
3014     std::string newBaseDir = MEDIA_KVDB_DIR;
3015     oldMonthKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
3016         .GetSingleKvStore(KvStoreRoleType::OWNER, CLONE_KVSTORE_MONTH_STOREID, oldBaseDir);
3017     oldYearKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
3018         .GetSingleKvStore(KvStoreRoleType::OWNER, CLONE_KVSTORE_YEAR_STOREID, oldBaseDir);
3019     newMonthKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
3020         .GetSingleKvStore(KvStoreRoleType::OWNER, MEDIA_KVSTORE_MONTH_STOREID, newBaseDir);
3021     newYearKvStorePtr_ = MediaLibraryKvStoreManager::GetInstance()
3022         .GetSingleKvStore(KvStoreRoleType::OWNER, MEDIA_KVSTORE_YEAR_STOREID, newBaseDir);
3023 
3024     bool cond = (oldMonthKvStorePtr_ == nullptr || oldYearKvStorePtr_ == nullptr ||
3025         newMonthKvStorePtr_ == nullptr || newYearKvStorePtr_ == nullptr);
3026     CHECK_AND_RETURN_RET_LOG(!cond, false, "Init all kvstore failed");
3027     return true;
3028 }
3029 
CloseAllKvStore()3030 void CloneRestore::CloseAllKvStore()
3031 {
3032     oldMonthKvStorePtr_ != nullptr && oldMonthKvStorePtr_->Close();
3033     oldYearKvStorePtr_ != nullptr && oldYearKvStorePtr_->Close();
3034     newMonthKvStorePtr_ != nullptr && newMonthKvStorePtr_->Close();
3035     newYearKvStorePtr_ != nullptr && newYearKvStorePtr_->Close();
3036 }
3037 
StartBackup()3038 void CloneRestore::StartBackup()
3039 {
3040     MEDIA_INFO_LOG("enter clone backup");
3041     if (WaitSouthDeviceExitTimeout()) {
3042         MEDIA_ERR_LOG("backup, wait south device cleaning data timeout.");
3043         SetErrorCode(RestoreError::RETAIN_FORCE_TIMEOUT);
3044         ErrorInfo errorInfo(RestoreError::RETAIN_FORCE_TIMEOUT, 0, "",
3045             "backup, wait south device cleaning data timeout.");
3046         UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
3047         return;
3048     }
3049     MEDIA_INFO_LOG("Start clone backup");
3050     SetParameterForBackup();
3051     bool cond = (!BackupKvStore() && !MediaFileUtils::DeleteDir(CLONE_KVDB_BACKUP_DIR));
3052     CHECK_AND_PRINT_LOG(!cond, "BackupKvStore failed and delete old backup kvdb failed, errno:%{public}d", errno);
3053     MEDIA_INFO_LOG("End clone backup");
3054 }
3055 
InheritManualCover()3056 void CloneRestore::InheritManualCover()
3057 {
3058     std::string querySql = "SELECT album_id, cover_uri, cover_uri_source, cover_cloud_id"
3059         " FROM PhotoAlbum WHERE cover_uri_source > 0";
3060     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, querySql);
3061     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Query resultSql is null.");
3062 
3063     vector<AlbumCoverInfo> albumCoverinfos;
3064     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
3065         AlbumCoverInfo albumCoverInfo;
3066         int32_t albumIdOld = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
3067         string coverUriOld = GetStringVal(PhotoAlbumColumns::ALBUM_COVER_URI, resultSet);
3068         int32_t fileIdOld = atoi(MediaLibraryDataManagerUtils::GetFileIdFromPhotoUri(coverUriOld).c_str());
3069         int32_t coverUriSourceOld = GetInt32Val(PhotoAlbumColumns::COVER_URI_SOURCE, resultSet);
3070         string coverCloudIdOld = GetStringVal(PhotoAlbumColumns::COVER_CLOUD_ID, resultSet);
3071 
3072         int32_t albumIdNew = tableAlbumIdMap_[PhotoAlbumColumns::TABLE][albumIdOld];
3073         auto photoInfo = photoInfoMap_[fileIdOld];
3074         int32_t fileIdNew = photoInfo.fileIdNew;
3075         string coverUriNew = MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileIdNew),
3076             MediaFileUtils::GetExtraUri(photoInfo.displayName, photoInfo.cloudPath));
3077         albumCoverInfo.albumId = albumIdNew;
3078         albumCoverInfo.coverUri = coverUriNew;
3079         albumCoverInfo.coverUriSource = coverUriSourceOld;
3080         albumCoverInfo.coverCloudId = coverCloudIdOld;
3081         albumCoverinfos.emplace_back(albumCoverInfo);
3082     }
3083     resultSet->Close();
3084 
3085     UpdatePhotoAlbumCoverUri(albumCoverinfos);
3086 }
3087 
BackupKvStore()3088 bool CloneRestore::BackupKvStore()
3089 {
3090     MEDIA_INFO_LOG("Start BackupKvstore");
3091     // Delete only redundant data and do not need to be returned.
3092     CHECK_AND_EXECUTE(!MediaFileUtils::IsFileExists(CLONE_KVDB_BACKUP_DIR),
3093         MediaFileUtils::DeleteDir(CLONE_KVDB_BACKUP_DIR));
3094     std::string backupKvdbPath = CLONE_KVDB_BACKUP_DIR + "/kvdb";
3095     CHECK_AND_RETURN_RET_LOG(BackupFileUtils::PreparePath(backupKvdbPath) == E_OK,
3096         false, "Prepare backup dir failed");
3097 
3098     int32_t status = MediaLibraryKvStoreManager::GetInstance().CloneKvStore(
3099         MEDIA_KVSTORE_MONTH_STOREID, MEDIA_KVDB_DIR, CLONE_KVSTORE_MONTH_STOREID, CLONE_KVDB_BACKUP_DIR);
3100     CHECK_AND_RETURN_RET(status == E_OK, false);
3101     status = MediaLibraryKvStoreManager::GetInstance().CloneKvStore(
3102         MEDIA_KVSTORE_YEAR_STOREID, MEDIA_KVDB_DIR, CLONE_KVSTORE_YEAR_STOREID, CLONE_KVDB_BACKUP_DIR);
3103     CHECK_AND_RETURN_RET(status == E_OK, false);
3104     MEDIA_INFO_LOG("End BackupKvstore");
3105     return true;
3106 }
3107 
BatchUpdateFileInfoData(std::vector<FileInfo> & fileInfos,unordered_map<string,CloudPhotoFileExistFlag> & resultExistMap)3108 void CloneRestore::BatchUpdateFileInfoData(std::vector<FileInfo> &fileInfos,
3109     unordered_map<string, CloudPhotoFileExistFlag> &resultExistMap)
3110 {
3111     for (size_t i = 0; i < fileInfos.size(); i++) {
3112         CHECK_AND_CONTINUE(fileInfos[i].needMove);
3113         CloudPhotoFileExistFlag fileExistFlag;
3114         unordered_map<string, CloudPhotoFileExistFlag>::iterator iter =
3115             resultExistMap.find(fileInfos[i].cloudPath);
3116         CHECK_AND_CONTINUE(iter != resultExistMap.end());
3117         fileExistFlag = iter->second;
3118         int32_t thumbReady = CheckThumbReady(fileInfos[i], fileExistFlag);
3119         int32_t thumbStatus = CheckThumbStatus(fileInfos[i], fileExistFlag);
3120         int32_t lcdVisitTime = CheckLcdVisitTime(fileExistFlag);
3121 
3122         std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
3123             std::make_unique<NativeRdb::AbsRdbPredicates>(PhotoColumn::PHOTOS_TABLE);
3124         std::string whereClause = "data = '" + fileInfos[i].cloudPath + "'";
3125         predicates->SetWhereClause(whereClause);
3126 
3127         int32_t updatedRows = 0;
3128         NativeRdb::ValuesBucket updateBucket;
3129         updateBucket.PutInt(PhotoColumn::PHOTO_THUMB_STATUS, thumbStatus);
3130         updateBucket.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY,
3131             thumbReady == 0 ? 0 : fileInfos[i].thumbnailReady);
3132         updateBucket.PutInt(PhotoColumn::PHOTO_LCD_VISIT_TIME, lcdVisitTime);
3133         updateBucket.PutInt(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE,
3134             thumbReady == 0 ? 0 : RESTORE_THUMBNAIL_VISIBLE_TRUE);
3135 
3136         int32_t ret = BackupDatabaseUtils::Update(mediaLibraryRdb_, updatedRows, updateBucket, predicates);
3137         bool cond = (updatedRows < 0 || ret < 0);
3138         CHECK_AND_PRINT_LOG(!cond, "BatchInsertFileInfoData Failed to update column: %s",
3139             fileInfos[i].cloudPath.c_str());
3140         MediaLibraryPhotoOperations::StoreThumbnailSize(to_string(fileInfos[i].fileIdNew),
3141             fileInfos[i].cloudPath);
3142     }
3143 }
3144 
CheckThumbReady(const FileInfo & fileInfo,const CloudPhotoFileExistFlag & cloudPhotoFileExistFlag)3145 int32_t CloneRestore::CheckThumbReady(const FileInfo &fileInfo,
3146     const CloudPhotoFileExistFlag &cloudPhotoFileExistFlag)
3147 {
3148     bool cond = (cloudPhotoFileExistFlag.isThmExist &&
3149             cloudPhotoFileExistFlag.isDayAstcExist &&
3150             cloudPhotoFileExistFlag.isYearAstcExist);
3151     CHECK_AND_RETURN_RET(!cond, RESTORE_THUMBNAIL_READY_ALL_SUCCESS);
3152     return RESTORE_THUMBNAIL_READY_FAIL;
3153 }
3154 
CheckThumbStatus(const FileInfo & fileInfo,const CloudPhotoFileExistFlag & cloudPhotoFileExistFlag)3155 int32_t CloneRestore::CheckThumbStatus(const FileInfo &fileInfo,
3156     const CloudPhotoFileExistFlag &cloudPhotoFileExistFlag)
3157 {
3158     if (!HasExThumbnail(fileInfo)) {
3159         if (cloudPhotoFileExistFlag.isThmExist &&
3160             cloudPhotoFileExistFlag.isLcdExist) {
3161                 return RESTORE_THUMBNAIL_STATUS_ALL;
3162         } else if (cloudPhotoFileExistFlag.isThmExist &&
3163             !cloudPhotoFileExistFlag.isLcdExist) {
3164                 return RESTORE_THUMBNAIL_STATUS_NOT_LCD;
3165         } else if (!cloudPhotoFileExistFlag.isThmExist &&
3166             cloudPhotoFileExistFlag.isLcdExist) {
3167                 return RESTORE_THUMBNAIL_STATUS_NOT_THUMB;
3168         } else {
3169             return RESTORE_THUMBNAIL_STATUS_NOT_ALL;
3170         }
3171     }
3172     if (cloudPhotoFileExistFlag.isExThmExist &&
3173         cloudPhotoFileExistFlag.isExLcdExist) {
3174             return RESTORE_THUMBNAIL_STATUS_ALL;
3175     } else if (cloudPhotoFileExistFlag.isExThmExist &&
3176         !cloudPhotoFileExistFlag.isExLcdExist) {
3177             return RESTORE_THUMBNAIL_STATUS_NOT_LCD;
3178     } else if (!cloudPhotoFileExistFlag.isExThmExist &&
3179         cloudPhotoFileExistFlag.isExLcdExist) {
3180             return RESTORE_THUMBNAIL_STATUS_NOT_THUMB;
3181     }
3182     return RESTORE_THUMBNAIL_STATUS_NOT_ALL;
3183 }
3184 
CheckLcdVisitTime(const CloudPhotoFileExistFlag & cloudPhotoFileExistFlag)3185 int32_t CloneRestore::CheckLcdVisitTime(const CloudPhotoFileExistFlag &cloudPhotoFileExistFlag)
3186 {
3187     CHECK_AND_RETURN_RET(!cloudPhotoFileExistFlag.isLcdExist, RESTORE_LCD_VISIT_TIME_SUCCESS);
3188     return RESTORE_LCD_VISIT_TIME_NO_LCD;
3189 }
3190 
3191 
GetNoNeedMigrateCount()3192 int32_t CloneRestore::GetNoNeedMigrateCount()
3193 {
3194     return this->photosClone_.GetNoNeedMigrateCount();
3195 }
3196 
RestoreAnalysisClassify()3197 void CloneRestore::RestoreAnalysisClassify()
3198 {
3199     CloneRestoreClassify cloneRestoreClassify;
3200     cloneRestoreClassify.Init(sceneCode_, taskId_, mediaLibraryRdb_, mediaRdb_);
3201     cloneRestoreClassify.Restore(photoInfoMap_);
3202 }
3203 
RestoreAnalysisGeo()3204 void CloneRestore::RestoreAnalysisGeo()
3205 {
3206     CloneRestoreGeo cloneRestoreGeo;
3207     cloneRestoreGeo.Init(sceneCode_, taskId_, mediaLibraryRdb_, mediaRdb_);
3208     cloneRestoreGeo.Restore(photoInfoMap_);
3209 }
3210 
UpdatePhotoAlbumCoverUri(vector<AlbumCoverInfo> & albumCoverInfos)3211 void CloneRestore::UpdatePhotoAlbumCoverUri(vector<AlbumCoverInfo>& albumCoverInfos)
3212 {
3213     for (auto& albumCoverInfo : albumCoverInfos) {
3214         int32_t changeRows = 0;
3215         std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
3216             make_unique<NativeRdb::AbsRdbPredicates>(PhotoAlbumColumns::TABLE);
3217         predicates->EqualTo(PhotoAlbumColumns::ALBUM_ID, albumCoverInfo.albumId);
3218         NativeRdb::ValuesBucket updateBucket;
3219         updateBucket.PutInt(PhotoAlbumColumns::COVER_URI_SOURCE, albumCoverInfo.coverUriSource);
3220         updateBucket.PutString(PhotoAlbumColumns::ALBUM_COVER_URI, albumCoverInfo.coverUri);
3221         updateBucket.PutString(PhotoAlbumColumns::COVER_CLOUD_ID, albumCoverInfo.coverCloudId);
3222         BackupDatabaseUtils::Update(mediaLibraryRdb_, changeRows, updateBucket, predicates);
3223         if (changeRows != 1) {
3224             MEDIA_ERR_LOG("UpdatePhotoAlbumCoverUri failed, expected count 1, but got %{public}d", changeRows);
3225         }
3226     }
3227 }
3228 
UpdateExistNewAddColumnSet(const std::unordered_map<string,string> & srcColumnInfoMap)3229 void CloneRestore::UpdateExistNewAddColumnSet(const std::unordered_map<string, string> &srcColumnInfoMap)
3230 {
3231     CHECK_AND_EXECUTE(srcColumnInfoMap.find(PhotoColumn::PHOTO_EXIF_ROTATE) == srcColumnInfoMap.end(),
3232         existNewAddColumnSet_.emplace(PhotoColumn::PHOTO_EXIF_ROTATE));
3233 }
3234 
GetOrientationAndExifRotateValue(const shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & fileInfo)3235 void CloneRestore::GetOrientationAndExifRotateValue(const shared_ptr<NativeRdb::ResultSet> &resultSet,
3236     FileInfo &fileInfo)
3237 {
3238     fileInfo.orientation = GetInt32Val(PhotoColumn::PHOTO_ORIENTATION, resultSet);
3239     if (existNewAddColumnSet_.count(PhotoColumn::PHOTO_EXIF_ROTATE) != 0) {
3240         fileInfo.exifRotate = GetInt32Val(PhotoColumn::PHOTO_EXIF_ROTATE, resultSet);
3241     } else if (fileInfo.orientation == 0 || fileInfo.fileType != MediaType::MEDIA_TYPE_IMAGE) {
3242         fileInfo.exifRotate = 0;
3243     } else {
3244         ExifRotateUtils::ConvertOrientationToExifRotate(fileInfo.orientation, fileInfo.exifRotate);
3245     }
3246 }
3247 
HasExThumbnail(const FileInfo & info)3248 bool CloneRestore::HasExThumbnail(const FileInfo &info)
3249 {
3250     CHECK_AND_RETURN_RET(info.position == static_cast<int32_t>(PhotoPositionType::LOCAL) ||
3251         info.position == static_cast<int32_t>(PhotoPositionType::LOCAL_AND_CLOUD),
3252         BackupFileUtils::HasOrientationOrExifRotate(info));
3253     return info.fileType == MediaType::MEDIA_TYPE_IMAGE && BackupFileUtils::HasOrientationOrExifRotate(info);
3254 }
3255 
BackupRelease()3256 void CloneRestore::BackupRelease()
3257 {
3258     StopParameterForBackup();
3259 }
3260 } // namespace Media
3261 } // namespace OHOS
3262