• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define MLOG_TAG "MediaLibraryUpgradeRestore"
17 
18 #include "upgrade_restore.h"
19 
20 #include "backup_const_column.h"
21 #include "backup_const_map.h"
22 #include "backup_database_utils.h"
23 #include "backup_file_utils.h"
24 #include "backup_log_utils.h"
25 #include "database_report.h"
26 #include "cloud_sync_helper.h"
27 #include "exif_rotate_utils.h"
28 #include "gallery_db_upgrade.h"
29 #include "media_column.h"
30 #include "media_file_utils.h"
31 #include "media_log.h"
32 #include "medialibrary_data_manager.h"
33 #include "medialibrary_errno.h"
34 #include "medialibrary_rdb_transaction.h"
35 #include "photo_album_restore.h"
36 #include "photos_dao.h"
37 #include "photos_restore.h"
38 #include "result_set_utils.h"
39 #include "upgrade_restore_task_report.h"
40 #include "userfile_manager_types.h"
41 #include "vision_album_column.h"
42 #include "vision_column.h"
43 #include "vision_face_tag_column.h"
44 #include "vision_image_face_column.h"
45 #include "vision_photo_map_column.h"
46 
47 #ifdef CLOUD_SYNC_MANAGER
48 #include "cloud_sync_manager.h"
49 #endif
50 
51 namespace OHOS {
52 namespace Media {
53 constexpr int32_t PHOTOS_TABLE_ALBUM_ID = -1;
54 constexpr int32_t BASE_TEN_NUMBER = 10;
55 constexpr int32_t SEVEN_NUMBER = 7;
56 constexpr int32_t RESTORE_CLOUD_QUERY_COUNT = 200;
57 const std::string DB_INTEGRITY_CHECK = "ok";
58 const int32_t IMAGE_ALBUM_ID = 7;
59 const int32_t VIDEO_ALBUM_ID = 2;
60 const int32_t FAVORITE_ALBUM_ID = 1;
61 const int32_t CLOUD_ENHANCEMENT_ALBUM_ID = 8;
62 const std::string LPATH_SCREEN_SHOTS = "/Pictures/Screenshots";
63 const std::string LPATH_SCREEN_RECORDS = "/Pictures/Screenrecords";
64 
UpgradeRestore(const std::string & galleryAppName,const std::string & mediaAppName,int32_t sceneCode)65 UpgradeRestore::UpgradeRestore(const std::string &galleryAppName, const std::string &mediaAppName, int32_t sceneCode)
66 {
67     galleryAppName_ = galleryAppName;
68     mediaAppName_ = mediaAppName;
69     sceneCode_ = sceneCode;
70     audioAppName_ = "Audio";
71     ffrt_disable_worker_escape();
72     MEDIA_INFO_LOG("Set ffrt_disable_worker_escape");
73 }
74 
UpgradeRestore(const std::string & galleryAppName,const std::string & mediaAppName,int32_t sceneCode,const std::string & dualDirName)75 UpgradeRestore::UpgradeRestore(const std::string &galleryAppName, const std::string &mediaAppName, int32_t sceneCode,
76     const std::string &dualDirName)
77 {
78     galleryAppName_ = galleryAppName;
79     mediaAppName_ = mediaAppName;
80     sceneCode_ = sceneCode;
81     dualDirName_ = dualDirName;
82     ffrt_disable_worker_escape();
83     MEDIA_INFO_LOG("Set ffrt_disable_worker_escape");
84 }
85 
Init(const std::string & backupRetoreDir,const std::string & upgradeFilePath,bool isUpgrade)86 int32_t UpgradeRestore::Init(const std::string &backupRetoreDir, const std::string &upgradeFilePath, bool isUpgrade)
87 {
88     appDataPath_ = backupRetoreDir;
89     string photosPreferencesPath;
90     if (sceneCode_ == DUAL_FRAME_CLONE_RESTORE_ID) {
91         filePath_ = backupRetoreDir;
92         galleryDbPath_ = backupRetoreDir + "/" + GALLERY_DB_NAME;
93         audioDbPath_ = backupRetoreDir + INTERNAL_PREFIX + "/0/" + AUDIO_DB_NAME;
94         photosPreferencesPath = backupRetoreDir + "/" + galleryAppName_ + "_preferences.xml";
95         // gallery db may include both internal & external, set flag to differentiate, default false
96         shouldIncludeSd_ = BackupFileUtils::ShouldIncludeSd(filePath_);
97         backupDatabaseHelper_.Init(sceneCode_, shouldIncludeSd_, filePath_);
98         SetCloneParameterAndStopSync();
99     } else {
100         filePath_ = upgradeFilePath;
101         galleryDbPath_ = backupRetoreDir + "/" + galleryAppName_ + "/ce/databases/gallery.db";
102         externalDbPath_ = backupRetoreDir + "/" + mediaAppName_ + "/ce/databases/external.db";
103         photosPreferencesPath =
104             backupRetoreDir + "/" + galleryAppName_ + "/ce/shared_prefs/" + galleryAppName_ + "_preferences.xml";
105         shouldIncludeSd_ = false;
106         if (!MediaFileUtils::IsFileExists(externalDbPath_)) {
107             ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "", "External db is not exist.");
108             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
109             MEDIA_ERR_LOG("External db is not exist.");
110             return EXTERNAL_DB_NOT_EXIST;
111         }
112         int32_t externalErr = BackupDatabaseUtils::InitDb(externalRdb_, EXTERNAL_DB_NAME, externalDbPath_,
113             mediaAppName_, false);
114         if (externalRdb_ == nullptr) {
115             ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "",
116                 "External init rdb fail, err = " + std::to_string(externalErr));
117             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
118             MEDIA_ERR_LOG("External init rdb fail, err = %{public}d", externalErr);
119             return E_FAIL;
120         }
121         backupDatabaseHelper_.AddDb(BackupDatabaseHelper::DbType::EXTERNAL, externalRdb_);
122     }
123     MEDIA_INFO_LOG("Shoud include Sd: %{public}d", static_cast<int32_t>(shouldIncludeSd_));
124     return InitDbAndXml(photosPreferencesPath, isUpgrade);
125 }
126 
InitDbAndXml(std::string xmlPath,bool isUpgrade)127 int32_t UpgradeRestore::InitDbAndXml(std::string xmlPath, bool isUpgrade)
128 {
129     int32_t errCode = InitDb(isUpgrade);
130     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
131 
132     ParseXml(xmlPath);
133     this->photoAlbumRestore_.OnStart(this->mediaLibraryRdb_, this->galleryRdb_);
134     this->photosRestore_.OnStart(this->mediaLibraryRdb_, this->galleryRdb_);
135     geoKnowledgeRestore_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->galleryRdb_);
136     highlightRestore_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->galleryRdb_);
137     MEDIA_INFO_LOG("Init db succ.");
138     return E_OK;
139 }
140 
HasLowQualityImage()141 bool UpgradeRestore::HasLowQualityImage()
142 {
143     std::string sql = "SELECT count(1) AS count FROM gallery_media WHERE (local_media_id != -1) AND \
144         (COALESCE(storage_id, 0) IN (0, 65537)) AND relative_bucket_id NOT IN (SELECT DISTINCT relative_bucket_id FROM \
145         garbage_album WHERE type = 1) AND _size = 0 AND photo_quality = 0";
146     int count = BackupDatabaseUtils::QueryInt(galleryRdb_, sql, CUSTOM_COUNT);
147     MEDIA_INFO_LOG("HasLowQualityImage count:%{public}d", count);
148     hasLowQualityImage_ = (count > 0);
149     return hasLowQualityImage_;
150 }
151 
StringToInt(const std::string & str)152 int UpgradeRestore::StringToInt(const std::string& str)
153 {
154     if (str.empty()) {
155         return 0;
156     }
157     int base = 0;
158     size_t num = 0;
159     int sign = 1;
160     size_t len = static_cast<ssize_t>(str.length());
161     while (num < len && str[num] == ' ') {
162         num++;
163     }
164     if (num < len && (str[num] == '-' || str[num] == '+')) {
165         sign = (str[num++] == '-') ? -1 : 1;
166     }
167     while (num < len && std::isdigit(str[num])) {
168         if (base > INT_MAX / BASE_TEN_NUMBER || (base == INT_MAX / BASE_TEN_NUMBER && str[num] - '0' > SEVEN_NUMBER)) {
169             MEDIA_INFO_LOG("The number is INT_MAX");
170             return 0;
171         }
172         base = BASE_TEN_NUMBER * base + (str[num++] - '0');
173     }
174     if (num < len && !std::isdigit(str[num])) {
175         MEDIA_INFO_LOG("Not digit");
176         return 0;
177     }
178     return base * sign;
179 }
180 
HandleXmlNode(xmlNodePtr cur)181 int32_t UpgradeRestore::HandleXmlNode(xmlNodePtr cur)
182 {
183     if (cur->type == XML_ELEMENT_NODE) {
184         xmlChar* name = xmlGetProp(cur, BAD_CAST"name");
185         if (name != nullptr && xmlStrcmp(name, BAD_CAST"filter_selected_size") == 0) {
186             xmlChar* value = xmlGetProp(cur, BAD_CAST"value");
187             if (value != nullptr) {
188                 fileMinSize_ = StringToInt((const char *)(value));
189                 xmlFree(value);
190                 xmlFree(name);
191                 return E_SUCCESS;
192             }
193             xmlFree(name);
194             return E_ERR;
195         }
196         if (name != nullptr) {
197             xmlFree(name);
198         }
199     }
200     return E_ERR;
201 }
202 
ParseXml(string path)203 int32_t UpgradeRestore::ParseXml(string path)
204 {
205     std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
206         xmlReadFile(path.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
207     if (docPtr == nullptr) {
208         MEDIA_ERR_LOG("failed to read xml file");
209         return E_ERR;
210     }
211     auto root = xmlDocGetRootElement(docPtr.get());
212     if (root == nullptr) {
213         MEDIA_ERR_LOG("failed to read root node");
214         return E_ERR;
215     }
216     for (xmlNodePtr cur = root->children; cur != NULL; cur = cur->next) {
217         if (HandleXmlNode(cur) == E_SUCCESS) {
218             return E_SUCCESS;
219         }
220     }
221     return E_ERR;
222 }
223 
RestoreAudio(void)224 void UpgradeRestore::RestoreAudio(void)
225 {
226     int64_t startRestoreAudio = MediaFileUtils::UTCTimeMilliSeconds();
227     if (sceneCode_ == DUAL_FRAME_CLONE_RESTORE_ID) {
228         if (!MediaFileUtils::IsFileExists(RESTORE_MUSIC_LOCAL_DIR)) {
229             MEDIA_INFO_LOG("music dir is not exists!!!");
230             MediaFileUtils::CreateDirectory(RESTORE_MUSIC_LOCAL_DIR);
231         }
232         RestoreAudioFromFile();
233     }
234     (void)NativeRdb::RdbHelper::DeleteRdbStore(audioDbPath_);
235 
236     int32_t restoreMode = BaseRestore::GetRestoreMode();
237     if (restoreMode == RESTORE_MODE_PROC_ALL_DATA || restoreMode == RESTORE_MODE_PROC_TWIN_DATA) {
238         (void)NativeRdb::RdbHelper::DeleteRdbStore(externalDbPath_);
239     } else {
240         MEDIA_INFO_LOG("restore mode no need to del external db");
241     }
242     int64_t endRestoreAudio = MediaFileUtils::UTCTimeMilliSeconds();
243     MEDIA_INFO_LOG("TimeCost: RestoreAudio cost: %{public}" PRId64, endRestoreAudio - startRestoreAudio);
244 }
245 
RestoreAudioFromFile()246 void UpgradeRestore::RestoreAudioFromFile()
247 {
248     MEDIA_INFO_LOG("start restore audio from audio_MediaInfo0");
249     int32_t totalNumber = BackupDatabaseUtils::QueryInt(audioRdb_, QUERY_DUAL_CLONE_AUDIO_COUNT, CUSTOM_COUNT);
250     MEDIA_INFO_LOG("totalNumber = %{public}d", totalNumber);
251     audioTotalNumber_ += static_cast<uint64_t>(totalNumber);
252     MEDIA_INFO_LOG("onProcess Update audioTotalNumber_: %{public}lld", (long long)audioTotalNumber_);
253     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
254         ffrt::submit([this, offset]() { RestoreAudioBatch(offset); }, { &offset }, {},
255             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
256     }
257     ffrt::wait();
258 }
259 
RestoreAudioBatch(int32_t offset)260 void UpgradeRestore::RestoreAudioBatch(int32_t offset)
261 {
262     MEDIA_INFO_LOG("start restore audio from external, offset: %{public}d", offset);
263     std::vector<FileInfo> infos = QueryAudioFileInfosFromAudio(offset);
264     InsertAudio(sceneCode_, infos);
265 }
266 
QueryAudioFileInfosFromAudio(int32_t offset)267 std::vector<FileInfo> UpgradeRestore::QueryAudioFileInfosFromAudio(int32_t offset)
268 {
269     std::vector<FileInfo> result;
270     result.reserve(QUERY_COUNT);
271     if (audioRdb_ == nullptr) {
272         MEDIA_ERR_LOG("audioRdb_ is nullptr, Maybe init failed.");
273         return result;
274     }
275     std::string queryAllAudioByCount = QUERY_ALL_AUDIOS_FROM_AUDIODB + " limit " + std::to_string(offset) + ", " +
276         std::to_string(QUERY_COUNT);
277     auto resultSet = audioRdb_->QuerySql(queryAllAudioByCount);
278     if (resultSet == nullptr) {
279         MEDIA_ERR_LOG("Query resultSql is null.");
280         return result;
281     }
282     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
283         FileInfo tmpInfo;
284         if (ParseResultSetFromAudioDb(resultSet, tmpInfo)) {
285             result.emplace_back(tmpInfo);
286         }
287     }
288     resultSet->Close();
289     return result;
290 }
291 
ParseResultSetFromAudioDb(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)292 bool UpgradeRestore::ParseResultSetFromAudioDb(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
293 {
294     info.fileType = MediaType::MEDIA_TYPE_AUDIO;
295     info.oldPath = GetStringVal(AUDIO_DATA, resultSet);
296     if (!ConvertPathToRealPath(info.oldPath, filePath_, info.filePath, info.relativePath)) {
297         MEDIA_ERR_LOG("Invalid path: %{public}s.",
298             BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
299         return false;
300     }
301     info.showDateToken = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet);
302     info.dateModified = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet) * MSEC_TO_SEC;
303     info.displayName = BackupFileUtils::GetFileNameFromPath(info.filePath);
304     info.title = BackupFileUtils::GetFileTitle(info.displayName);
305     info.packageName = BackupFileUtils::GetFileFolderFromPath(info.relativePath, false);
306     info.isFavorite = 0;
307     info.recycledTime = 0;
308     return true;
309 }
310 
GetHighlightCloudMediaCnt()311 int32_t UpgradeRestore::GetHighlightCloudMediaCnt()
312 {
313     const std::string QUERY_SQL = "SELECT COUNT(1) AS count FROM t_story_album t1 "
314         "WHERE COALESCE(t1.name, '') <> '' AND t1.displayable = 1 "
315         "AND EXISTS "
316         "(SELECT t2._id FROM gallery_media t2 WHERE t2.local_media_id = -1 "
317         "AND t2.story_chosen = 1 "
318         "AND (t2.story_id LIKE '%,'||t1.story_id||',%' OR t2.portrait_id LIKE '%,'||t1.story_id||',%'))";
319     std::shared_ptr<NativeRdb::ResultSet> resultSet =
320         BackupDatabaseUtils::QuerySql(this->galleryRdb_, QUERY_SQL, {});
321     if (resultSet == nullptr) {
322         MEDIA_ERR_LOG("query count of highlight cloud media failed.");
323         return -1;
324     }
325     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
326         resultSet->Close();
327         return -1;
328     }
329     int32_t cnt = GetInt32Val("count", resultSet);
330     MEDIA_INFO_LOG("GetHighlightCloudMediaCnt is %{public}d", cnt);
331     resultSet->Close();
332     return cnt;
333 }
334 
RestoreSmartAlbums()335 void UpgradeRestore::RestoreSmartAlbums()
336 {
337     CHECK_AND_RETURN(sceneCode_ == UPGRADE_RESTORE_ID || sceneCode_ == DUAL_FRAME_CLONE_RESTORE_ID);
338     MEDIA_INFO_LOG("RestoreSmartAlbums start");
339     int64_t startRestoreGeo = MediaFileUtils::UTCTimeMilliSeconds();
340     geoKnowledgeRestore_.RestoreGeo(photoInfoMap_);
341     int64_t startRestoreHighlight = MediaFileUtils::UTCTimeMilliSeconds();
342     RestoreHighlightAlbums();
343     int64_t endRestoreHighlight = MediaFileUtils::UTCTimeMilliSeconds();
344     MEDIA_INFO_LOG("TimeCost: RestoreGeo cost: %{public}" PRId64 ", RestoreHighlight cost: %{public}" PRId64,
345         startRestoreHighlight - startRestoreGeo, endRestoreHighlight - startRestoreHighlight);
346     MEDIA_INFO_LOG("RestoreSmartAlbums end");
347 }
348 
RestoreHighlightAlbums()349 void UpgradeRestore::RestoreHighlightAlbums()
350 {
351     int32_t highlightCloudMediaCnt = GetHighlightCloudMediaCnt();
352     UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
353         .Report("Highlight Restore", "",
354         "sceneCode_: " + std::to_string(sceneCode_) +
355         ", dualDeviceSoftName_: " + dualDeviceSoftName_ +
356         ", highlightCloudMediaCnt: " + std::to_string(highlightCloudMediaCnt) +
357         ", isAccountValid_: " + std::to_string(isAccountValid_) +
358         ", syncSwitchType_: " + std::to_string(syncSwitchType_) +
359         ", isSyncSwitchOpen: " + std::to_string(isSyncSwitchOn_));
360     if ((sceneCode_ == UPGRADE_RESTORE_ID || dualDeviceSoftName_.empty()
361         || dualDeviceSoftName_.find("4", dualDeviceSoftName_.find(" ")) == dualDeviceSoftName_.find(" ") + 1)
362         && (highlightCloudMediaCnt == 0 || IsCloudRestoreSatisfied())) {
363         MEDIA_INFO_LOG("start to restore highlight albums");
364         highlightRestore_.RestoreHighlight(albumOdid_, photoInfoMap_);
365     }
366 }
367 
RestorePhotoInner()368 void UpgradeRestore::RestorePhotoInner()
369 {
370     std::string dbIntegrityCheck = CheckGalleryDbIntegrity();
371     if (dbIntegrityCheck == DB_INTEGRITY_CHECK) {
372         MEDIA_INFO_LOG("the isAccountValid is %{public}d, sync switch open is %{public}d", isAccountValid_,
373             isSyncSwitchOn_);
374         // upgrade gallery.db
375         int64_t startGalleryDbUpgrade = MediaFileUtils::UTCTimeMilliSeconds();
376         DataTransfer::GalleryDbUpgrade().OnUpgrade(this->galleryRdb_);
377         int64_t startAnalyzeGallerySource = MediaFileUtils::UTCTimeMilliSeconds();
378         AnalyzeGallerySource();
379         InitGarbageAlbum();
380         int64_t startAlbumRestore = MediaFileUtils::UTCTimeMilliSeconds();
381         // restore PhotoAlbum
382         this->photoAlbumRestore_.Restore();
383         int64_t startRestorePortrait = MediaFileUtils::UTCTimeMilliSeconds();
384         RestoreAnalysisAlbum();
385         int64_t endRestoreAlbums = MediaFileUtils::UTCTimeMilliSeconds();
386         MEDIA_INFO_LOG("TimeCost: GalleryDbUpgrade cost: %{public}" PRId64
387             ", AnalyzeGallerySource cost: %{public}" PRId64
388             ", photoAlbumRestore cost: %{public}" PRId64 ", RestorePortrait cost: %{public}" PRId64,
389             startAnalyzeGallerySource - startGalleryDbUpgrade, startAlbumRestore - startAnalyzeGallerySource,
390             startRestorePortrait - startAlbumRestore, endRestoreAlbums - startRestorePortrait);
391         // restore Photos
392         RestoreFromGallery();
393         if (IsCloudRestoreSatisfied()) {
394             MEDIA_INFO_LOG("here cloud clone");
395             RestoreCloudFromGallery();
396             MEDIA_INFO_LOG("Migrate LCD:%{public}" PRIu64 ",THM:%{public}" PRIu64
397             ",Rotate LCD:%{public}" PRIu64 ",THM: %{public}" PRIu64 ", migrateCloud: %{public}" PRIu64
398             ", migrateDatabase: %{public}" PRIu64,
399             (cloudLcdCount_.load(std::memory_order_relaxed) + localLcdCount_.load(std::memory_order_relaxed)),
400             (cloudThumbnailCount_.load(std::memory_order_relaxed) +
401             localThumbnailCount_.load(std::memory_order_relaxed)),
402             rotateLcdMigrateFileNumber_.load(), rotateThmMigrateFileNumber_.load(),
403             totalCloudMetaNumber_.load(), migrateDatabaseNumber_.load());
404         }
405         InheritManualCover();
406     } else {
407         maxId_ = 0;
408         SetErrorCode(RestoreError::GALLERY_DATABASE_CORRUPTION);
409         ErrorInfo errorInfo(RestoreError::GALLERY_DATABASE_CORRUPTION, 0, "", dbIntegrityCheck);
410         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
411     }
412 }
413 
RestorePhoto()414 void UpgradeRestore::RestorePhoto()
415 {
416     CHECK_AND_RETURN(IsRestorePhoto());
417     AnalyzeSource();
418     RestorePhotoInner();
419     MEDIA_INFO_LOG("migrate from gallery number: %{public}lld, file number: %{public}lld",
420         (long long) migrateDatabaseNumber_, (long long) migrateFileNumber_);
421     if (sceneCode_ == UPGRADE_RESTORE_ID) {
422         RestoreFromExternal(true);
423         MEDIA_INFO_LOG("migrate from camera number: %{public}lld, file number: %{public}lld",
424             (long long) migrateDatabaseNumber_, (long long) migrateFileNumber_);
425         RestoreFromExternal(false);
426         MEDIA_INFO_LOG("migrate from others number: %{public}lld, file number: %{public}lld",
427             (long long) migrateDatabaseNumber_, (long long) migrateFileNumber_);
428     }
429 
430     if (sceneCode_ == UPGRADE_RESTORE_ID) {
431         int64_t startUpdateFace = MediaFileUtils::UTCTimeMilliSeconds();
432         UpdateFaceAnalysisStatus();
433         int64_t endUpdateFace = MediaFileUtils::UTCTimeMilliSeconds();
434         MEDIA_INFO_LOG("TimeCost: UpdateFaceAnalysisStatus cost: %{public}" PRId64, endUpdateFace - startUpdateFace);
435     } else {
436         int64_t startUpdateDual = MediaFileUtils::UTCTimeMilliSeconds();
437         UpdateDualCloneFaceAnalysisStatus();
438         int64_t endUpdateDual = MediaFileUtils::UTCTimeMilliSeconds();
439         MEDIA_INFO_LOG("TimeCost: UpdateDualCloneFaceAnalysisStatus cost: %{public}" PRId64,
440             endUpdateDual - startUpdateDual);
441     }
442     RestoreSmartAlbums();
443     ReportPortraitStat(sceneCode_);
444 
445     int32_t restoreMode = BaseRestore::GetRestoreMode();
446     UpgradeRestoreTaskReport()
447         .SetSceneCode(sceneCode_)
448         .SetTaskId(taskId_)
449         .ReportRestoreMode(restoreMode, BaseRestore::GetNotFoundNumber());
450     if (restoreMode == RESTORE_MODE_PROC_ALL_DATA || restoreMode == RESTORE_MODE_PROC_TWIN_DATA) {
451         (void)NativeRdb::RdbHelper::DeleteRdbStore(galleryDbPath_);
452     } else {
453         MEDIA_INFO_LOG("restore mode no need to del gallery db");
454     }
455     ProcessBurstPhotos();
456     StopParameterForRestore();
457     StopParameterForClone();
458 }
459 
AnalyzeSource()460 void UpgradeRestore::AnalyzeSource()
461 {
462     MEDIA_INFO_LOG("start AnalyzeSource.");
463     DatabaseReport()
464         .SetSceneCode(this->sceneCode_)
465         .SetTaskId(this->taskId_)
466         .ReportExternal(this->externalRdb_,  this->galleryRdb_)
467         .ReportMedia(this->mediaLibraryRdb_, DatabaseReport::PERIOD_BEFORE);
468     MEDIA_INFO_LOG("end AnalyzeSource.");
469 }
470 
AnalyzeGalleryErrorSource()471 void UpgradeRestore::AnalyzeGalleryErrorSource()
472 {
473     if (galleryRdb_ == nullptr) {
474         MEDIA_ERR_LOG("galleryRdb_ is nullptr, Maybe init failed.");
475         return;
476     }
477     AnalyzeGalleryDuplicateData();
478 }
479 
AnalyzeGalleryDuplicateData()480 void UpgradeRestore::AnalyzeGalleryDuplicateData()
481 {
482     int32_t count = 0;
483     int32_t total = 0;
484     BackupDatabaseUtils::QueryGalleryDuplicateDataCount(galleryRdb_, count, total);
485     MEDIA_INFO_LOG("Duplicate data count: %{public}d, total: %{public}d", count, total);
486     this->photosRestore_.GetDuplicateData(count);
487 }
488 
AnalyzeGallerySource()489 void UpgradeRestore::AnalyzeGallerySource()
490 {
491     MEDIA_INFO_LOG("start AnalyzeGallerySource.");
492     AnalyzeGalleryErrorSource();
493     DatabaseReport()
494         .SetSceneCode(this->sceneCode_)
495         .SetTaskId(this->taskId_)
496         .ReportGallery(this->galleryRdb_, this->shouldIncludeSd_);
497     MEDIA_INFO_LOG("end AnalyzeGallerySource.");
498 }
499 
InitGarbageAlbum()500 void UpgradeRestore::InitGarbageAlbum()
501 {
502     BackupDatabaseUtils::InitGarbageAlbum(galleryRdb_, cacheSet_, nickMap_);
503 }
504 
AddToGalleryFailedOffsets(int32_t offset)505 void UpgradeRestore::AddToGalleryFailedOffsets(int32_t offset)
506 {
507     std::lock_guard<ffrt::mutex> lock(galleryFailedMutex_);
508     galleryFailedOffsets_.push_back(offset);
509 }
510 
ProcessGalleryFailedOffsets()511 void UpgradeRestore::ProcessGalleryFailedOffsets()
512 {
513     std::lock_guard<ffrt::mutex> lock(galleryFailedMutex_);
514     size_t vectorLen = galleryFailedOffsets_.size();
515     needReportFailed_ = true;
516     for (auto minId : galleryFailedOffsets_) {
517         RestoreBatch(minId);
518     }
519     galleryFailedOffsets_.clear();
520 }
521 
ProcessCloudGalleryFailedOffsets()522 void UpgradeRestore::ProcessCloudGalleryFailedOffsets()
523 {
524     std::lock_guard<ffrt::mutex> lock(galleryFailedMutex_);
525     size_t vectorLen = galleryFailedOffsets_.size();
526     needReportFailed_ = true;
527     for (auto minId : galleryFailedOffsets_) {
528         RestoreBatchForCloud(minId);
529     }
530     galleryFailedOffsets_.clear();
531 }
532 
AddToExternalFailedOffsets(int32_t offset)533 void UpgradeRestore::AddToExternalFailedOffsets(int32_t offset)
534 {
535     std::lock_guard<ffrt::mutex> lock(externalFailedMutex_);
536     externalFailedOffsets_.push_back(offset);
537 }
538 
ProcessExternalFailedOffsets(int32_t maxId,bool isCamera,int32_t type)539 void UpgradeRestore::ProcessExternalFailedOffsets(int32_t maxId, bool isCamera, int32_t type)
540 {
541     std::lock_guard<ffrt::mutex> lock(externalFailedMutex_);
542     size_t vectorLen = externalFailedOffsets_.size();
543     needReportFailed_ = true;
544     for (size_t offset = 0; offset < vectorLen; offset++) {
545         RestoreExternalBatch(externalFailedOffsets_[offset], maxId, isCamera, type);
546     }
547     externalFailedOffsets_.clear();
548 }
549 
RestoreFromGallery()550 void UpgradeRestore::RestoreFromGallery()
551 {
552     MEDIA_INFO_LOG("RestoreFromGallery start");
553     this->photosRestore_.LoadPhotoAlbums();
554     HasLowQualityImage();
555     // local count
556     int32_t totalNumber = this->photosRestore_.GetGalleryMediaCount(this->shouldIncludeSd_, this->hasLowQualityImage_);
557     MEDIA_INFO_LOG("local totalNumber = %{public}d", totalNumber);
558     totalNumber_ += static_cast<uint64_t>(totalNumber);
559     std::vector<int32_t> minIds = GetLocalPhotoMinIds();
560     MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
561     int64_t startRestoreBatch = MediaFileUtils::UTCTimeMilliSeconds();
562     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
563     needReportFailed_ = false;
564     for (auto minId : minIds) {
565         ffrt::submit([this, minId]() { RestoreBatch(minId); }, { &minId }, {},
566             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
567     }
568     ffrt::wait();
569     int64_t endRestoreBatch = MediaFileUtils::UTCTimeMilliSeconds();
570     MEDIA_INFO_LOG("TimeCost: RestoreBatch cost: %{public}" PRId64, endRestoreBatch - startRestoreBatch);
571     ProcessGalleryFailedOffsets();
572     MEDIA_INFO_LOG("RestoreFromGallery end");
573 }
574 
RestoreCloudFromGallery()575 void UpgradeRestore::RestoreCloudFromGallery()
576 {
577     MEDIA_INFO_LOG("RestoreCloudFromGallery start");
578     this->photosRestore_.LoadPhotoAlbums();
579     // cloud count
580     int32_t cloudMetaCount = this->photosRestore_.GetCloudMetaCount(this->shouldIncludeSd_, false);
581     std::vector<int32_t> minIds = GetCloudPhotoMinIds();
582     MEDIA_INFO_LOG("the cloud count is %{public}d", cloudMetaCount);
583     int64_t startRestoreBatch = MediaFileUtils::UTCTimeMilliSeconds();
584     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
585     needReportFailed_ = false;
586     totalNumber_ += static_cast<uint64_t>(cloudMetaCount);
587     for (auto minId : minIds) {
588         ffrt::submit([this, minId]() { RestoreBatchForCloud(minId); }, { &minId }, {},
589             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
590     }
591     ffrt::wait();
592     int64_t endRestoreBatch = MediaFileUtils::UTCTimeMilliSeconds();
593     MEDIA_INFO_LOG("TimeCost: RestoreBatchForCloud cost: %{public}" PRId64, endRestoreBatch - startRestoreBatch);
594     ProcessCloudGalleryFailedOffsets();
595     MEDIA_INFO_LOG("RestoreCloudFromGallery end");
596 }
597 
GetCloudPhotoMinIds()598 std::vector<int32_t> UpgradeRestore::GetCloudPhotoMinIds()
599 {
600     int64_t startGetCloudPhotoMinIds = MediaFileUtils::UTCTimeMilliSeconds();
601     std::vector<int32_t> minIds;
602     std::string querySql = "SELECT _id FROM ("
603         "SELECT _id, ROW_NUMBER() OVER (ORDER BY _id ASC) AS row_num FROM gallery_media "
604             "WHERE (local_media_id == -1) AND COALESCE(uniqueId,'') <> '' "
605             "AND (relative_bucket_id IS NULL OR relative_bucket_id NOT IN ("
606                 "SELECT DISTINCT relative_bucket_id FROM garbage_album WHERE type = 1)) "
607             "AND (_size > 0 OR (1 = ? AND _size = 0 AND photo_quality = 0)) "
608             "AND _data NOT LIKE '/storage/emulated/0/Pictures/cloud/Imports%' "
609             "AND COALESCE(_data, '') <> '' AND (1 = ? OR COALESCE(storage_id, 0) IN (0, 65537))) AS numbered "
610         "WHERE (row_num - 1) % 200 = 0 ;";
611     std::vector<NativeRdb::ValueObject> params = { hasLowQualityImage_, shouldIncludeSd_ };
612     auto resultSet = galleryRdb_->QuerySql(querySql, params);
613     CHECK_AND_RETURN_RET(resultSet != nullptr, minIds);
614     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
615         minIds.emplace_back(GetInt32Val("_id", resultSet));
616     }
617     resultSet->Close();
618     int64_t endGetCloudPhotoMinIds = MediaFileUtils::UTCTimeMilliSeconds();
619     MEDIA_INFO_LOG("TimeCost: GetCloudPhotoMinIds cost: %{public}" PRId64,
620         endGetCloudPhotoMinIds - startGetCloudPhotoMinIds);
621     return minIds;
622 }
623 
GetLocalPhotoMinIds()624 std::vector<int32_t> UpgradeRestore::GetLocalPhotoMinIds()
625 {
626     int64_t startGetLocalPhotoMinIds = MediaFileUtils::UTCTimeMilliSeconds();
627     std::vector<int32_t> minIds;
628     std::string querySql = "SELECT _id FROM ("
629         "SELECT _id, ROW_NUMBER() OVER (ORDER BY _id ASC) AS row_num FROM gallery_media "
630             "WHERE (local_media_id != -1) "
631             "AND (relative_bucket_id IS NULL OR relative_bucket_id NOT IN ("
632                 "SELECT DISTINCT relative_bucket_id FROM garbage_album WHERE type = 1)) "
633             "AND (_size > 0 OR (1 = ? AND _size = 0 AND photo_quality = 0)) "
634             "AND _data NOT LIKE '/storage/emulated/0/Pictures/cloud/Imports%' "
635             "AND COALESCE(_data, '') <> '' AND (1 = ? OR COALESCE(storage_id, 0) IN (0, 65537))) AS numbered "
636         "WHERE (row_num - 1) % 200 = 0 ;";
637     std::vector<NativeRdb::ValueObject> params = { hasLowQualityImage_, shouldIncludeSd_ };
638     auto resultSet = galleryRdb_->QuerySql(querySql, params);
639     CHECK_AND_RETURN_RET(resultSet != nullptr, minIds);
640 
641     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
642         minIds.emplace_back(GetInt32Val("_id", resultSet));
643     }
644     resultSet->Close();
645     int64_t endGetLocalPhotoMinIds = MediaFileUtils::UTCTimeMilliSeconds();
646     MEDIA_INFO_LOG("TimeCost: GetLocalPhotoMinIds cost: %{public}" PRId64,
647         endGetLocalPhotoMinIds - startGetLocalPhotoMinIds);
648     return minIds;
649 }
650 
RestoreBatchForCloud(int32_t minId)651 void UpgradeRestore::RestoreBatchForCloud(int32_t minId)
652 {
653     int64_t startQueryFileInfos = MediaFileUtils::UTCTimeMilliSeconds();
654     std::vector<FileInfo> infos = QueryCloudFileInfos(minId);
655     MEDIA_INFO_LOG("the infos size is %{public}zu", infos.size());
656     int64_t startInsertPhoto = MediaFileUtils::UTCTimeMilliSeconds();
657     CHECK_AND_EXECUTE(InsertCloudPhoto(sceneCode_, infos, SourceType::GALLERY) == E_OK,
658         AddToGalleryFailedOffsets(minId));
659     int64_t startUpdateAnalysisTotal = MediaFileUtils::UTCTimeMilliSeconds();
660     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(infos);
661     BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
662     int64_t endUpdateAnalysisTotal = MediaFileUtils::UTCTimeMilliSeconds();
663     MEDIA_INFO_LOG("TimeCost: cloud QueryFileInfos cost: %{public}" PRId64 ", InsertPhoto cost: %{public}" PRId64
664         ", UpdateAnalysisTotal cost: %{public}" PRId64 ", minId: %{public}d", startInsertPhoto - startQueryFileInfos,
665         startUpdateAnalysisTotal - startInsertPhoto, endUpdateAnalysisTotal - startUpdateAnalysisTotal, minId);
666 }
667 
RestoreBatch(int32_t minId)668 void UpgradeRestore::RestoreBatch(int32_t minId)
669 {
670     MEDIA_INFO_LOG("start restore from gallery, minId: %{public}d", minId);
671     int64_t startQueryFileInfos = MediaFileUtils::UTCTimeMilliSeconds();
672     std::vector<FileInfo> infos = QueryFileInfos(minId);
673     int64_t startInsertPhoto = MediaFileUtils::UTCTimeMilliSeconds();
674     CHECK_AND_EXECUTE(InsertPhoto(sceneCode_, infos, SourceType::GALLERY) == E_OK,
675         AddToGalleryFailedOffsets(minId));
676     int64_t startUpdateAnalysisTotal = MediaFileUtils::UTCTimeMilliSeconds();
677     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(infos);
678     BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
679     int64_t endUpdateAnalysisTotal = MediaFileUtils::UTCTimeMilliSeconds();
680     MEDIA_INFO_LOG("TimeCost: QueryFileInfos cost: %{public}" PRId64 ", InsertPhoto cost: %{public}" PRId64
681         ", UpdateAnalysisTotal cost: %{public}" PRId64 ", minId: %{public}d", startInsertPhoto - startQueryFileInfos,
682         startUpdateAnalysisTotal - startInsertPhoto, endUpdateAnalysisTotal - startUpdateAnalysisTotal, minId);
683 }
684 
RestoreFromExternal(bool isCamera)685 void UpgradeRestore::RestoreFromExternal(bool isCamera)
686 {
687     int64_t startRestoreFromExternal = MediaFileUtils::UTCTimeMilliSeconds();
688     MEDIA_INFO_LOG("start restore from %{public}s", (isCamera ? "camera" : "others"));
689     int32_t maxId = BackupDatabaseUtils::QueryInt(galleryRdb_, isCamera ?
690         QUERY_MAX_ID_CAMERA_SCREENSHOT : QUERY_MAX_ID_OTHERS, CUSTOM_MAX_ID);
691     maxId = (maxId_ == -1) ? maxId : maxId_;
692     int32_t type = isCamera ? SourceType::EXTERNAL_CAMERA : SourceType::EXTERNAL_OTHERS;
693     int32_t totalNumber = QueryNotSyncTotalNumber(maxId, isCamera);
694     MEDIA_INFO_LOG("totalNumber = %{public}d, maxId = %{public}d", totalNumber, maxId);
695     totalNumber_ += static_cast<uint64_t>(totalNumber);
696     MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
697     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
698     needReportFailed_ = false;
699     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
700         ffrt::submit([this, offset, maxId, isCamera, type]() {
701                 RestoreExternalBatch(offset, maxId, isCamera, type);
702             }, { &offset }, {}, ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
703     }
704     ffrt::wait();
705     ProcessExternalFailedOffsets(maxId, isCamera, type);
706     int64_t endstat = MediaFileUtils::UTCTimeMilliSeconds();
707     MEDIA_INFO_LOG("TimeCost: RestoreFromExternal cost: %{public}" PRId64, endstat - startRestoreFromExternal);
708 }
709 
RestoreExternalBatch(int32_t offset,int32_t maxId,bool isCamera,int32_t type)710 void UpgradeRestore::RestoreExternalBatch(int32_t offset, int32_t maxId, bool isCamera, int32_t type)
711 {
712     MEDIA_INFO_LOG("start restore from external, offset: %{public}d", offset);
713     std::vector<FileInfo> infos = QueryFileInfosFromExternal(offset, maxId, isCamera);
714     if (InsertPhoto(sceneCode_, infos, type) != E_OK) {
715         AddToExternalFailedOffsets(offset);
716     }
717 }
718 
QueryNotSyncTotalNumber(int32_t maxId,bool isCamera)719 int32_t UpgradeRestore::QueryNotSyncTotalNumber(int32_t maxId, bool isCamera)
720 {
721     std::string queryCamera = isCamera ? IN_CAMERA : NOT_IN_CAMERA;
722     std::string queryNotSyncByCount = QUERY_COUNT_FROM_FILES + queryCamera + " AND " +
723         COMPARE_ID + std::to_string(maxId) + " AND " + QUERY_NOT_SYNC;
724     return BackupDatabaseUtils::QueryInt(externalRdb_, queryNotSyncByCount, CUSTOM_COUNT);
725 }
726 
HandleRestData(void)727 void UpgradeRestore::HandleRestData(void)
728 {
729     int64_t startRestoreThumbnail = MediaFileUtils::UTCTimeMilliSeconds();
730     MEDIA_INFO_LOG("Start to handle rest data in native.");
731     RestoreThumbnail();
732     int64_t endRestoreThumbnail = MediaFileUtils::UTCTimeMilliSeconds();
733     MEDIA_INFO_LOG("TimeCost: RestoreThumbnail cost: %{public}" PRId64, endRestoreThumbnail - startRestoreThumbnail);
734     int32_t restoreMode = BaseRestore::GetRestoreMode();
735     if (restoreMode != RESTORE_MODE_PROC_ALL_DATA && restoreMode != RESTORE_MODE_PROC_TWIN_DATA) {
736         MEDIA_DEBUG_LOG("restore mode no need to del rest data");
737         return;
738     }
739 
740     int64_t startDeleteDir = MediaFileUtils::UTCTimeMilliSeconds();
741     std::string photoData = appDataPath_ + "/" + galleryAppName_;
742     std::string mediaData = appDataPath_ + "/" + mediaAppName_;
743     if (MediaFileUtils::IsFileExists(photoData)) {
744         MEDIA_DEBUG_LOG("Start to delete photo data.");
745         (void)MediaFileUtils::DeleteDir(photoData);
746     }
747     if (MediaFileUtils::IsFileExists(mediaData)) {
748         MEDIA_DEBUG_LOG("Start to delete media data.");
749         (void)MediaFileUtils::DeleteDir(mediaData);
750     }
751     BackupFileUtils::DeleteSdDatabase(filePath_);
752     int64_t endDeleteDir = MediaFileUtils::UTCTimeMilliSeconds();
753     MEDIA_INFO_LOG("TimeCost: DeleteDir cost: %{public}" PRId64, endDeleteDir - startDeleteDir);
754     int64_t startDeleteEmptyAlbum = MediaFileUtils::UTCTimeMilliSeconds();
755     this->DeleteEmptyAlbums();
756     int64_t endDeleteEmptyAlbum = MediaFileUtils::UTCTimeMilliSeconds();
757     MEDIA_INFO_LOG("TimeCost: DeleteEmptyAlbum cost: %{public}" PRId64, endDeleteEmptyAlbum - startDeleteEmptyAlbum);
758 }
759 
QueryFileInfos(int32_t minId)760 std::vector<FileInfo> UpgradeRestore::QueryFileInfos(int32_t minId)
761 {
762     std::vector<FileInfo> result;
763     result.reserve(QUERY_COUNT);
764     CHECK_AND_RETURN_RET_LOG(galleryRdb_ != nullptr, result, "galleryRdb_ is nullptr, Maybe init failed.");
765     auto resultSet = this->photosRestore_.GetGalleryMedia(
766         minId, QUERY_COUNT, this->shouldIncludeSd_, this->hasLowQualityImage_);
767     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
768     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
769         FileInfo tmpInfo;
770         CHECK_AND_EXECUTE(!ParseResultSetFromGallery(resultSet, tmpInfo), result.emplace_back(tmpInfo));
771     }
772     resultSet->Close();
773     return result;
774 }
775 
QueryCloudFileInfos(int32_t minId)776 std::vector<FileInfo> UpgradeRestore::QueryCloudFileInfos(int32_t minId)
777 {
778     std::vector<FileInfo> result;
779     result.reserve(RESTORE_CLOUD_QUERY_COUNT);
780     CHECK_AND_RETURN_RET_LOG(galleryRdb_ != nullptr, result, "cloud galleryRdb_ is nullptr, Maybe init failed.");
781     auto resultSet = this->photosRestore_.GetCloudGalleryMedia(
782         minId, RESTORE_CLOUD_QUERY_COUNT, this->shouldIncludeSd_, this->hasLowQualityImage_);
783     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query cloud resultSql is null.");
784     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
785         FileInfo tmpInfo;
786         CHECK_AND_EXECUTE(!ParseResultSetFromGallery(resultSet, tmpInfo),  result.emplace_back(tmpInfo));
787     }
788     resultSet->Close();
789     return result;
790 }
791 
ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)792 bool UpgradeRestore::ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
793 {
794     info.oldPath = GetStringVal(EXTERNAL_FILE_DATA, resultSet);
795     int32_t mediaType = GetInt32Val(EXTERNAL_MEDIA_TYPE, resultSet);
796     CHECK_AND_RETURN_RET_LOG(mediaType == DUAL_MEDIA_TYPE::AUDIO_TYPE, false,
797         "Invalid media type: %{public}d, path: %{public}s", mediaType,
798         BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
799     info.fileType = MediaType::MEDIA_TYPE_AUDIO;
800     CHECK_AND_RETURN_RET_LOG(BaseRestore::ConvertPathToRealPath(info.oldPath, filePath_, info.filePath,
801         info.relativePath), false, "Invalid path: %{public}s.",
802         BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
803     info.displayName = GetStringVal(EXTERNAL_DISPLAY_NAME, resultSet);
804     info.title = GetStringVal(EXTERNAL_TITLE, resultSet);
805     info.fileSize = GetInt64Val(EXTERNAL_FILE_SIZE, resultSet);
806     CHECK_AND_WARN_LOG(info.fileSize >= GARBAGE_PHOTO_SIZE, "maybe garbage path = %{public}s.",
807         BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
808     info.duration = GetInt64Val(GALLERY_DURATION, resultSet);
809     info.isFavorite = GetInt32Val(EXTERNAL_IS_FAVORITE, resultSet);
810     info.dateModified = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet) * MSEC_TO_SEC;
811     return true;
812 }
813 
QueryFileInfosFromExternal(int32_t offset,int32_t maxId,bool isCamera)814 std::vector<FileInfo> UpgradeRestore::QueryFileInfosFromExternal(int32_t offset, int32_t maxId, bool isCamera)
815 {
816     std::vector<FileInfo> result;
817     result.reserve(QUERY_COUNT);
818     CHECK_AND_RETURN_RET_LOG(externalRdb_ != nullptr, result, "Pointer rdb_ is nullptr, Maybe init failed.");
819     std::string queryCamera = isCamera ? IN_CAMERA : NOT_IN_CAMERA;
820     std::string queryFilesByCount = QUERY_FILE_COLUMN + queryCamera + " AND " +
821         COMPARE_ID + std::to_string(maxId) + " AND " + QUERY_NOT_SYNC + " limit " + std::to_string(offset) + ", " +
822         std::to_string(QUERY_COUNT);
823     auto resultSet = externalRdb_->QuerySql(queryFilesByCount);
824     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
825     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
826         FileInfo tmpInfo;
827         if (ParseResultSetFromExternal(resultSet, tmpInfo)) {
828             std::string findPath = tmpInfo.relativePath;
829             bool isValid = IsValidDir(findPath);
830             if (isValid) {
831                 result.emplace_back(tmpInfo);
832             }
833         }
834     }
835     resultSet->Close();
836     return result;
837 }
838 
IsValidDir(const string & path)839 bool UpgradeRestore::IsValidDir(const string &path)
840 {
841     bool isValid = true;
842     for (auto &cacheDir : cacheSet_) {
843         if (path.find(cacheDir) == 0) {
844             isValid = false;
845             break;
846         }
847     }
848     return isValid;
849 }
ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,string dbName)850 bool UpgradeRestore::ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
851     string dbName)
852 {
853     // only parse image and video
854     CHECK_AND_RETURN_RET(IsBasicInfoValid(resultSet, info, dbName), false);
855     info.title = GetStringVal(GALLERY_TITLE, resultSet);
856     info.userComment = GetStringVal(GALLERY_DESCRIPTION, resultSet);
857     info.duration = GetInt64Val(GALLERY_DURATION, resultSet);
858     info.isFavorite = GetInt32Val(GALLERY_IS_FAVORITE, resultSet);
859     info.specialFileType = GetInt32Val(GALLERY_SPECIAL_FILE_TYPE, resultSet);
860     // only local data need livePhoto path
861     if (info.localMediaId != -1 && BackupFileUtils::IsLivePhoto(info) &&
862         !BackupFileUtils::ConvertToMovingPhoto(info)) {
863         ErrorInfo errorInfo(RestoreError::MOVING_PHOTO_CONVERT_FAILED, 1, "",
864             BackupLogUtils::FileInfoToString(sceneCode_, info));
865         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
866         return false;
867     }
868     info.height = GetInt64Val(GALLERY_HEIGHT, resultSet);
869     info.width = GetInt64Val(GALLERY_WIDTH, resultSet);
870     info.resolution = GetStringVal(GALLERY_RESOLUTION, resultSet);
871     // For cloud data, prioritize using resolution parsing to obtain the width and height.
872     // If parsing fails, set both width and height to 0
873     if (info.localMediaId == -1) {
874         BackupFileUtils::ParseResolution(info.resolution, info.width, info.height);
875     }
876     info.orientation = GetInt64Val(GALLERY_ORIENTATION, resultSet);
877     info.dateModified = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet) * MSEC_TO_SEC;
878     info.firstUpdateTime = GetInt64Val(GALLERY_FIRST_UPDATE_TIME, resultSet);
879     info.detailTime = GetStringVal(GALLERY_DETAIL_TIME, resultSet);
880     info.userId = BackupFileUtils::GetUserId(info.oldPath);
881     return true;
882 }
883 
ParseResultSetFromGallery(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)884 bool UpgradeRestore::ParseResultSetFromGallery(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
885 {
886     info.localMediaId = GetInt32Val(GALLERY_LOCAL_MEDIA_ID, resultSet);
887     info.hidden = (info.localMediaId == GALLERY_HIDDEN_ID) ? 1 : 0;
888     info.recycledTime = GetInt64Val(GALLERY_RECYCLED_TIME, resultSet);
889     info.showDateToken = GetInt64Val(GALLERY_SHOW_DATE_TOKEN, resultSet);
890     // fetch relative_bucket_id, recycleFlag, is_hw_burst, hash field to generate burst_key
891     info.relativeBucketId = GetStringVal(GALLERY_MEDIA_BUCKET_ID, resultSet);
892     info.recycleFlag = GetInt32Val(GALLERY_RECYCLE_FLAG, resultSet);
893     info.isBurst = GetInt32Val(GALLERY_IS_BURST, resultSet);
894     info.hashCode = GetStringVal(GALLERY_HASH, resultSet);
895     info.fileIdOld = GetInt32Val(GALLERY_ID, resultSet);
896     info.photoQuality = GetInt32Val(PhotoColumn::PHOTO_QUALITY, resultSet);
897     info.thumbType = GetInt32Val(GALLERY_THUMB_TYPE, resultSet);
898     info.filePath = GetStringVal(GALLERY_FILE_DATA, resultSet);
899     info.albumId = GetStringVal(GALLERY_ALBUM_ID, resultSet);
900     info.orientation = GetInt32Val(GALLERY_ORIENTATION, resultSet);
901     info.uniqueId = GetStringVal(GALLERY_UNIQUE_ID, resultSet);
902     info.localThumbPath = GetStringVal(GALLERY_LOCAL_THUMB_PATH_ID, resultSet);
903     info.localBigThumbPath = GetStringVal(GALLERY_LOCAL_BIG_THUMB_PATH_ID, resultSet);
904     info.dateTaken = info.showDateToken;
905     bool isSuccess = ParseResultSet(resultSet, info, GALLERY_DB_NAME);
906     CHECK_AND_RETURN_RET_LOG(isSuccess, isSuccess, "ParseResultSetFromGallery fail");
907     info.burstKey = burstKeyGenerator_.FindBurstKey(info);
908     // Pre-Fetch: sourcePath, lPath
909     info.sourcePath = GetStringVal(GALLERY_MEDIA_SOURCE_PATH, resultSet);
910     info.lPath = GetStringVal(GALLERY_ALBUM_IPATH, resultSet);
911     // Find lPath, bundleName, packageName by sourcePath, lPath
912     info.lPath = this->photosRestore_.FindlPath(info);
913     info.bundleName = this->photosRestore_.FindBundleName(info);
914     info.packageName = this->photosRestore_.FindPackageName(info);
915     info.photoQuality = this->photosRestore_.FindPhotoQuality(info);
916     info.latitude = GetDoubleVal("latitude", resultSet);
917     info.longitude = GetDoubleVal("longitude", resultSet);
918     info.storyIds = GetStringVal("story_id", resultSet);
919     info.portraitIds = GetStringVal("portrait_id", resultSet);
920     info.storyChosen = GetInt32Val("story_chosen", resultSet);
921     return isSuccess;
922 }
923 
ParseResultSetFromExternal(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,int mediaType)924 bool UpgradeRestore::ParseResultSetFromExternal(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
925     int mediaType)
926 {
927     bool isSuccess;
928     if (mediaType == DUAL_MEDIA_TYPE::AUDIO_TYPE) {
929         isSuccess = ParseResultSetForAudio(resultSet, info);
930     } else {
931         isSuccess = ParseResultSet(resultSet, info, EXTERNAL_DB_NAME);
932     }
933     CHECK_AND_RETURN_RET_LOG(isSuccess, isSuccess, "ParseResultSetFromExternal fail");
934     info.showDateToken = GetInt64Val(EXTERNAL_DATE_TAKEN, resultSet);
935     info.dateTaken = GetInt64Val(EXTERNAL_DATE_TAKEN, resultSet);
936     info.sourcePath = GetStringVal(EXTERNAL_FILE_DATA, resultSet);
937     info.localMediaId = GetInt32Val(EXTERNAL_FILE_ID, resultSet);
938     return isSuccess;
939 }
940 
GetInsertValue(const FileInfo & fileInfo,const std::string & newPath,int32_t sourceType)941 NativeRdb::ValuesBucket UpgradeRestore::GetInsertValue(const FileInfo &fileInfo, const std::string &newPath,
942     int32_t sourceType)
943 {
944     NativeRdb::ValuesBucket values;
945     values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
946     values.PutString(MediaColumn::MEDIA_TITLE, fileInfo.title);
947     values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
948     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(fileInfo.displayName));
949     values.PutInt(MediaColumn::MEDIA_TYPE, fileInfo.fileType);
950     if (fileInfo.firstUpdateTime != 0) {
951         values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.firstUpdateTime);
952     } else if (fileInfo.dateTaken != 0) {
953         values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateTaken);
954     }
955     if (fileInfo.dateTaken != 0) {
956         values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, fileInfo.dateTaken);
957     } else {
958         UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
959             .ReportInAudit("INVALID_DATETAKEN", std::to_string(fileInfo.dateTaken),
960                 BackupLogUtils::FileInfoToString(sceneCode_, fileInfo));
961     }
962     values.PutString(PhotoColumn::PHOTO_DETAIL_TIME, fileInfo.detailTime);
963     values.PutLong(MediaColumn::MEDIA_DURATION, fileInfo.duration);
964     values.PutInt(MediaColumn::MEDIA_IS_FAV, fileInfo.isFavorite);
965     if (fileInfo.isFavorite != 0) {
966         string fileName = fileInfo.displayName;
967         MEDIA_WARN_LOG("the file :%{public}s is favorite.", BackupFileUtils::GarbleFileName(fileName).c_str());
968     }
969     values.PutLong(MediaColumn::MEDIA_DATE_TRASHED, this->photosRestore_.FindDateTrashed(fileInfo));
970     values.PutInt(MediaColumn::MEDIA_HIDDEN, fileInfo.hidden);
971     if (fileInfo.hidden != 0) {
972         string fileName = fileInfo.displayName;
973         MEDIA_WARN_LOG("the file :%{public}s is hidden.", BackupFileUtils::GarbleFileName(fileName).c_str());
974     }
975     values.PutInt(PhotoColumn::PHOTO_HEIGHT, fileInfo.height);
976     values.PutInt(PhotoColumn::PHOTO_WIDTH, fileInfo.width);
977     values.PutString(PhotoColumn::PHOTO_USER_COMMENT, fileInfo.userComment);
978     std::string package_name = fileInfo.packageName;
979     if (package_name != "") {
980         values.PutString(PhotoColumn::MEDIA_PACKAGE_NAME, package_name);
981     }
982     values.PutInt(PhotoColumn::PHOTO_QUALITY, fileInfo.photoQuality);
983     values.PutInt(PhotoColumn::PHOTO_SUBTYPE, this->photosRestore_.FindSubtype(fileInfo));
984     values.PutInt(PhotoColumn::PHOTO_BURST_COVER_LEVEL, this->photosRestore_.FindBurstCoverLevel(fileInfo));
985     values.PutString(PhotoColumn::PHOTO_BURST_KEY, this->photosRestore_.FindBurstKey(fileInfo));
986     // find album_id by lPath.
987     values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, this->photosRestore_.FindAlbumId(fileInfo));
988     // fill the source_path at last.
989     values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, this->photosRestore_.FindSourcePath(fileInfo));
990     values.PutInt(PhotoColumn::PHOTO_STRONG_ASSOCIATION, this->photosRestore_.FindStrongAssociation(fileInfo));
991     values.PutInt(PhotoColumn::PHOTO_CE_AVAILABLE, this->photosRestore_.FindCeAvailable(fileInfo));
992     // set invisible for local & cloud
993     values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
994     // for cloud clone
995     if (fileInfo.localMediaId == -1) {
996         values.PutString(PhotoColumn::PHOTO_CLOUD_ID, fileInfo.uniqueId);
997         values.PutInt(PhotoColumn::PHOTO_POSITION, PHOTO_CLOUD_POSITION);
998         values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_SYNCED));
999     } else {
1000         values.PutInt(PhotoColumn::PHOTO_DIRTY, this->photosRestore_.FindDirty(fileInfo));
1001     }
1002     return values;
1003 }
1004 
ConvertPathToRealPath(const std::string & srcPath,const std::string & prefix,std::string & newPath,std::string & relativePath)1005 bool UpgradeRestore::ConvertPathToRealPath(const std::string &srcPath, const std::string &prefix,
1006     std::string &newPath, std::string &relativePath)
1007 {
1008     size_t pos = 0;
1009     CHECK_AND_RETURN_RET(BackupFileUtils::GetPathPosByPrefixLevel(sceneCode_, srcPath,
1010         INTERNAL_PREFIX_LEVEL, pos), false);
1011     newPath = prefix + srcPath;
1012     relativePath = srcPath.substr(pos);
1013     return true;
1014 }
1015 
ConvertPathToRealPath(const std::string & srcPath,const std::string & prefix,std::string & newPath,std::string & relativePath,FileInfo & fileInfo)1016 bool UpgradeRestore::ConvertPathToRealPath(const std::string &srcPath, const std::string &prefix,
1017     std::string &newPath, std::string &relativePath, FileInfo &fileInfo)
1018 {
1019     if (MediaFileUtils::StartsWith(srcPath, INTERNAL_PREFIX)) {
1020         return ConvertPathToRealPath(srcPath, prefix, newPath, relativePath);
1021     }
1022     size_t pos = 0;
1023     if (!BackupFileUtils::GetPathPosByPrefixLevel(sceneCode_, srcPath, SD_PREFIX_LEVEL, pos)) {
1024         return false;
1025     }
1026     relativePath = srcPath.substr(pos);
1027     if (fileInfo.fileSize < TAR_FILE_LIMIT || fileInfo.localMediaId == GALLERY_HIDDEN_ID ||
1028         fileInfo.localMediaId == GALLERY_TRASHED_ID) {
1029         newPath = prefix + srcPath; // packed as tar, hidden or trashed, use path in DB
1030     } else {
1031         newPath = prefix + relativePath; // others, remove sd prefix, use relative path
1032     }
1033     fileInfo.isInternal = false;
1034     return true;
1035 }
1036 
1037 /**
1038  * @brief Update the FileInfo if it has a copy in system.
1039  */
HasSameFileForDualClone(FileInfo & fileInfo)1040 bool UpgradeRestore::HasSameFileForDualClone(FileInfo &fileInfo)
1041 {
1042     PhotosDao::PhotosRowData rowData = this->photosRestore_.FindSameFile(fileInfo);
1043     int32_t fileId = rowData.fileId;
1044     std::string cloudPath = rowData.data;
1045     if (fileId <= 0 || cloudPath.empty()) {
1046         return false;
1047     }
1048     // Meed extra check to determine whether or not to drop the duplicate file.
1049     return ExtraCheckForCloneSameFile(fileInfo, rowData);
1050 }
1051 
RestoreFromGalleryPortraitAlbum()1052 void UpgradeRestore::RestoreFromGalleryPortraitAlbum()
1053 {
1054     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
1055     maxAnalysisAlbumId_ = BackupDatabaseUtils::QueryMaxId(mediaLibraryRdb_,
1056         ANALYSIS_ALBUM_TABLE, ANALYSIS_COL_ALBUM_ID);
1057     int32_t totalNumber = QueryPortraitAlbumTotalNumber();
1058     MEDIA_INFO_LOG("QueryPortraitAlbumTotalNumber, totalNumber = %{public}d", totalNumber);
1059 
1060     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
1061         std::vector<std::string> tagNameToDeleteSelection;
1062         std::vector<std::string> tagIds;
1063         vector<PortraitAlbumInfo> portraitAlbumInfos = QueryPortraitAlbumInfos(offset,
1064             tagNameToDeleteSelection);
1065         CHECK_AND_RETURN_LOG(BackupDatabaseUtils::DeleteDuplicatePortraitAlbum(maxAnalysisAlbumId_,
1066             tagNameToDeleteSelection, tagIds, mediaLibraryRdb_), "Batch delete duplicate portrait album failed.");
1067         InsertPortraitAlbum(portraitAlbumInfos);
1068     }
1069 
1070     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1071     migratePortraitTotalTimeCost_ += end - start;
1072 }
1073 
QueryPortraitAlbumTotalNumber()1074 int32_t UpgradeRestore::QueryPortraitAlbumTotalNumber()
1075 {
1076     return BackupDatabaseUtils::QueryInt(galleryRdb_,
1077         (IsCloudRestoreSatisfied() ?
1078         QUERY_GALLERY_PORTRAIT_ALBUM_WITH_CLOUD_COUNT : QUERY_GALLERY_PORTRAIT_ALBUM_COUNT), CUSTOM_COUNT);
1079 }
1080 
QueryPortraitAlbumInfos(int32_t offset,std::vector<std::string> & tagNameToDeleteSelection)1081 vector<PortraitAlbumInfo> UpgradeRestore::QueryPortraitAlbumInfos(int32_t offset,
1082     std::vector<std::string>& tagNameToDeleteSelection)
1083 {
1084     vector<PortraitAlbumInfo> result;
1085     result.reserve(QUERY_COUNT);
1086 
1087     std::string querySql = "SELECT " + GALLERY_MERGE_TAG_TAG_ID + ", " + GALLERY_GROUP_TAG + ", " +
1088         GALLERY_TAG_NAME + ", " + GALLERY_USER_OPERATION + ", " + GALLERY_RENAME_OPERATION +
1089         " FROM " + (IsCloudRestoreSatisfied() ?
1090         GALLERY_PORTRAIT_ALBUM_TABLE_WITH_CLOUD : GALLERY_PORTRAIT_ALBUM_TABLE);
1091     querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
1092 
1093     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
1094     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
1095     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1096         PortraitAlbumInfo portraitAlbumInfo;
1097         if (!ParsePortraitAlbumResultSet(resultSet, portraitAlbumInfo)) {
1098             MEDIA_ERR_LOG("Parse portrait album result set failed, exclude %{public}s",
1099                 portraitAlbumInfo.tagName.c_str());
1100             continue;
1101         }
1102         if (!SetAttributes(portraitAlbumInfo)) {
1103             MEDIA_ERR_LOG("Set attributes failed, exclude %{public}s", portraitAlbumInfo.tagName.c_str());
1104             continue;
1105         }
1106         if (!portraitAlbumInfo.tagName.empty()) {
1107             tagNameToDeleteSelection.emplace_back(portraitAlbumInfo.tagName);
1108         }
1109 
1110         result.emplace_back(portraitAlbumInfo);
1111     }
1112     resultSet->Close();
1113     return result;
1114 }
1115 
ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,PortraitAlbumInfo & portraitAlbumInfo)1116 bool UpgradeRestore::ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
1117     PortraitAlbumInfo &portraitAlbumInfo)
1118 {
1119     portraitAlbumInfo.tagIdOld = GetStringVal(GALLERY_MERGE_TAG_TAG_ID, resultSet);
1120     portraitAlbumInfo.groupTagOld = GetStringVal(GALLERY_GROUP_TAG, resultSet);
1121     portraitAlbumInfo.tagName = GetStringVal(GALLERY_TAG_NAME, resultSet);
1122     portraitAlbumInfo.userOperation = GetInt32Val(GALLERY_USER_OPERATION, resultSet);
1123     portraitAlbumInfo.renameOperation = GetInt32Val(GALLERY_RENAME_OPERATION, resultSet);
1124     return true;
1125 }
1126 
SetAttributes(PortraitAlbumInfo & portraitAlbumInfo)1127 bool UpgradeRestore::SetAttributes(PortraitAlbumInfo &portraitAlbumInfo)
1128 {
1129     return BackupDatabaseUtils::SetTagIdNew(portraitAlbumInfo, tagIdMap_);
1130 }
1131 
InsertPortraitAlbum(std::vector<PortraitAlbumInfo> & portraitAlbumInfos)1132 void UpgradeRestore::InsertPortraitAlbum(std::vector<PortraitAlbumInfo> &portraitAlbumInfos)
1133 {
1134     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
1135     CHECK_AND_RETURN_LOG(!portraitAlbumInfos.empty(), "portraitAlbumInfos are empty");
1136 
1137     int64_t startInsertAlbum = MediaFileUtils::UTCTimeMilliSeconds();
1138     int32_t albumRowNum = InsertPortraitAlbumByTable(portraitAlbumInfos, true);
1139     if (albumRowNum <= 0) {
1140         BackupDatabaseUtils::PrintErrorLog("Insert portrait album failed", startInsertAlbum);
1141         return;
1142     }
1143 
1144     int64_t startInsertTag = MediaFileUtils::UTCTimeMilliSeconds();
1145     int32_t tagRowNum = InsertPortraitAlbumByTable(portraitAlbumInfos, false);
1146     if (tagRowNum <= 0) {
1147         BackupDatabaseUtils::PrintErrorLog("Insert face tag failed", startInsertTag);
1148         return;
1149     }
1150 
1151     int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1152     BatchQueryAlbum(portraitAlbumInfos);
1153     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1154     MEDIA_INFO_LOG("insert %{public}ld albums cost %{public}ld, %{public}ld tags cost %{public}ld, query cost "
1155         "%{public}ld.", (long)albumRowNum, (long)(startInsertTag - startInsertAlbum), (long)tagRowNum,
1156         (long)(startQuery - startInsertTag), (long)(end - startQuery));
1157 }
1158 
InsertPortraitAlbumByTable(std::vector<PortraitAlbumInfo> & portraitAlbumInfos,bool isAlbum)1159 int32_t UpgradeRestore::InsertPortraitAlbumByTable(std::vector<PortraitAlbumInfo> &portraitAlbumInfos,
1160     bool isAlbum)
1161 {
1162     std::vector<NativeRdb::ValuesBucket> values = GetInsertValues(portraitAlbumInfos, isAlbum);
1163     int64_t rowNum = 0;
1164     std::string tableName = isAlbum ? ANALYSIS_ALBUM_TABLE : VISION_FACE_TAG_TABLE;
1165     int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
1166     CHECK_AND_RETURN_RET(errCode == E_OK, 0);
1167     return rowNum;
1168 }
1169 
GetInsertValues(std::vector<PortraitAlbumInfo> & portraitAlbumInfos,bool isAlbum)1170 std::vector<NativeRdb::ValuesBucket> UpgradeRestore::GetInsertValues(std::vector<PortraitAlbumInfo> &portraitAlbumInfos,
1171     bool isAlbum)
1172 {
1173     std::vector<NativeRdb::ValuesBucket> values;
1174     for (auto &portraitAlbumInfo : portraitAlbumInfos) {
1175         NativeRdb::ValuesBucket value = GetInsertValue(portraitAlbumInfo, isAlbum);
1176         values.emplace_back(value);
1177     }
1178     return values;
1179 }
1180 
GetInsertValue(const PortraitAlbumInfo & portraitAlbumInfo,bool isAlbum)1181 NativeRdb::ValuesBucket UpgradeRestore::GetInsertValue(const PortraitAlbumInfo &portraitAlbumInfo, bool isAlbum)
1182 {
1183     NativeRdb::ValuesBucket values;
1184     values.PutString(TAG_ID, portraitAlbumInfo.tagIdNew);
1185     values.PutInt(COUNT, 0);
1186     if (isAlbum) {
1187         values.PutString(ALBUM_NAME, portraitAlbumInfo.tagName);
1188         values.PutString(GROUP_TAG, portraitAlbumInfo.groupTagOld);
1189         values.PutInt(USER_OPERATION, portraitAlbumInfo.userOperation);
1190         values.PutInt(RENAME_OPERATION, RENAME_OPERATION_RENAMED);
1191         values.PutInt(ALBUM_TYPE, PhotoAlbumType::SMART);
1192         values.PutInt(ALBUM_SUBTYPE, PhotoAlbumSubType::PORTRAIT);
1193         values.PutInt(USER_DISPLAY_LEVEL, PortraitPages::FIRST_PAGE);
1194         values.PutInt(IS_LOCAL, IS_LOCAL_TRUE);
1195     } else {
1196         values.PutString(TAG_VERSION, E_VERSION); // updated by analysis service
1197     }
1198     return values;
1199 }
1200 
BatchQueryAlbum(std::vector<PortraitAlbumInfo> & portraitAlbumInfos)1201 void UpgradeRestore::BatchQueryAlbum(std::vector<PortraitAlbumInfo> &portraitAlbumInfos)
1202 {
1203     std::string tagIdSelection;
1204     for (auto &portraitAlbumInfo : portraitAlbumInfos) {
1205         BackupDatabaseUtils::UpdateSelection(tagIdSelection, portraitAlbumInfo.tagIdNew, true);
1206     }
1207     std::string querySql = "SELECT " + ALBUM_ID + ", " + TAG_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
1208         TAG_ID + " IN (" + tagIdSelection + ")";
1209     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1210     CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr");
1211     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1212         int32_t albumId = GetInt32Val(ALBUM_ID, resultSet);
1213         std::string tagId = GetStringVal(TAG_ID, resultSet);
1214         bool cond = (albumId <= 0 || tagId.empty());
1215         CHECK_AND_CONTINUE(!cond);
1216         portraitAlbumIdMap_[tagId] = albumId;
1217     }
1218     resultSet->Close();
1219 }
1220 
NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)1221 bool UpgradeRestore::NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
1222 {
1223     if (portraitAlbumIdMap_.empty()) {
1224         return false;
1225     }
1226     std::string selection;
1227     for (const auto &fileInfo : fileInfos) {
1228         BackupDatabaseUtils::UpdateSelection(selection, std::to_string(fileInfo.fileIdOld), false);
1229     }
1230     std::unordered_set<std::string> needQuerySet;
1231     std::string querySql = "SELECT DISTINCT mf.hash "
1232         " FROM merge_face mf "
1233         " INNER JOIN merge_tag mt ON mf.tag_id = mt.tag_id "
1234         " INNER JOIN gallery_media gm ON mf.hash = gm.hash "
1235         " WHERE "
1236         " COALESCE(gm.albumId, '') NOT IN ('default-album-3', 'default-album-4') "
1237         " AND (mt.tag_name IS NOT NULL AND mt.tag_name != '') "
1238         " GROUP BY mf.hash, mf.face_id "
1239         " HAVING gm._id IN (" + selection + ")";
1240 
1241     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
1242     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "Query resultSql is null.");
1243     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1244         std::string hash = GetStringVal(GALLERY_MERGE_FACE_HASH, resultSet);
1245         CHECK_AND_CONTINUE(!hash.empty());
1246         needQuerySet.insert(hash);
1247     }
1248     resultSet->Close();
1249 
1250     CHECK_AND_RETURN_RET(!needQuerySet.empty(), false);
1251     needQueryMap[PhotoRelatedType::PORTRAIT] = needQuerySet;
1252     return true;
1253 }
1254 
InsertFaceAnalysisData(const std::vector<FileInfo> & fileInfos,const NeedQueryMap & needQueryMap,int64_t & faceRowNum,int64_t & mapRowNum,int64_t & photoNum)1255 void UpgradeRestore::InsertFaceAnalysisData(const std::vector<FileInfo> &fileInfos, const NeedQueryMap &needQueryMap,
1256     int64_t &faceRowNum, int64_t &mapRowNum, int64_t &photoNum)
1257 {
1258     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
1259     CHECK_AND_RETURN(needQueryMap.count(PhotoRelatedType::PORTRAIT) != 0);
1260     bool cond = (mediaLibraryRdb_ == nullptr || fileInfos.empty());
1261     CHECK_AND_RETURN_LOG(!cond, "mediaLibraryRdb_ is null or fileInfos empty");
1262 
1263     std::string hashSelection;
1264     std::unordered_map<std::string, FileInfo> fileInfoMap;
1265     SetHashReference(fileInfos, needQueryMap, hashSelection, fileInfoMap);
1266 
1267     int32_t totalNumber = QueryFaceTotalNumber(hashSelection);
1268     MEDIA_INFO_LOG("Current %{public}zu / %{public}zu have %{public}d faces", fileInfoMap.size(), fileInfos.size(),
1269         totalNumber);
1270     std::unordered_set<std::string> excludedFiles;
1271     std::unordered_set<std::string> filesWithFace;
1272     auto uniqueFileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
1273     BackupDatabaseUtils::DeleteExistingImageFaceData(mediaLibraryRdb_, uniqueFileIdPairs);
1274 
1275     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
1276         std::vector<FaceInfo> faceInfos = QueryFaceInfos(hashSelection, fileInfoMap, offset, excludedFiles);
1277         int64_t startInsertFace = MediaFileUtils::UTCTimeMilliSeconds();
1278         faceRowNum += InsertFaceAnalysisDataByTable(faceInfos, false, excludedFiles);
1279         if (faceRowNum <= 0) {
1280             BackupDatabaseUtils::PrintErrorLog("Insert face failed", startInsertFace);
1281             continue;
1282         }
1283         int64_t startInsertMap = MediaFileUtils::UTCTimeMilliSeconds();
1284         mapRowNum += InsertFaceAnalysisDataByTable(faceInfos, true, excludedFiles);
1285         if (mapRowNum <= 0) {
1286             BackupDatabaseUtils::PrintErrorLog("Insert map failed", startInsertMap);
1287             continue;
1288         }
1289         UpdateFilesWithFace(filesWithFace, faceInfos);
1290         int64_t endInsert = MediaFileUtils::UTCTimeMilliSeconds();
1291         MEDIA_INFO_LOG("insert %{public}ld faces cost %{public}ld, %{public}ld maps cost %{public}ld", (long)faceRowNum,
1292             (long)(startInsertMap - startInsertFace), (long)mapRowNum, (long)(endInsert - startInsertMap));
1293     }
1294     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1295     photoNum = static_cast<int64_t>(filesWithFace.size());
1296     migratePortraitFaceNumber_ += faceRowNum;
1297     migratePortraitPhotoNumber_ += photoNum;
1298     migratePortraitTotalTimeCost_ += end - start;
1299 }
1300 
SetHashReference(const std::vector<FileInfo> & fileInfos,const NeedQueryMap & needQueryMap,std::string & hashSelection,std::unordered_map<std::string,FileInfo> & fileInfoMap)1301 void UpgradeRestore::SetHashReference(const std::vector<FileInfo> &fileInfos, const NeedQueryMap &needQueryMap,
1302     std::string &hashSelection, std::unordered_map<std::string, FileInfo> &fileInfoMap)
1303 {
1304     auto needQuerySet = needQueryMap.at(PhotoRelatedType::PORTRAIT);
1305     for (const auto &fileInfo : fileInfos) {
1306         bool isInvalid = fileInfo.hidden || fileInfo.dateTrashed;
1307         bool notInQuerySet = (needQuerySet.count(fileInfo.hashCode) == 0);
1308         bool invalidFileId = (fileInfo.fileIdNew <= 0);
1309         bool cond = isInvalid || notInQuerySet || invalidFileId;
1310         CHECK_AND_CONTINUE(!cond);
1311         // select the first one to build map
1312         CHECK_AND_CONTINUE(fileInfoMap.count(fileInfo.hashCode) <= 0);
1313         BackupDatabaseUtils::UpdateSelection(hashSelection, fileInfo.hashCode, true);
1314         fileInfoMap[fileInfo.hashCode] = fileInfo;
1315     }
1316 }
1317 
QueryFaceTotalNumber(const std::string & hashSelection)1318 int32_t UpgradeRestore::QueryFaceTotalNumber(const std::string &hashSelection)
1319 {
1320     std::string querySql = "SELECT count(1) as count FROM " + GALLERY_TABLE_MERGE_FACE + " WHERE " +
1321         GALLERY_MERGE_FACE_HASH + " IN (" + hashSelection + ")";
1322     return BackupDatabaseUtils::QueryInt(galleryRdb_, querySql, CUSTOM_COUNT);
1323 }
1324 
QueryFaceInfos(const std::string & hashSelection,const std::unordered_map<std::string,FileInfo> & fileInfoMap,int32_t offset,std::unordered_set<std::string> & excludedFiles)1325 std::vector<FaceInfo> UpgradeRestore::QueryFaceInfos(const std::string &hashSelection,
1326     const std::unordered_map<std::string, FileInfo> &fileInfoMap, int32_t offset,
1327     std::unordered_set<std::string> &excludedFiles)
1328 {
1329     vector<FaceInfo> result;
1330     result.reserve(QUERY_COUNT);
1331 
1332     std::string querySql = "SELECT " + GALLERY_SCALE_X + ", " + GALLERY_SCALE_Y + ", " + GALLERY_SCALE_WIDTH + ", " +
1333         GALLERY_SCALE_HEIGHT + ", " + GALLERY_PITCH + ", " + GALLERY_YAW + ", " + GALLERY_ROLL + ", " +
1334         GALLERY_PROB + ", " + GALLERY_TOTAL_FACE + ", " + GALLERY_MERGE_FACE_HASH + ", " + GALLERY_MERGE_FACE_FACE_ID +
1335         ", " + GALLERY_MERGE_FACE_TAG_ID + " FROM " + GALLERY_TABLE_MERGE_FACE + " WHERE " +
1336         GALLERY_MERGE_FACE_HASH + " IN (" + hashSelection + ") ";
1337     querySql += " AND " + GALLERY_MERGE_FACE_TAG_ID + " != \'-1\'";
1338     querySql += " ORDER BY " + GALLERY_MERGE_FACE_HASH + ", " + GALLERY_MERGE_FACE_FACE_ID +
1339         " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
1340 
1341     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
1342     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
1343     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1344         FaceInfo faceInfo;
1345         if (!ParseFaceResultSet(resultSet, faceInfo)) {
1346             MEDIA_ERR_LOG("Parse face result set failed, exclude %{public}s", faceInfo.hash.c_str());
1347             excludedFiles.insert(faceInfo.hash);
1348             continue;
1349         }
1350         if (!SetAttributes(faceInfo, fileInfoMap)) {
1351             MEDIA_ERR_LOG("Set attributes failed, exclude %{public}s", faceInfo.hash.c_str());
1352             excludedFiles.insert(faceInfo.hash);
1353             continue;
1354         }
1355         result.emplace_back(faceInfo);
1356     }
1357     resultSet->Close();
1358     return result;
1359 }
1360 
ParseFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FaceInfo & faceInfo)1361 bool UpgradeRestore::ParseFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FaceInfo &faceInfo)
1362 {
1363     faceInfo.scaleX = GetDoubleVal(GALLERY_SCALE_X, resultSet);
1364     faceInfo.scaleY = GetDoubleVal(GALLERY_SCALE_Y, resultSet);
1365     faceInfo.scaleWidth = GetDoubleVal(GALLERY_SCALE_WIDTH, resultSet);
1366     faceInfo.scaleHeight = GetDoubleVal(GALLERY_SCALE_HEIGHT, resultSet);
1367     faceInfo.pitch = GetDoubleVal(GALLERY_PITCH, resultSet);
1368     faceInfo.yaw = GetDoubleVal(GALLERY_YAW, resultSet);
1369     faceInfo.roll = GetDoubleVal(GALLERY_ROLL, resultSet);
1370     faceInfo.prob = GetDoubleVal(GALLERY_PROB, resultSet);
1371     faceInfo.totalFaces = GetInt32Val(GALLERY_TOTAL_FACE, resultSet);
1372     faceInfo.hash = GetStringVal(GALLERY_MERGE_FACE_HASH, resultSet);
1373     faceInfo.faceId = GetStringVal(GALLERY_MERGE_FACE_FACE_ID, resultSet);
1374     faceInfo.tagIdOld = GetStringVal(GALLERY_MERGE_FACE_TAG_ID, resultSet);
1375     return true;
1376 }
1377 
SetAttributes(FaceInfo & faceInfo,const std::unordered_map<std::string,FileInfo> & fileInfoMap)1378 bool UpgradeRestore::SetAttributes(FaceInfo &faceInfo, const std::unordered_map<std::string, FileInfo> &fileInfoMap)
1379 {
1380     return BackupDatabaseUtils::SetFileIdNew(faceInfo, fileInfoMap) &&
1381         BackupDatabaseUtils::SetTagIdNew(faceInfo, tagIdMap_) &&
1382         BackupDatabaseUtils::SetAlbumIdNew(faceInfo, portraitAlbumIdMap_);
1383 }
1384 
InsertFaceAnalysisDataByTable(const std::vector<FaceInfo> & faceInfos,bool isMap,const std::unordered_set<std::string> & excludedFiles)1385 int32_t UpgradeRestore::InsertFaceAnalysisDataByTable(const std::vector<FaceInfo> &faceInfos, bool isMap,
1386     const std::unordered_set<std::string> &excludedFiles)
1387 {
1388     std::vector<NativeRdb::ValuesBucket> values = GetInsertValues(faceInfos, isMap, excludedFiles);
1389     int64_t rowNum = 0;
1390     std::string tableName = isMap ? ANALYSIS_PHOTO_MAP_TABLE : VISION_IMAGE_FACE_TABLE;
1391     int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
1392     CHECK_AND_RETURN_RET(errCode == E_OK, 0);
1393     return rowNum;
1394 }
1395 
GetInsertValues(const std::vector<FaceInfo> & faceInfos,bool isMap,const std::unordered_set<std::string> & excludedFiles)1396 std::vector<NativeRdb::ValuesBucket> UpgradeRestore::GetInsertValues(const std::vector<FaceInfo> &faceInfos, bool isMap,
1397     const std::unordered_set<std::string> &excludedFiles)
1398 {
1399     std::vector<NativeRdb::ValuesBucket> values;
1400     for (auto &faceInfo : faceInfos) {
1401         CHECK_AND_CONTINUE(excludedFiles.count(faceInfo.hash) <= 0);
1402         bool cond = (isMap && faceInfo.tagIdNew == TAG_ID_UNPROCESSED);
1403         CHECK_AND_CONTINUE(!cond);
1404         NativeRdb::ValuesBucket value = GetInsertValue(faceInfo, isMap);
1405         values.emplace_back(value);
1406     }
1407     return values;
1408 }
1409 
GetInsertValue(const FaceInfo & faceInfo,bool isMap)1410 NativeRdb::ValuesBucket UpgradeRestore::GetInsertValue(const FaceInfo &faceInfo, bool isMap)
1411 {
1412     NativeRdb::ValuesBucket values;
1413     if (isMap) {
1414         values.PutInt(MAP_ALBUM, faceInfo.albumIdNew);
1415         values.PutInt(MAP_ASSET, faceInfo.fileIdNew);
1416     } else {
1417         values.PutDouble(SCALE_X, faceInfo.scaleX);
1418         values.PutDouble(SCALE_Y, faceInfo.scaleY);
1419         values.PutDouble(SCALE_WIDTH, faceInfo.scaleWidth);
1420         values.PutDouble(SCALE_HEIGHT, faceInfo.scaleHeight);
1421         values.PutDouble(PITCH, faceInfo.pitch);
1422         values.PutDouble(YAW, faceInfo.yaw);
1423         values.PutDouble(ROLL, faceInfo.roll);
1424         values.PutDouble(PROB, faceInfo.prob);
1425         values.PutInt(TOTAL_FACES, faceInfo.totalFaces);
1426         values.PutInt(FILE_ID, faceInfo.fileIdNew);
1427         values.PutString(FACE_ID, faceInfo.faceId);
1428         values.PutString(TAG_ID, faceInfo.tagIdNew);
1429         values.PutString(IMAGE_FACE_VERSION, DEFAULT_BACKUP_VERSION); // replaced by the latest
1430         values.PutString(IMAGE_FEATURES_VERSION, E_VERSION); // updated by analysis service
1431     }
1432     return values;
1433 }
1434 
UpdateFilesWithFace(std::unordered_set<std::string> & filesWithFace,const std::vector<FaceInfo> & faceInfos)1435 void UpgradeRestore::UpdateFilesWithFace(std::unordered_set<std::string> &filesWithFace,
1436     const std::vector<FaceInfo> &faceInfos)
1437 {
1438     for (const auto &faceInfo : faceInfos) {
1439         CHECK_AND_CONTINUE(!faceInfo.hash.empty());
1440         filesWithFace.insert(faceInfo.hash);
1441     }
1442 }
1443 
UpdateFaceAnalysisStatus()1444 void UpgradeRestore::UpdateFaceAnalysisStatus()
1445 {
1446     if (portraitAlbumIdMap_.empty()) {
1447         MEDIA_INFO_LOG("There is no need to update face analysis status");
1448         return;
1449     }
1450     int64_t startUpdateGroupTag = MediaFileUtils::UTCTimeMilliSeconds();
1451     BackupDatabaseUtils::UpdateFaceGroupTagOfGallery(mediaLibraryRdb_);
1452     int64_t startUpdateTotal = MediaFileUtils::UTCTimeMilliSeconds();
1453     BackupDatabaseUtils::UpdateAnalysisTotalStatus(mediaLibraryRdb_);
1454     int64_t startUpdateFaceTag = MediaFileUtils::UTCTimeMilliSeconds();
1455     BackupDatabaseUtils::UpdateAnalysisFaceTagStatus(mediaLibraryRdb_);
1456     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1457     MEDIA_INFO_LOG("Update group tag cost %{public}lld, update total table cost %{public}lld, update face tag table "
1458         "cost %{public}lld", (long long)(startUpdateTotal - startUpdateGroupTag),
1459         (long long)(startUpdateFaceTag - startUpdateTotal), (long long)(end - startUpdateFaceTag));
1460     migratePortraitTotalTimeCost_ += end - startUpdateGroupTag;
1461 }
1462 
UpdateDualCloneFaceAnalysisStatus()1463 void UpgradeRestore::UpdateDualCloneFaceAnalysisStatus()
1464 {
1465     if (portraitAlbumIdMap_.empty()) {
1466         MEDIA_INFO_LOG("There is no need to update face analysis status");
1467         return;
1468     }
1469 
1470     BackupDatabaseUtils::UpdateFaceGroupTagOfGallery(mediaLibraryRdb_);
1471     BackupDatabaseUtils::UpdateAnalysisPhotoMapStatus(mediaLibraryRdb_);
1472     BackupDatabaseUtils::UpdateFaceAnalysisTblStatus(mediaLibraryRdb_);
1473 }
1474 
CheckInvalidFile(const FileInfo & fileInfo,int32_t errCode)1475 std::string UpgradeRestore::CheckInvalidFile(const FileInfo &fileInfo, int32_t errCode)
1476 {
1477     CHECK_AND_RETURN_RET(errCode == E_NO_SUCH_FILE, "");
1478     int32_t dbType = BackupDatabaseHelper::DbType::DEFAULT;
1479     int32_t dbStatus = E_OK;
1480     int32_t fileStatus = E_OK;
1481     backupDatabaseHelper_.IsFileExist(sceneCode_, fileInfo, dbType, dbStatus, fileStatus);
1482     MEDIA_INFO_LOG("Check status type: %{public}d, db: %{public}d, file: %{public}d", dbType, dbStatus, fileStatus);
1483     return BackupLogUtils::FileDbCheckInfoToString(FileDbCheckInfo(dbType, dbStatus, fileStatus));
1484 }
1485 
GetNoNeedMigrateCount()1486 int32_t UpgradeRestore::GetNoNeedMigrateCount()
1487 {
1488     return GalleryMediaDao(this->galleryRdb_).GetNoNeedMigrateCount(this->shouldIncludeSd_);
1489 }
1490 
IsBasicInfoValid(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,const std::string & dbName)1491 bool UpgradeRestore::IsBasicInfoValid(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
1492     const std::string &dbName)
1493 {
1494     info.displayName = GetStringVal(GALLERY_DISPLAY_NAME, resultSet);
1495     info.oldPath = GetStringVal(GALLERY_FILE_DATA, resultSet);
1496     info.fileType = GetInt32Val(GALLERY_MEDIA_TYPE, resultSet);
1497     info.fileSize = GetInt64Val(GALLERY_FILE_SIZE, resultSet); // read basic info from db first
1498     if (this->photosRestore_.IsDuplicateData(info.oldPath)) {
1499         ErrorInfo errorInfo(RestoreError::DUPLICATE_DATA, 1, "",
1500             BackupLogUtils::FileInfoToString(sceneCode_, info));
1501         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1502         return false;
1503     }
1504     if (info.thumbType != 0) {
1505         if (sceneCode_ == UPGRADE_RESTORE_ID ?
1506             !BaseRestore::ConvertPathToRealPath(info.oldPath, filePath_, info.filePath, info.relativePath) :
1507             !ConvertPathToRealPath(info.oldPath, filePath_, info.filePath, info.relativePath, info)) {
1508             ErrorInfo errorInfo(RestoreError::PATH_INVALID, 1, "",
1509                 BackupLogUtils::FileInfoToString(sceneCode_, info));
1510             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1511             return false;
1512         }
1513     }
1514     info.fileType = this->photosRestore_.FindMediaType(info);
1515     if (info.fileType != MediaType::MEDIA_TYPE_IMAGE && info.fileType != MediaType::MEDIA_TYPE_VIDEO) {
1516         ErrorInfo errorInfo(RestoreError::MEDIA_TYPE_INVALID, 1, std::to_string(info.fileType),
1517             BackupLogUtils::FileInfoToString(sceneCode_, info));
1518         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1519         return false;
1520     }
1521     if (info.fileSize < fileMinSize_ && dbName == EXTERNAL_DB_NAME) {
1522         MEDIA_WARN_LOG("maybe garbage path = %{public}s, minSize:%{public}d.",
1523             BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str(), fileMinSize_);
1524         ErrorInfo errorInfo(RestoreError::SIZE_INVALID, 1, "Db size < " + std::to_string(fileMinSize_),
1525             BackupLogUtils::FileInfoToString(sceneCode_, info));
1526         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1527         return false;
1528     }
1529     return true;
1530 }
1531 
CheckGalleryDbIntegrity()1532 std::string UpgradeRestore::CheckGalleryDbIntegrity()
1533 {
1534     MEDIA_INFO_LOG("start handle gallery integrity check.");
1535     std::string dbIntegrityCheck = DB_INTEGRITY_CHECK;
1536     std::string dbSize = "";
1537     struct stat statInfo {};
1538     if (stat(galleryDbPath_.c_str(), &statInfo) == 0) {
1539         dbSize = std::to_string(statInfo.st_size);
1540     }
1541     int64_t dbIntegrityCheckTime = MediaFileUtils::UTCTimeMilliSeconds();
1542     dbIntegrityCheck = BackupDatabaseUtils::CheckDbIntegrity(galleryRdb_, sceneCode_, "GALLERY_DB_CORRUPTION");
1543     dbIntegrityCheckTime = MediaFileUtils::UTCTimeMilliSeconds() - dbIntegrityCheckTime;
1544     UpgradeRestoreTaskReport()
1545         .SetSceneCode(this->sceneCode_)
1546         .SetTaskId(this->taskId_)
1547         .ReportProgress("GalleryDbCheck", dbSize + ";" + std::to_string(dbIntegrityCheckTime));
1548     MEDIA_INFO_LOG("end handle gallery integrity check, cost %{public}lld, size %{public}s.", \
1549         (long long)(dbIntegrityCheckTime), dbSize.c_str());
1550     return dbIntegrityCheck;
1551 }
1552 
RestoreAnalysisAlbum()1553 void UpgradeRestore::RestoreAnalysisAlbum()
1554 {
1555     RestoreFromGalleryPortraitAlbum();
1556 }
1557 
SetCloneParameterAndStopSync()1558 void UpgradeRestore::SetCloneParameterAndStopSync()
1559 {
1560     SetParameterForClone();
1561     SetParameterForRestore();
1562 #ifdef CLOUD_SYNC_MANAGER
1563     FileManagement::CloudSync::CloudSyncManager::GetInstance().StopSync("com.ohos.medialibrary.medialibrarydata");
1564 #endif
1565 }
1566 
InitDb(bool isUpgrade)1567 int32_t UpgradeRestore::InitDb(bool isUpgrade)
1568 {
1569     if (isUpgrade && BaseRestore::Init() != E_OK) {
1570         ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "",
1571             "InitDb And Xml fail, isUpgrade = " + std::to_string(isUpgrade));
1572         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1573         return E_FAIL;
1574     }
1575 
1576     if (!MediaFileUtils::IsFileExists(galleryDbPath_)) {
1577         MEDIA_ERR_LOG("Gallery media db is not exist.");
1578     } else {
1579         int32_t galleryErr = BackupDatabaseUtils::InitDb(galleryRdb_, GALLERY_DB_NAME, galleryDbPath_,
1580             galleryAppName_, false);
1581         if (galleryRdb_ == nullptr) {
1582             ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "",
1583                 "Gallery init rdb fail, err = " + std::to_string(galleryErr));
1584             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1585             MEDIA_ERR_LOG("Gallery init rdb fail, err = %{public}d", galleryErr);
1586             return E_FAIL;
1587         }
1588     }
1589 
1590     if (!MediaFileUtils::IsFileExists(audioDbPath_)) {
1591         MEDIA_ERR_LOG("audio mediaInfo db is not exist.");
1592     } else {
1593         int32_t audioErr = BackupDatabaseUtils::InitDb(audioRdb_, AUDIO_DB_NAME, audioDbPath_,
1594             audioAppName_, false);
1595         if (audioRdb_ == nullptr) {
1596             ErrorInfo errorInfo(RestoreError::INIT_FAILED, 0, "",
1597                 "audio init rdb fail, err = " + std::to_string(audioErr));
1598             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1599             MEDIA_ERR_LOG("audio init rdb fail, err = %{public}d", audioErr);
1600             return E_FAIL;
1601         }
1602     }
1603 
1604     return E_OK;
1605 }
1606 
InheritManualCover()1607 void UpgradeRestore::InheritManualCover()
1608 {
1609     std::string querySql = "SELECT gallery_cover_cache.*, gallery_album.* FROM gallery_cover_cache "
1610         "LEFT JOIN gallery_album ON gallery_cover_cache.relative_bucket_id = gallery_album.relativeBucketId "
1611         "WHERE gallery_cover_cache.column_name = 'relative_bucket_id' AND gallery_cover_cache.from_user = 1";
1612     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
1613     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Query resultSql is null.");
1614 
1615     vector<AlbumCoverInfo> albumCoverinfos;
1616     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1617         AlbumCoverInfo albumCoverInfo;
1618         if (RecordAlbumCoverInfo(resultSet, albumCoverInfo) != E_OK) {
1619             continue;
1620         }
1621         auto lPath = albumCoverInfo.lPath;
1622         if (this->photosRestore_.ToLower(lPath) ==
1623             this->photosRestore_.ToLower(LPATH_SCREEN_SHOTS)) {
1624             AlbumCoverInfo screenRecordsCoverInfo;
1625             screenRecordsCoverInfo.albumId = 0;
1626             screenRecordsCoverInfo.lPath = LPATH_SCREEN_RECORDS;
1627             screenRecordsCoverInfo.coverUri = albumCoverInfo.coverUri;
1628             albumCoverinfos.emplace_back(screenRecordsCoverInfo);
1629         }
1630         albumCoverinfos.emplace_back(albumCoverInfo);
1631     }
1632     resultSet->Close();
1633 
1634     UpdatePhotoAlbumCoverUri(albumCoverinfos);
1635     return;
1636 }
1637 
RecordAlbumCoverInfo(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,AlbumCoverInfo & albumCoverInfo)1638 int32_t UpgradeRestore::RecordAlbumCoverInfo(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
1639     AlbumCoverInfo& albumCoverInfo)
1640 {
1641     const static string COLUMN_VALUE = "column_value";
1642     const static string virtualPrefix = "/gallery/album/virtual/common/*/";
1643     const static string COVER_ID = "cover_id";
1644     const static unordered_map<string, int32_t> virtualAlbumIdMap = {
1645         {"/gallery/album/virtual/common/*/0", IMAGE_ALBUM_ID},
1646         {"/gallery/album/virtual/common/*/1", VIDEO_ALBUM_ID},
1647         {"/gallery/album/virtual/common/*/2", FAVORITE_ALBUM_ID},
1648         {"/gallery/album/virtual/common/*/3", CLOUD_ENHANCEMENT_ALBUM_ID},
1649     };
1650     string lPath = GetStringVal(GALLERY_ALBUM_IPATH, resultSet);
1651     if (lPath.empty()) { // virtual album
1652         string columnValue = GetStringVal(COLUMN_VALUE, resultSet);
1653         if (virtualAlbumIdMap.count(columnValue)) {
1654             MEDIA_ERR_LOG("RecordAlbumCoverInfo columnValue:%{public}s not in map", columnValue.c_str());
1655             return E_ERR;
1656         }
1657         int32_t albumId = virtualAlbumIdMap.at(columnValue);
1658         albumCoverInfo.albumId = albumId;
1659     } else {
1660         albumCoverInfo.lPath = lPath;
1661     }
1662     int32_t coverId = GetInt32Val(COVER_ID, resultSet);
1663     PhotoInfo photoInfo = photoInfoMap_[coverId];
1664     int32_t newFileId = photoInfo.fileIdNew;
1665     string displayName = photoInfo.displayName;
1666     string coverUri = MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(newFileId),
1667         MediaFileUtils::GetExtraUri(displayName, photoInfo.cloudPath));
1668     albumCoverInfo.coverUri = coverUri;
1669     return E_OK;
1670 }
1671 
UpdatePhotoAlbumCoverUri(vector<AlbumCoverInfo> & albumCoverInfos)1672 void UpgradeRestore::UpdatePhotoAlbumCoverUri(vector<AlbumCoverInfo>& albumCoverInfos)
1673 {
1674     for (auto& albumCoverInfo : albumCoverInfos) {
1675         if (!albumCoverInfo.lPath.empty()) { // virtual album
1676             auto photoAlbumRowData = this->photosRestore_.GetPhotoAlbumDaoRowData(albumCoverInfo.lPath);
1677             albumCoverInfo.albumId = photoAlbumRowData.albumId;
1678         }
1679         int32_t changeRows = 0;
1680         std::unique_ptr<NativeRdb::AbsRdbPredicates> predicates =
1681             make_unique<NativeRdb::AbsRdbPredicates>(PhotoAlbumColumns::TABLE);
1682         predicates->BeginWrap()
1683         ->EqualTo(PhotoAlbumColumns::ALBUM_ID, albumCoverInfo.albumId)
1684         ->Or()
1685         ->EqualTo(PhotoAlbumColumns::ALBUM_LPATH, albumCoverInfo.lPath)
1686         ->EndWrap();
1687         NativeRdb::ValuesBucket updateBucket;
1688         updateBucket.PutInt(PhotoAlbumColumns::COVER_URI_SOURCE,
1689             static_cast<int32_t>(CoverUriSource::MANUAL_LOCAL_COVER));
1690         updateBucket.PutString(PhotoAlbumColumns::ALBUM_COVER_URI, albumCoverInfo.coverUri);
1691         auto dateModified = MediaFileUtils::UTCTimeMilliSeconds();
1692         updateBucket.PutString(PhotoAlbumColumns::COVER_CLOUD_ID, to_string(dateModified) + ",");
1693         BackupDatabaseUtils::Update(mediaLibraryRdb_, changeRows, updateBucket, predicates);
1694         if (changeRows != 1) {
1695             MEDIA_ERR_LOG("UpdatePhotoAlbumCoverUri failed, expected count 1, but got %{public}d", changeRows);
1696         }
1697     }
1698 }
1699 
SetOrientationAndExifRotate(FileInfo & info,NativeRdb::ValuesBucket & value,std::unique_ptr<Metadata> & data)1700 void UpgradeRestore::SetOrientationAndExifRotate(FileInfo &info, NativeRdb::ValuesBucket &value,
1701     std::unique_ptr<Metadata> &data)
1702 {
1703     CHECK_AND_RETURN_RET(info.localMediaId == -1, BaseRestore::SetOrientationAndExifRotate(info, value, data));
1704     if (info.orientation == 0 || info.fileType != MediaType::MEDIA_TYPE_IMAGE) {
1705         info.exifRotate = 0;
1706         value.PutInt(PhotoColumn::PHOTO_ORIENTATION, info.orientation);
1707         value.PutInt(PhotoColumn::PHOTO_EXIF_ROTATE, 0);
1708     } else {
1709         ExifRotateUtils::ConvertOrientationToExifRotate(info.orientation, info.exifRotate);
1710         value.PutInt(PhotoColumn::PHOTO_ORIENTATION, info.orientation);
1711         value.PutInt(PhotoColumn::PHOTO_EXIF_ROTATE, info.exifRotate);
1712     }
1713 }
1714 
DeleteEmptyAlbums()1715 void UpgradeRestore::DeleteEmptyAlbums()
1716 {
1717     const size_t BATCH_SIZE = 200;
1718     auto albumIds = this->photosRestore_.GetAlbumIdsFromPhotoAlbumCache();
1719     size_t start = 0;
1720     int32_t totalDeleteRows = 0;
1721     while (start < albumIds.size()) {
1722         int32_t deleteRows = 0;
1723         int32_t end = std::min(start + BATCH_SIZE, albumIds.size());
1724         std::vector<int32_t> batchAlbumIds(albumIds.begin() + start, albumIds.begin() + end);
1725         BatchDeleteEmptyAlbums(batchAlbumIds, deleteRows);
1726         totalDeleteRows += deleteRows;
1727         start += BATCH_SIZE;
1728     };
1729     MEDIA_INFO_LOG("delete empty photo album, deleted nums: %{public}d", totalDeleteRows);
1730 }
1731 
BatchDeleteEmptyAlbums(const std::vector<int32_t> & batchAlbumIds,int32_t & deleteRows)1732 void UpgradeRestore::BatchDeleteEmptyAlbums(const std::vector<int32_t> &batchAlbumIds, int32_t &deleteRows)
1733 {
1734     NativeRdb::AbsRdbPredicates deletePredicates("PhotoAlbum");
1735     int32_t maxAlbumId = this->photoAlbumRestore_.GetMaxAlbumId();
1736     std::string whereClause = "album_id > ? AND album_id IN (";
1737     for (auto i = 0; i < batchAlbumIds.size(); i++) {
1738         if (i != 0) {
1739             whereClause += ",";
1740         }
1741         whereClause += "?";
1742     }
1743     whereClause += ")";
1744     whereClause += "AND NOT EXISTS (SELECT 1 FROM Photos as P WHERE P.owner_album_id = PhotoAlbum.album_id)";
1745     deletePredicates.SetWhereClause(whereClause);
1746     std::vector<std::string> whereArgs;
1747     whereArgs.push_back(to_string(maxAlbumId));
1748     for (auto i = 0; i < batchAlbumIds.size(); i++) {
1749         whereArgs.push_back(to_string(batchAlbumIds[i]));
1750     }
1751     deletePredicates.SetWhereArgs(whereArgs);
1752     BackupDatabaseUtils::Delete(deletePredicates, deleteRows, mediaLibraryRdb_);
1753 }
1754 } // namespace Media
1755 } // namespace OHOS