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