• 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 "ffrt.h"
28 #include "ffrt_inner.h"
29 #include "gallery_db_upgrade.h"
30 #include "media_column.h"
31 #include "media_file_utils.h"
32 #include "media_log.h"
33 #include "medialibrary_data_manager.h"
34 #include "medialibrary_errno.h"
35 #include "medialibrary_rdb_transaction.h"
36 #include "photo_album_restore.h"
37 #include "photos_dao.h"
38 #include "photos_restore.h"
39 #include "result_set_utils.h"
40 #include "upgrade_restore_task_report.h"
41 #include "userfile_manager_types.h"
42 #include "vision_album_column.h"
43 #include "vision_column.h"
44 #include "vision_face_tag_column.h"
45 #include "vision_image_face_column.h"
46 #include "vision_photo_map_column.h"
47 
48 #ifdef CLOUD_SYNC_MANAGER
49 #include "cloud_sync_manager.h"
50 #endif
51 
52 namespace OHOS {
53 namespace Media {
54 constexpr int32_t PHOTOS_TABLE_ALBUM_ID = -1;
55 constexpr int32_t BASE_TEN_NUMBER = 10;
56 constexpr int32_t SEVEN_NUMBER = 7;
57 constexpr int32_t SD_PREFIX_LEVEL = 3;
58 constexpr int32_t RESTORE_CLOUD_QUERY_COUNT = 200;
59 const std::string DB_INTEGRITY_CHECK = "ok";
60 
UpgradeRestore(const std::string & galleryAppName,const std::string & mediaAppName,int32_t sceneCode)61 UpgradeRestore::UpgradeRestore(const std::string &galleryAppName, const std::string &mediaAppName, int32_t sceneCode)
62 {
63     galleryAppName_ = galleryAppName;
64     mediaAppName_ = mediaAppName;
65     sceneCode_ = sceneCode;
66     audioAppName_ = "Audio";
67     ffrt_disable_worker_escape();
68     MEDIA_INFO_LOG("Set ffrt_disable_worker_escape");
69 }
70 
UpgradeRestore(const std::string & galleryAppName,const std::string & mediaAppName,int32_t sceneCode,const std::string & dualDirName)71 UpgradeRestore::UpgradeRestore(const std::string &galleryAppName, const std::string &mediaAppName, int32_t sceneCode,
72     const std::string &dualDirName)
73 {
74     galleryAppName_ = galleryAppName;
75     mediaAppName_ = mediaAppName;
76     sceneCode_ = sceneCode;
77     dualDirName_ = dualDirName;
78     ffrt_disable_worker_escape();
79     MEDIA_INFO_LOG("Set ffrt_disable_worker_escape");
80 }
81 
Init(const std::string & backupRetoreDir,const std::string & upgradeFilePath,bool isUpgrade)82 int32_t UpgradeRestore::Init(const std::string &backupRetoreDir, const std::string &upgradeFilePath, bool isUpgrade)
83 {
84     appDataPath_ = backupRetoreDir;
85     string photosPreferencesPath;
86     if (sceneCode_ == DUAL_FRAME_CLONE_RESTORE_ID) {
87         filePath_ = backupRetoreDir;
88         galleryDbPath_ = backupRetoreDir + "/" + GALLERY_DB_NAME;
89         audioDbPath_ = backupRetoreDir + INTERNAL_PREFIX + "/0/" + AUDIO_DB_NAME;
90         photosPreferencesPath = backupRetoreDir + "/" + galleryAppName_ + "_preferences.xml";
91         // gallery db may include both internal & external, set flag to differentiate, default false
92         shouldIncludeSd_ = BackupFileUtils::ShouldIncludeSd(filePath_);
93         backupDatabaseHelper_.Init(sceneCode_, shouldIncludeSd_, filePath_);
94         SetParameterForClone();
95 #ifdef CLOUD_SYNC_MANAGER
96         FileManagement::CloudSync::CloudSyncManager::GetInstance().StopSync("com.ohos.medialibrary.medialibrarydata");
97 #endif
98     } else {
99         filePath_ = upgradeFilePath;
100         galleryDbPath_ = backupRetoreDir + "/" + galleryAppName_ + "/ce/databases/gallery.db";
101         externalDbPath_ = backupRetoreDir + "/" + mediaAppName_ + "/ce/databases/external.db";
102         photosPreferencesPath =
103             backupRetoreDir + "/" + galleryAppName_ + "/ce/shared_prefs/" + galleryAppName_ + "_preferences.xml";
104         shouldIncludeSd_ = false;
105         if (!MediaFileUtils::IsFileExists(externalDbPath_)) {
106             MEDIA_ERR_LOG("External db is not exist.");
107             return EXTERNAL_DB_NOT_EXIST;
108         }
109         int32_t externalErr = BackupDatabaseUtils::InitDb(externalRdb_, EXTERNAL_DB_NAME, externalDbPath_,
110             mediaAppName_, false);
111         if (externalRdb_ == nullptr) {
112             MEDIA_ERR_LOG("External init rdb fail, err = %{public}d", externalErr);
113             return E_FAIL;
114         }
115         backupDatabaseHelper_.AddDb(BackupDatabaseHelper::DbType::EXTERNAL, externalRdb_);
116     }
117     MEDIA_INFO_LOG("Shoud include Sd: %{public}d", static_cast<int32_t>(shouldIncludeSd_));
118     return InitDbAndXml(photosPreferencesPath, isUpgrade);
119 }
120 
InitDbAndXml(std::string xmlPath,bool isUpgrade)121 int32_t UpgradeRestore::InitDbAndXml(std::string xmlPath, bool isUpgrade)
122 {
123     if (isUpgrade && BaseRestore::Init() != E_OK) {
124         return E_FAIL;
125     }
126     if (!MediaFileUtils::IsFileExists(galleryDbPath_)) {
127         MEDIA_ERR_LOG("Gallery media db is not exist.");
128     } else {
129         int32_t galleryErr = BackupDatabaseUtils::InitDb(galleryRdb_, GALLERY_DB_NAME, galleryDbPath_,
130             galleryAppName_, false);
131         if (galleryRdb_ == nullptr) {
132             MEDIA_ERR_LOG("Gallery init rdb fail, err = %{public}d", galleryErr);
133             return E_FAIL;
134         }
135     }
136 
137     if (!MediaFileUtils::IsFileExists(audioDbPath_)) {
138         MEDIA_ERR_LOG("audio mediaInfo db is not exist.");
139     } else {
140         int32_t audioErr = BackupDatabaseUtils::InitDb(audioRdb_, AUDIO_DB_NAME, audioDbPath_,
141             audioAppName_, false);
142         if (audioRdb_ == nullptr) {
143             MEDIA_ERR_LOG("audio init rdb fail, err = %{public}d", audioErr);
144             return E_FAIL;
145         }
146     }
147     ParseXml(xmlPath);
148     this->photoAlbumRestore_.OnStart(this->mediaLibraryRdb_, this->galleryRdb_);
149     this->photosRestore_.OnStart(this->mediaLibraryRdb_, this->galleryRdb_);
150     geoKnowledgeRestore_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->galleryRdb_);
151     highlightRestore_.Init(this->sceneCode_, this->taskId_, this->mediaLibraryRdb_, this->galleryRdb_);
152     MEDIA_INFO_LOG("Init db succ.");
153     return E_OK;
154 }
155 
HasLowQualityImage()156 bool UpgradeRestore::HasLowQualityImage()
157 {
158     std::string sql = "SELECT count(1) AS count FROM gallery_media WHERE (local_media_id != -1) AND \
159         (storage_id IN (0, 65537)) AND relative_bucket_id NOT IN (SELECT DISTINCT relative_bucket_id FROM \
160         garbage_album WHERE type = 1) AND _size = 0 AND photo_quality = 0";
161     int count = BackupDatabaseUtils::QueryInt(galleryRdb_, sql, CUSTOM_COUNT);
162     MEDIA_INFO_LOG("HasLowQualityImage count:%{public}d", count);
163     hasLowQualityImage_ = (count > 0);
164     return hasLowQualityImage_;
165 }
166 
StringToInt(const std::string & str)167 int UpgradeRestore::StringToInt(const std::string& str)
168 {
169     if (str.empty()) {
170         return 0;
171     }
172     int base = 0;
173     size_t num = 0;
174     int sign = 1;
175     size_t len = static_cast<ssize_t>(str.length());
176     while (num < len && str[num] == ' ') {
177         num++;
178     }
179     if (num < len && (str[num] == '-' || str[num] == '+')) {
180         sign = (str[num++] == '-') ? -1 : 1;
181     }
182     while (num < len && std::isdigit(str[num])) {
183         if (base > INT_MAX / BASE_TEN_NUMBER || (base == INT_MAX / BASE_TEN_NUMBER && str[num] - '0' > SEVEN_NUMBER)) {
184             MEDIA_INFO_LOG("The number is INT_MAX");
185             return 0;
186         }
187         base = BASE_TEN_NUMBER * base + (str[num++] - '0');
188     }
189     if (num < len && !std::isdigit(str[num])) {
190         MEDIA_INFO_LOG("Not digit");
191         return 0;
192     }
193     return base * sign;
194 }
195 
HandleXmlNode(xmlNodePtr cur)196 int32_t UpgradeRestore::HandleXmlNode(xmlNodePtr cur)
197 {
198     if (cur->type == XML_ELEMENT_NODE) {
199         xmlChar* name = xmlGetProp(cur, BAD_CAST"name");
200         if (name != nullptr && xmlStrcmp(name, BAD_CAST"filter_selected_size") == 0) {
201             xmlChar* value = xmlGetProp(cur, BAD_CAST"value");
202             if (value != nullptr) {
203                 fileMinSize_ = StringToInt((const char *)(value));
204                 xmlFree(value);
205                 return E_SUCCESS;
206             }
207             xmlFree(name);
208             return E_ERR;
209         }
210         xmlFree(name);
211     }
212     return E_ERR;
213 }
214 
ParseXml(string path)215 int32_t UpgradeRestore::ParseXml(string path)
216 {
217     std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
218         xmlReadFile(path.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
219     if (docPtr == nullptr) {
220         MEDIA_ERR_LOG("failed to read xml file");
221         return E_ERR;
222     }
223     auto root = xmlDocGetRootElement(docPtr.get());
224     if (root == nullptr) {
225         MEDIA_ERR_LOG("failed to read root node");
226         return E_ERR;
227     }
228     for (xmlNodePtr cur = root->children; cur != NULL; cur = cur->next) {
229         if (HandleXmlNode(cur) == E_SUCCESS) {
230             return E_SUCCESS;
231         }
232     }
233     return E_ERR;
234 }
235 
RestoreAudio(void)236 void UpgradeRestore::RestoreAudio(void)
237 {
238     if (sceneCode_ == DUAL_FRAME_CLONE_RESTORE_ID) {
239         if (!MediaFileUtils::IsFileExists(RESTORE_MUSIC_LOCAL_DIR)) {
240             MEDIA_INFO_LOG("music dir is not exists!!!");
241             MediaFileUtils::CreateDirectory(RESTORE_MUSIC_LOCAL_DIR);
242         }
243         RestoreAudioFromFile();
244     }
245     (void)NativeRdb::RdbHelper::DeleteRdbStore(audioDbPath_);
246 
247     int32_t restoreMode = BaseRestore::GetRestoreMode();
248     if (restoreMode == RESTORE_MODE_PROC_ALL_DATA || restoreMode == RESTORE_MODE_PROC_TWIN_DATA) {
249         (void)NativeRdb::RdbHelper::DeleteRdbStore(externalDbPath_);
250     } else {
251         MEDIA_INFO_LOG("restore mode no need to del external db");
252     }
253 }
254 
RestoreAudioFromFile()255 void UpgradeRestore::RestoreAudioFromFile()
256 {
257     MEDIA_INFO_LOG("start restore audio from audio_MediaInfo0");
258     int32_t totalNumber = BackupDatabaseUtils::QueryInt(audioRdb_, QUERY_DUAL_CLONE_AUDIO_COUNT, CUSTOM_COUNT);
259     MEDIA_INFO_LOG("totalNumber = %{public}d", totalNumber);
260     audioTotalNumber_ += static_cast<uint64_t>(totalNumber);
261     MEDIA_INFO_LOG("onProcess Update audioTotalNumber_: %{public}lld", (long long)audioTotalNumber_);
262     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
263         ffrt::submit([this, offset]() { RestoreAudioBatch(offset); }, { &offset }, {},
264             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
265     }
266     ffrt::wait();
267 }
268 
RestoreAudioBatch(int32_t offset)269 void UpgradeRestore::RestoreAudioBatch(int32_t offset)
270 {
271     MEDIA_INFO_LOG("start restore audio from external, offset: %{public}d", offset);
272     std::vector<FileInfo> infos = QueryAudioFileInfosFromAudio(offset);
273     InsertAudio(sceneCode_, infos);
274 }
275 
QueryAudioFileInfosFromAudio(int32_t offset)276 std::vector<FileInfo> UpgradeRestore::QueryAudioFileInfosFromAudio(int32_t offset)
277 {
278     std::vector<FileInfo> result;
279     result.reserve(QUERY_COUNT);
280     if (audioRdb_ == nullptr) {
281         MEDIA_ERR_LOG("audioRdb_ is nullptr, Maybe init failed.");
282         return result;
283     }
284     std::string queryAllAudioByCount = QUERY_ALL_AUDIOS_FROM_AUDIODB + " limit " + std::to_string(offset) + ", " +
285         std::to_string(QUERY_COUNT);
286     auto resultSet = audioRdb_->QuerySql(queryAllAudioByCount);
287     if (resultSet == nullptr) {
288         MEDIA_ERR_LOG("Query resultSql is null.");
289         return result;
290     }
291     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
292         FileInfo tmpInfo;
293         if (ParseResultSetFromAudioDb(resultSet, tmpInfo)) {
294             result.emplace_back(tmpInfo);
295         }
296     }
297     return result;
298 }
299 
ParseResultSetFromAudioDb(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)300 bool UpgradeRestore::ParseResultSetFromAudioDb(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
301 {
302     info.fileType = MediaType::MEDIA_TYPE_AUDIO;
303     info.oldPath = GetStringVal(AUDIO_DATA, resultSet);
304     if (!ConvertPathToRealPath(info.oldPath, filePath_, info.filePath, info.relativePath)) {
305         MEDIA_ERR_LOG("Invalid path: %{public}s.",
306             BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
307         return false;
308     }
309     info.showDateToken = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet);
310     info.dateModified = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet) * MSEC_TO_SEC;
311     info.displayName = BackupFileUtils::GetFileNameFromPath(info.filePath);
312     info.title = BackupFileUtils::GetFileTitle(info.displayName);
313     info.packageName = BackupFileUtils::GetFileFolderFromPath(info.relativePath, false);
314     info.isFavorite = 0;
315     info.recycledTime = 0;
316     return true;
317 }
318 
GetHighlightCloudMediaCnt()319 int32_t UpgradeRestore::GetHighlightCloudMediaCnt()
320 {
321     const std::string QUERY_SQL = "SELECT COUNT(1) AS count FROM t_story_album t1 "
322         "WHERE COALESCE(t1.name, '') <> '' AND t1.displayable = 1 "
323         "AND EXISTS "
324         "(SELECT t2._id FROM gallery_media t2 WHERE t2.local_media_id = -1 "
325         "AND t2.story_chosen = 1 "
326         "AND (t2.story_id LIKE '%,'||t1.story_id||',%' OR t2.portrait_id LIKE '%,'||t1.story_id||',%'))";
327     std::shared_ptr<NativeRdb::ResultSet> resultSet =
328         BackupDatabaseUtils::QuerySql(this->galleryRdb_, QUERY_SQL, {});
329     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
330         MEDIA_ERR_LOG("query count of highlight cloud media failed.");
331         return -1;
332     }
333     int32_t cnt = GetInt32Val("count", resultSet);
334     MEDIA_INFO_LOG("GetHighlightCloudMediaCnt is %{public}d", cnt);
335     resultSet->Close();
336     return cnt;
337 }
338 
RestoreHighlightAlbums()339 void UpgradeRestore::RestoreHighlightAlbums()
340 {
341     int32_t highlightCloudMediaCnt = GetHighlightCloudMediaCnt();
342     UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
343         .Report("Highlight Restore", "",
344         "sceneCode_: " + std::to_string(sceneCode_) +
345         ", dualDeviceSoftName_: " + dualDeviceSoftName_ +
346         ", highlightCloudMediaCnt: " + std::to_string(highlightCloudMediaCnt) +
347         ", isAccountValid_: " + std::to_string(isAccountValid_) +
348         ", isSyncSwitchOpen: " + std::to_string(isSyncSwitchOn_));
349     if ((sceneCode_ == UPGRADE_RESTORE_ID || dualDeviceSoftName_.empty()
350         || dualDeviceSoftName_.find("4", dualDeviceSoftName_.find(" ")) == dualDeviceSoftName_.find(" ") + 1)
351         && (highlightCloudMediaCnt == 0 || IsCloudRestoreSatisfied())) {
352         MEDIA_INFO_LOG("start to restore highlight albums");
353         highlightRestore_.RestoreAlbums(albumOdid_);
354     }
355 }
356 
RestorePhotoInner()357 void UpgradeRestore::RestorePhotoInner()
358 {
359     std::string dbIntegrityCheck = CheckGalleryDbIntegrity();
360     if (dbIntegrityCheck == DB_INTEGRITY_CHECK) {
361         MEDIA_INFO_LOG("the isAccountValid is %{public}d, sync switch open is %{public}d", isAccountValid_,
362             isSyncSwitchOn_);
363         // upgrade gallery.db
364         DataTransfer::GalleryDbUpgrade().OnUpgrade(this->galleryRdb_);
365         AnalyzeGallerySource();
366         InitGarbageAlbum();
367         // restore PhotoAlbum
368         this->photoAlbumRestore_.Restore();
369         RestoreFromGalleryPortraitAlbum();
370         geoKnowledgeRestore_.RestoreGeoKnowledgeInfos();
371         RestoreHighlightAlbums();
372         // restore Photos
373         RestoreFromGallery();
374         if (IsCloudRestoreSatisfied()) {
375             MEDIA_INFO_LOG("here cloud clone");
376             RestoreCloudFromGallery();
377             MEDIA_INFO_LOG("Migrate LCD:%{public}" PRIu64 ",THM:%{public}" PRIu64
378             ",Rotate LCD:%{public}" PRIu64 ",THM: %{public}" PRIu64 ", migrateCloud: %{public}" PRIu64
379             ", migrateDatabase: %{public}" PRIu64,
380             (cloudLcdCount_.load(std::memory_order_relaxed) + localLcdCount_.load(std::memory_order_relaxed)),
381             (cloudThumbnailCount_.load(std::memory_order_relaxed) +
382             localThumbnailCount_.load(std::memory_order_relaxed)),
383             rotateLcdMigrateFileNumber_.load(), rotateThmMigrateFileNumber_.load(),
384             totalCloudMetaNumber_.load(), migrateDatabaseNumber_.load());
385         }
386     } else {
387         maxId_ = 0;
388         SetErrorCode(RestoreError::GALLERY_DATABASE_CORRUPTION);
389         ErrorInfo errorInfo(RestoreError::GALLERY_DATABASE_CORRUPTION, 0, "", dbIntegrityCheck);
390         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
391     }
392 }
393 
RestorePhoto()394 void UpgradeRestore::RestorePhoto()
395 {
396     if (!IsRestorePhoto()) {
397         return;
398     }
399     AnalyzeSource();
400     RestorePhotoInner();
401     StopParameterForClone(sceneCode_);
402     MEDIA_INFO_LOG("migrate from gallery number: %{public}lld, file number: %{public}lld",
403         (long long) migrateDatabaseNumber_, (long long) migrateFileNumber_);
404     if (sceneCode_ == UPGRADE_RESTORE_ID) {
405         RestoreFromExternal(true);
406         MEDIA_INFO_LOG("migrate from camera number: %{public}lld, file number: %{public}lld",
407             (long long) migrateDatabaseNumber_, (long long) migrateFileNumber_);
408         RestoreFromExternal(false);
409         MEDIA_INFO_LOG("migrate from others number: %{public}lld, file number: %{public}lld",
410             (long long) migrateDatabaseNumber_, (long long) migrateFileNumber_);
411     }
412 
413     if (sceneCode_ == UPGRADE_RESTORE_ID) {
414         UpdateFaceAnalysisStatus();
415     } else {
416         UpdateDualCloneFaceAnalysisStatus();
417     }
418 
419     geoKnowledgeRestore_.ReportGeoRestoreTask();
420     highlightRestore_.UpdateAlbums();
421     ReportPortraitStat(sceneCode_);
422 
423     int32_t restoreMode = BaseRestore::GetRestoreMode();
424     UpgradeRestoreTaskReport()
425         .SetSceneCode(sceneCode_)
426         .SetTaskId(taskId_)
427         .ReportRestoreMode(restoreMode, BaseRestore::GetNotFoundNumber());
428     if (restoreMode == RESTORE_MODE_PROC_ALL_DATA || restoreMode == RESTORE_MODE_PROC_TWIN_DATA) {
429         (void)NativeRdb::RdbHelper::DeleteRdbStore(galleryDbPath_);
430     } else {
431         MEDIA_INFO_LOG("restore mode no need to del gallery db");
432     }
433     PrcoessBurstPhotos();
434 }
435 
AnalyzeSource()436 void UpgradeRestore::AnalyzeSource()
437 {
438     MEDIA_INFO_LOG("start AnalyzeSource.");
439     DatabaseReport()
440         .SetSceneCode(this->sceneCode_)
441         .SetTaskId(this->taskId_)
442         .ReportExternal(this->externalRdb_,  this->galleryRdb_)
443         .ReportMedia(this->mediaLibraryRdb_, DatabaseReport::PERIOD_BEFORE);
444     MEDIA_INFO_LOG("end AnalyzeSource.");
445 }
446 
AnalyzeGalleryErrorSource()447 void UpgradeRestore::AnalyzeGalleryErrorSource()
448 {
449     if (galleryRdb_ == nullptr) {
450         MEDIA_ERR_LOG("galleryRdb_ is nullptr, Maybe init failed.");
451         return;
452     }
453     AnalyzeGalleryDuplicateData();
454 }
455 
AnalyzeGalleryDuplicateData()456 void UpgradeRestore::AnalyzeGalleryDuplicateData()
457 {
458     int32_t count = 0;
459     int32_t total = 0;
460     BackupDatabaseUtils::QueryGalleryDuplicateDataCount(galleryRdb_, count, total);
461     MEDIA_INFO_LOG("Duplicate data count: %{public}d, total: %{public}d", count, total);
462     this->photosRestore_.GetDuplicateData(count);
463 }
464 
AnalyzeGallerySource()465 void UpgradeRestore::AnalyzeGallerySource()
466 {
467     MEDIA_INFO_LOG("start AnalyzeGallerySource.");
468     AnalyzeGalleryErrorSource();
469     DatabaseReport()
470         .SetSceneCode(this->sceneCode_)
471         .SetTaskId(this->taskId_)
472         .ReportGallery(this->galleryRdb_, this->shouldIncludeSd_);
473     MEDIA_INFO_LOG("end AnalyzeGallerySource.");
474 }
475 
InitGarbageAlbum()476 void UpgradeRestore::InitGarbageAlbum()
477 {
478     BackupDatabaseUtils::InitGarbageAlbum(galleryRdb_, cacheSet_, nickMap_);
479 }
480 
RestoreFromGallery()481 void UpgradeRestore::RestoreFromGallery()
482 {
483     this->photosRestore_.LoadPhotoAlbums();
484     HasLowQualityImage();
485     // local count
486     int32_t totalNumber = this->photosRestore_.GetGalleryMediaCount(this->shouldIncludeSd_, this->hasLowQualityImage_);
487     MEDIA_INFO_LOG("local totalNumber = %{public}d", totalNumber);
488     totalNumber_ += static_cast<uint64_t>(totalNumber);
489     MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
490     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
491     needReportFailed_ = false;
492     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
493         ffrt::submit([this, offset]() { RestoreBatch(offset); }, { &offset }, {},
494             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
495     }
496     ffrt::wait();
497     size_t vectorLen = galleryFailedOffsets.size();
498     needReportFailed_ = true;
499     for (size_t offset = 0; offset < vectorLen; offset++) {
500         RestoreBatch(galleryFailedOffsets[offset]);
501     }
502 }
503 
RestoreCloudFromGallery()504 void UpgradeRestore::RestoreCloudFromGallery()
505 {
506     MEDIA_INFO_LOG("RestoreCloudFromGallery");
507     this->photosRestore_.LoadPhotoAlbums();
508     // cloud count
509     int32_t cloudMetaCount = this->photosRestore_.GetCloudMetaCount(this->shouldIncludeSd_, false);
510     MEDIA_INFO_LOG("the cloud count is %{public}d", cloudMetaCount);
511     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
512     needReportFailed_ = false;
513     totalNumber_ += static_cast<uint64_t>(cloudMetaCount);
514     for (int32_t offset = 0; offset < cloudMetaCount; offset += RESTORE_CLOUD_QUERY_COUNT) {
515         ffrt::submit([this, offset]() { RestoreBatchForCloud(offset); }, { &offset }, {},
516             ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
517     }
518     ffrt::wait();
519     size_t vectorLen = galleryFailedOffsets.size();
520     needReportFailed_ = true;
521     for (size_t offset = 0; offset < vectorLen; offset++) {
522         RestoreBatchForCloud(galleryFailedOffsets[offset]);
523     }
524 }
525 
RestoreBatchForCloud(int32_t offset)526 void UpgradeRestore::RestoreBatchForCloud(int32_t offset)
527 {
528     std::vector<FileInfo> infos = QueryCloudFileInfos(offset);
529     MEDIA_INFO_LOG("the infos size is %{public}zu", infos.size());
530     if (InsertCloudPhoto(sceneCode_, infos, SourceType::GALLERY) != E_OK) {
531         galleryFailedOffsets.push_back(offset);
532     }
533     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(infos);
534     BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
535 }
536 
RestoreBatch(int32_t offset)537 void UpgradeRestore::RestoreBatch(int32_t offset)
538 {
539     MEDIA_INFO_LOG("start restore from gallery, offset: %{public}d", offset);
540     std::vector<FileInfo> infos = QueryFileInfos(offset);
541     if (InsertPhoto(sceneCode_, infos, SourceType::GALLERY) != E_OK) {
542         galleryFailedOffsets.push_back(offset);
543     }
544     auto fileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(infos);
545     BackupDatabaseUtils::UpdateAnalysisTotalTblStatus(mediaLibraryRdb_, fileIdPairs);
546 }
547 
RestoreFromExternal(bool isCamera)548 void UpgradeRestore::RestoreFromExternal(bool isCamera)
549 {
550     MEDIA_INFO_LOG("start restore from %{public}s", (isCamera ? "camera" : "others"));
551     int32_t maxId = BackupDatabaseUtils::QueryInt(galleryRdb_, isCamera ?
552         QUERY_MAX_ID_CAMERA_SCREENSHOT : QUERY_MAX_ID_OTHERS, CUSTOM_MAX_ID);
553     maxId = (maxId_ == -1) ? maxId : maxId_;
554     int32_t type = isCamera ? SourceType::EXTERNAL_CAMERA : SourceType::EXTERNAL_OTHERS;
555     int32_t totalNumber = QueryNotSyncTotalNumber(maxId, isCamera);
556     MEDIA_INFO_LOG("totalNumber = %{public}d, maxId = %{public}d", totalNumber, maxId);
557     totalNumber_ += static_cast<uint64_t>(totalNumber);
558     MEDIA_INFO_LOG("onProcess Update totalNumber_: %{public}lld", (long long)totalNumber_);
559     ffrt_set_cpu_worker_max_num(ffrt::qos_utility, MAX_THREAD_NUM);
560     needReportFailed_ = false;
561     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
562         ffrt::submit([this, offset, maxId, isCamera, type]() {
563                 RestoreExternalBatch(offset, maxId, isCamera, type);
564             }, { &offset }, {}, ffrt::task_attr().qos(static_cast<int32_t>(ffrt::qos_utility)));
565     }
566     ffrt::wait();
567     size_t vectorLen = externalFailedOffsets.size();
568     needReportFailed_ = true;
569     for (size_t offset = 0; offset < vectorLen; offset++) {
570         RestoreExternalBatch(externalFailedOffsets[offset], maxId, isCamera, type);
571     }
572 }
573 
RestoreExternalBatch(int32_t offset,int32_t maxId,bool isCamera,int32_t type)574 void UpgradeRestore::RestoreExternalBatch(int32_t offset, int32_t maxId, bool isCamera, int32_t type)
575 {
576     MEDIA_INFO_LOG("start restore from external, offset: %{public}d", offset);
577     std::vector<FileInfo> infos = QueryFileInfosFromExternal(offset, maxId, isCamera);
578     if (InsertPhoto(sceneCode_, infos, type) != E_OK) {
579         externalFailedOffsets.push_back(offset);
580     }
581 }
582 
QueryNotSyncTotalNumber(int32_t maxId,bool isCamera)583 int32_t UpgradeRestore::QueryNotSyncTotalNumber(int32_t maxId, bool isCamera)
584 {
585     std::string queryCamera = isCamera ? IN_CAMERA : NOT_IN_CAMERA;
586     std::string queryNotSyncByCount = QUERY_COUNT_FROM_FILES + queryCamera + " AND " +
587         COMPARE_ID + std::to_string(maxId) + " AND " + QUERY_NOT_SYNC;
588     return BackupDatabaseUtils::QueryInt(externalRdb_, queryNotSyncByCount, CUSTOM_COUNT);
589 }
590 
HandleRestData(void)591 void UpgradeRestore::HandleRestData(void)
592 {
593     MEDIA_INFO_LOG("Start to handle rest data in native.");
594     RestoreThumbnail();
595 
596     int32_t restoreMode = BaseRestore::GetRestoreMode();
597     if (restoreMode != RESTORE_MODE_PROC_ALL_DATA && restoreMode != RESTORE_MODE_PROC_TWIN_DATA) {
598         MEDIA_DEBUG_LOG("restore mode no need to del rest data");
599         return;
600     }
601 
602     std::string photoData = appDataPath_ + "/" + galleryAppName_;
603     std::string mediaData = appDataPath_ + "/" + mediaAppName_;
604     if (MediaFileUtils::IsFileExists(photoData)) {
605         MEDIA_DEBUG_LOG("Start to delete photo data.");
606         (void)MediaFileUtils::DeleteDir(photoData);
607     }
608     if (MediaFileUtils::IsFileExists(mediaData)) {
609         MEDIA_DEBUG_LOG("Start to delete media data.");
610         (void)MediaFileUtils::DeleteDir(mediaData);
611     }
612     BackupFileUtils::DeleteSdDatabase(filePath_);
613 }
614 
QueryFileInfos(int32_t offset)615 std::vector<FileInfo> UpgradeRestore::QueryFileInfos(int32_t offset)
616 {
617     std::vector<FileInfo> result;
618     result.reserve(QUERY_COUNT);
619     CHECK_AND_RETURN_RET_LOG(galleryRdb_ != nullptr, result, "galleryRdb_ is nullptr, Maybe init failed.");
620     auto resultSet = this->photosRestore_.GetGalleryMedia(
621         offset, QUERY_COUNT, this->shouldIncludeSd_, this->hasLowQualityImage_);
622     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
623     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
624         FileInfo tmpInfo;
625         if (ParseResultSetFromGallery(resultSet, tmpInfo)) {
626             result.emplace_back(tmpInfo);
627         }
628     }
629     return result;
630 }
631 
QueryCloudFileInfos(int32_t offset)632 std::vector<FileInfo> UpgradeRestore::QueryCloudFileInfos(int32_t offset)
633 {
634     std::vector<FileInfo> result;
635     result.reserve(RESTORE_CLOUD_QUERY_COUNT);
636     CHECK_AND_RETURN_RET_LOG(galleryRdb_ != nullptr, result, "cloud galleryRdb_ is nullptr, Maybe init failed.");
637     auto resultSet = this->photosRestore_.GetCloudGalleryMedia(
638         offset, RESTORE_CLOUD_QUERY_COUNT, this->shouldIncludeSd_, this->hasLowQualityImage_);
639     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query cloud resultSql is null.");
640     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
641         FileInfo tmpInfo;
642         if (ParseResultSetFromGallery(resultSet, tmpInfo)) {
643             result.emplace_back(tmpInfo);
644         }
645     }
646     return result;
647 }
648 
ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)649 bool UpgradeRestore::ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
650 {
651     info.oldPath = GetStringVal(EXTERNAL_FILE_DATA, resultSet);
652     int32_t mediaType = GetInt32Val(EXTERNAL_MEDIA_TYPE, resultSet);
653     CHECK_AND_RETURN_RET_LOG(mediaType == DUAL_MEDIA_TYPE::AUDIO_TYPE, false,
654         "Invalid media type: %{public}d, path: %{public}s", mediaType,
655         BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
656     info.fileType = MediaType::MEDIA_TYPE_AUDIO;
657     CHECK_AND_RETURN_RET_LOG(BaseRestore::ConvertPathToRealPath(info.oldPath, filePath_, info.filePath,
658         info.relativePath), false, "Invalid path: %{public}s.",
659         BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
660     info.displayName = GetStringVal(EXTERNAL_DISPLAY_NAME, resultSet);
661     info.title = GetStringVal(EXTERNAL_TITLE, resultSet);
662     info.fileSize = GetInt64Val(EXTERNAL_FILE_SIZE, resultSet);
663     CHECK_AND_WARN_LOG(info.fileSize >= GARBAGE_PHOTO_SIZE, "maybe garbage path = %{public}s.",
664         BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str());
665     info.duration = GetInt64Val(GALLERY_DURATION, resultSet);
666     info.isFavorite = GetInt32Val(EXTERNAL_IS_FAVORITE, resultSet);
667     info.dateModified = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet) * MSEC_TO_SEC;
668     return true;
669 }
670 
QueryFileInfosFromExternal(int32_t offset,int32_t maxId,bool isCamera)671 std::vector<FileInfo> UpgradeRestore::QueryFileInfosFromExternal(int32_t offset, int32_t maxId, bool isCamera)
672 {
673     std::vector<FileInfo> result;
674     result.reserve(QUERY_COUNT);
675     CHECK_AND_RETURN_RET_LOG(externalRdb_ != nullptr, result, "Pointer rdb_ is nullptr, Maybe init failed.");
676     std::string queryCamera = isCamera ? IN_CAMERA : NOT_IN_CAMERA;
677     std::string queryFilesByCount = QUERY_FILE_COLUMN + queryCamera + " AND " +
678         COMPARE_ID + std::to_string(maxId) + " AND " + QUERY_NOT_SYNC + " limit " + std::to_string(offset) + ", " +
679         std::to_string(QUERY_COUNT);
680     auto resultSet = externalRdb_->QuerySql(queryFilesByCount);
681     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
682     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
683         FileInfo tmpInfo;
684         if (ParseResultSetFromExternal(resultSet, tmpInfo)) {
685             std::string findPath = tmpInfo.relativePath;
686             bool isValid = IsValidDir(findPath);
687             if (isValid) {
688                 result.emplace_back(tmpInfo);
689             }
690         }
691     }
692     return result;
693 }
694 
IsValidDir(const string & path)695 bool UpgradeRestore::IsValidDir(const string &path)
696 {
697     bool isValid = true;
698     for (auto &cacheDir : cacheSet_) {
699         if (path.find(cacheDir) == 0) {
700             isValid = false;
701             break;
702         }
703     }
704     return isValid;
705 }
ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,string dbName)706 bool UpgradeRestore::ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
707     string dbName)
708 {
709     // only parse image and video
710     CHECK_AND_RETURN_RET(IsBasicInfoValid(resultSet, info, dbName), false);
711     info.title = GetStringVal(GALLERY_TITLE, resultSet);
712     info.userComment = GetStringVal(GALLERY_DESCRIPTION, resultSet);
713     info.duration = GetInt64Val(GALLERY_DURATION, resultSet);
714     info.isFavorite = GetInt32Val(GALLERY_IS_FAVORITE, resultSet);
715     info.specialFileType = GetInt32Val(GALLERY_SPECIAL_FILE_TYPE, resultSet);
716     // only local data need livePhoto path
717     if (info.localMediaId != -1 && BackupFileUtils::IsLivePhoto(info) &&
718         !BackupFileUtils::ConvertToMovingPhoto(info)) {
719         ErrorInfo errorInfo(RestoreError::MOVING_PHOTO_CONVERT_FAILED, 1, "",
720             BackupLogUtils::FileInfoToString(sceneCode_, info));
721         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
722         return false;
723     }
724     info.height = GetInt64Val(GALLERY_HEIGHT, resultSet);
725     info.width = GetInt64Val(GALLERY_WIDTH, resultSet);
726     info.resolution = GetStringVal(GALLERY_RESOLUTION, resultSet);
727     // For cloud data, prioritize using resolution parsing to obtain the width and height.
728     // If parsing fails, set both width and height to 0
729     if (info.localMediaId == -1) {
730         BackupFileUtils::ParseResolution(info.resolution, info.width, info.height);
731     }
732     info.orientation = GetInt64Val(GALLERY_ORIENTATION, resultSet);
733     info.dateModified = GetInt64Val(EXTERNAL_DATE_MODIFIED, resultSet) * MSEC_TO_SEC;
734     info.firstUpdateTime = GetInt64Val(GALLERY_FIRST_UPDATE_TIME, resultSet);
735     info.dateTaken = GetInt64Val(GALLERY_DATE_TAKEN, resultSet);
736     info.detailTime = GetStringVal(GALLERY_DETAIL_TIME, resultSet);
737     info.userId = BackupFileUtils::GetUserId(info.oldPath);
738     return true;
739 }
740 
ParseResultSetFromGallery(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info)741 bool UpgradeRestore::ParseResultSetFromGallery(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info)
742 {
743     info.localMediaId = GetInt32Val(GALLERY_LOCAL_MEDIA_ID, resultSet);
744     info.hidden = (info.localMediaId == GALLERY_HIDDEN_ID) ? 1 : 0;
745     info.recycledTime = GetInt64Val(GALLERY_RECYCLED_TIME, resultSet);
746     info.showDateToken = GetInt64Val(GALLERY_SHOW_DATE_TOKEN, resultSet);
747     // fetch relative_bucket_id, recycleFlag, is_hw_burst, hash field to generate burst_key
748     info.relativeBucketId = GetStringVal(GALLERY_MEDIA_BUCKET_ID, resultSet);
749     info.recycleFlag = GetInt32Val(GALLERY_RECYCLE_FLAG, resultSet);
750     info.isBurst = GetInt32Val(GALLERY_IS_BURST, resultSet);
751     info.hashCode = GetStringVal(GALLERY_HASH, resultSet);
752     info.fileIdOld = GetInt32Val(GALLERY_ID, resultSet);
753     info.photoQuality = GetInt32Val(PhotoColumn::PHOTO_QUALITY, resultSet);
754     info.thumbType = GetInt32Val(GALLERY_THUMB_TYPE, resultSet);
755     info.filePath = GetStringVal(GALLERY_FILE_DATA, resultSet);
756     info.albumId = GetStringVal(GALLERY_ALBUM_ID, resultSet);
757     info.orientation = GetInt32Val(GALLERY_ORIENTATION, resultSet);
758     info.uniqueId = GetStringVal(GALLERY_UNIQUE_ID, resultSet);
759     info.localThumbPath = GetStringVal(GALLERY_LOCAL_THUMB_PATH_ID, resultSet);
760     info.localBigThumbPath = GetStringVal(GALLERY_LOCAL_BIG_THUMB_PATH_ID, resultSet);
761 
762     bool isSuccess = ParseResultSet(resultSet, info, GALLERY_DB_NAME);
763     CHECK_AND_RETURN_RET_LOG(isSuccess, isSuccess, "ParseResultSetFromGallery fail");
764     info.burstKey = burstKeyGenerator_.FindBurstKey(info);
765     // Pre-Fetch: sourcePath, lPath
766     info.sourcePath = GetStringVal(GALLERY_MEDIA_SOURCE_PATH, resultSet);
767     info.lPath = GetStringVal(GALLERY_ALBUM_IPATH, resultSet);
768     // Find lPath, bundleName, packageName by sourcePath, lPath
769     info.lPath = this->photosRestore_.FindlPath(info);
770     info.bundleName = this->photosRestore_.FindBundleName(info);
771     info.packageName = this->photosRestore_.FindPackageName(info);
772     info.photoQuality = this->photosRestore_.FindPhotoQuality(info);
773     info.latitude = GetDoubleVal("latitude", resultSet);
774     info.longitude = GetDoubleVal("longitude", resultSet);
775     info.storyIds = GetStringVal("story_id", resultSet);
776     info.portraitIds = GetStringVal("portrait_id", resultSet);
777     info.storyChosen = GetInt32Val("story_chosen", resultSet);
778     return isSuccess;
779 }
780 
ParseResultSetFromExternal(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,int mediaType)781 bool UpgradeRestore::ParseResultSetFromExternal(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
782     int mediaType)
783 {
784     bool isSuccess;
785     if (mediaType == DUAL_MEDIA_TYPE::AUDIO_TYPE) {
786         isSuccess = ParseResultSetForAudio(resultSet, info);
787     } else {
788         isSuccess = ParseResultSet(resultSet, info, EXTERNAL_DB_NAME);
789     }
790     CHECK_AND_RETURN_RET_LOG(isSuccess, isSuccess, "ParseResultSetFromExternal fail");
791     info.showDateToken = GetInt64Val(EXTERNAL_DATE_TAKEN, resultSet);
792     info.dateTaken = GetInt64Val(EXTERNAL_DATE_TAKEN, resultSet);
793     info.sourcePath = GetStringVal(EXTERNAL_FILE_DATA, resultSet);
794     info.localMediaId = GetInt32Val(EXTERNAL_FILE_ID, resultSet);
795     return isSuccess;
796 }
797 
GetInsertValue(const FileInfo & fileInfo,const std::string & newPath,int32_t sourceType)798 NativeRdb::ValuesBucket UpgradeRestore::GetInsertValue(const FileInfo &fileInfo, const std::string &newPath,
799     int32_t sourceType)
800 {
801     NativeRdb::ValuesBucket values;
802     values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
803     values.PutString(MediaColumn::MEDIA_TITLE, fileInfo.title);
804     values.PutString(MediaColumn::MEDIA_NAME, fileInfo.displayName);
805     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(fileInfo.displayName));
806     values.PutInt(MediaColumn::MEDIA_TYPE, fileInfo.fileType);
807     if (fileInfo.firstUpdateTime != 0) {
808         values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.firstUpdateTime);
809     } else if (fileInfo.dateTaken != 0) {
810         values.PutLong(MediaColumn::MEDIA_DATE_ADDED, fileInfo.dateTaken);
811     }
812     if (fileInfo.dateTaken != 0) {
813         values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, fileInfo.dateTaken);
814     }
815     values.PutString(PhotoColumn::PHOTO_DETAIL_TIME, fileInfo.detailTime);
816     values.PutLong(MediaColumn::MEDIA_DURATION, fileInfo.duration);
817     values.PutInt(MediaColumn::MEDIA_IS_FAV, fileInfo.isFavorite);
818     if (fileInfo.isFavorite != 0) {
819         string fileName = fileInfo.displayName;
820         MEDIA_WARN_LOG("the file :%{public}s is favorite.", BackupFileUtils::GarbleFileName(fileName).c_str());
821     }
822     values.PutLong(MediaColumn::MEDIA_DATE_TRASHED, this->photosRestore_.FindDateTrashed(fileInfo));
823     values.PutInt(MediaColumn::MEDIA_HIDDEN, fileInfo.hidden);
824     if (fileInfo.hidden != 0) {
825         string fileName = fileInfo.displayName;
826         MEDIA_WARN_LOG("the file :%{public}s is hidden.", BackupFileUtils::GarbleFileName(fileName).c_str());
827     }
828     values.PutInt(PhotoColumn::PHOTO_HEIGHT, fileInfo.height);
829     values.PutInt(PhotoColumn::PHOTO_WIDTH, fileInfo.width);
830     values.PutString(PhotoColumn::PHOTO_USER_COMMENT, fileInfo.userComment);
831     values.PutInt(PhotoColumn::PHOTO_ORIENTATION, fileInfo.orientation);
832     std::string package_name = fileInfo.packageName;
833     if (package_name != "") {
834         values.PutString(PhotoColumn::MEDIA_PACKAGE_NAME, package_name);
835     }
836     values.PutInt(PhotoColumn::PHOTO_QUALITY, fileInfo.photoQuality);
837     values.PutInt(PhotoColumn::PHOTO_SUBTYPE, this->photosRestore_.FindSubtype(fileInfo));
838     values.PutInt(PhotoColumn::PHOTO_BURST_COVER_LEVEL, this->photosRestore_.FindBurstCoverLevel(fileInfo));
839     values.PutString(PhotoColumn::PHOTO_BURST_KEY, this->photosRestore_.FindBurstKey(fileInfo));
840     // find album_id by lPath.
841     values.PutInt(PhotoColumn::PHOTO_OWNER_ALBUM_ID, this->photosRestore_.FindAlbumId(fileInfo));
842     // fill the source_path at last.
843     values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, this->photosRestore_.FindSourcePath(fileInfo));
844     values.PutInt(PhotoColumn::PHOTO_STRONG_ASSOCIATION, this->photosRestore_.FindStrongAssociation(fileInfo));
845     values.PutInt(PhotoColumn::PHOTO_CE_AVAILABLE, this->photosRestore_.FindCeAvailable(fileInfo));
846     // set invisible for local & cloud
847     values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_BACKUP));
848     // for cloud clone
849     if (fileInfo.localMediaId == -1) {
850         values.PutString(PhotoColumn::PHOTO_CLOUD_ID, fileInfo.uniqueId);
851         values.PutInt(PhotoColumn::PHOTO_POSITION, PHOTO_CLOUD_POSITION);
852         values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_SYNCED));
853     } else {
854         values.PutInt(PhotoColumn::PHOTO_DIRTY, this->photosRestore_.FindDirty(fileInfo));
855     }
856     return values;
857 }
858 
ConvertPathToRealPath(const std::string & srcPath,const std::string & prefix,std::string & newPath,std::string & relativePath)859 bool UpgradeRestore::ConvertPathToRealPath(const std::string &srcPath, const std::string &prefix,
860     std::string &newPath, std::string &relativePath)
861 {
862     size_t pos = 0;
863     CHECK_AND_RETURN_RET(BackupFileUtils::GetPathPosByPrefixLevel(sceneCode_, srcPath,
864         INTERNAL_PREFIX_LEVEL, pos), false);
865     newPath = prefix + srcPath;
866     relativePath = srcPath.substr(pos);
867     return true;
868 }
869 
ConvertPathToRealPath(const std::string & srcPath,const std::string & prefix,std::string & newPath,std::string & relativePath,FileInfo & fileInfo)870 bool UpgradeRestore::ConvertPathToRealPath(const std::string &srcPath, const std::string &prefix,
871     std::string &newPath, std::string &relativePath, FileInfo &fileInfo)
872 {
873     if (MediaFileUtils::StartsWith(srcPath, INTERNAL_PREFIX)) {
874         return ConvertPathToRealPath(srcPath, prefix, newPath, relativePath);
875     }
876     size_t pos = 0;
877     if (!BackupFileUtils::GetPathPosByPrefixLevel(sceneCode_, srcPath, SD_PREFIX_LEVEL, pos)) {
878         return false;
879     }
880     relativePath = srcPath.substr(pos);
881     if (fileInfo.fileSize < TAR_FILE_LIMIT || fileInfo.localMediaId == GALLERY_HIDDEN_ID ||
882         fileInfo.localMediaId == GALLERY_TRASHED_ID) {
883         newPath = prefix + srcPath; // packed as tar, hidden or trashed, use path in DB
884     } else {
885         newPath = prefix + relativePath; // others, remove sd prefix, use relative path
886     }
887     fileInfo.isInternal = false;
888     return true;
889 }
890 
891 /**
892  * @brief Update the FileInfo if it has a copy in system.
893  */
HasSameFileForDualClone(FileInfo & fileInfo)894 bool UpgradeRestore::HasSameFileForDualClone(FileInfo &fileInfo)
895 {
896     PhotosDao::PhotosRowData rowData = this->photosRestore_.FindSameFile(fileInfo);
897     int32_t fileId = rowData.fileId;
898     std::string cloudPath = rowData.data;
899     if (fileId <= 0 || cloudPath.empty()) {
900         return false;
901     }
902     // Meed extra check to determine whether or not to drop the duplicate file.
903     return ExtraCheckForCloneSameFile(fileInfo, rowData);
904 }
905 
RestoreFromGalleryPortraitAlbum()906 void UpgradeRestore::RestoreFromGalleryPortraitAlbum()
907 {
908     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
909     int32_t totalNumber = QueryPortraitAlbumTotalNumber();
910     MEDIA_INFO_LOG("QueryPortraitAlbumTotalNumber, totalNumber = %{public}d", totalNumber);
911 
912     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
913         std::vector<std::string> tagNameToDeleteSelection;
914         std::vector<std::string> tagIds;
915         vector<PortraitAlbumInfo> portraitAlbumInfos = QueryPortraitAlbumInfos(offset,
916             tagNameToDeleteSelection);
917         CHECK_AND_RETURN_LOG(BackupDatabaseUtils::DeleteDuplicatePortraitAlbum(tagNameToDeleteSelection,
918             tagIds, mediaLibraryRdb_), "Batch delete duplicate portrait album failed.");
919         InsertPortraitAlbum(portraitAlbumInfos);
920     }
921 
922     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
923     migratePortraitTotalTimeCost_ += end - start;
924 }
925 
QueryPortraitAlbumTotalNumber()926 int32_t UpgradeRestore::QueryPortraitAlbumTotalNumber()
927 {
928     return BackupDatabaseUtils::QueryInt(galleryRdb_,
929         (IsCloudRestoreSatisfied() ?
930         QUERY_GALLERY_PORTRAIT_ALBUM_WITH_CLOUD_COUNT : QUERY_GALLERY_PORTRAIT_ALBUM_COUNT), CUSTOM_COUNT);
931 }
932 
QueryPortraitAlbumInfos(int32_t offset,std::vector<std::string> & tagNameToDeleteSelection)933 vector<PortraitAlbumInfo> UpgradeRestore::QueryPortraitAlbumInfos(int32_t offset,
934     std::vector<std::string>& tagNameToDeleteSelection)
935 {
936     vector<PortraitAlbumInfo> result;
937     result.reserve(QUERY_COUNT);
938 
939     std::string querySql = "SELECT " + GALLERY_MERGE_TAG_TAG_ID + ", " + GALLERY_GROUP_TAG + ", " +
940         GALLERY_TAG_NAME + ", " + GALLERY_USER_OPERATION + ", " + GALLERY_RENAME_OPERATION +
941         " FROM " + (IsCloudRestoreSatisfied() ?
942         GALLERY_PORTRAIT_ALBUM_TABLE_WITH_CLOUD : GALLERY_PORTRAIT_ALBUM_TABLE);
943     querySql += " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
944 
945     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
946     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
947     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
948         PortraitAlbumInfo portraitAlbumInfo;
949         if (!ParsePortraitAlbumResultSet(resultSet, portraitAlbumInfo)) {
950             MEDIA_ERR_LOG("Parse portrait album result set failed, exclude %{public}s",
951                 portraitAlbumInfo.tagName.c_str());
952             continue;
953         }
954         if (!SetAttributes(portraitAlbumInfo)) {
955             MEDIA_ERR_LOG("Set attributes failed, exclude %{public}s", portraitAlbumInfo.tagName.c_str());
956             continue;
957         }
958         if (!portraitAlbumInfo.tagName.empty()) {
959             tagNameToDeleteSelection.emplace_back(portraitAlbumInfo.tagName);
960         }
961 
962         result.emplace_back(portraitAlbumInfo);
963     }
964     return result;
965 }
966 
ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,PortraitAlbumInfo & portraitAlbumInfo)967 bool UpgradeRestore::ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
968     PortraitAlbumInfo &portraitAlbumInfo)
969 {
970     portraitAlbumInfo.tagIdOld = GetStringVal(GALLERY_MERGE_TAG_TAG_ID, resultSet);
971     portraitAlbumInfo.groupTagOld = GetStringVal(GALLERY_GROUP_TAG, resultSet);
972     portraitAlbumInfo.tagName = GetStringVal(GALLERY_TAG_NAME, resultSet);
973     portraitAlbumInfo.userOperation = GetInt32Val(GALLERY_USER_OPERATION, resultSet);
974     portraitAlbumInfo.renameOperation = GetInt32Val(GALLERY_RENAME_OPERATION, resultSet);
975     return true;
976 }
977 
SetAttributes(PortraitAlbumInfo & portraitAlbumInfo)978 bool UpgradeRestore::SetAttributes(PortraitAlbumInfo &portraitAlbumInfo)
979 {
980     return BackupDatabaseUtils::SetTagIdNew(portraitAlbumInfo, tagIdMap_);
981 }
982 
InsertPortraitAlbum(std::vector<PortraitAlbumInfo> & portraitAlbumInfos)983 void UpgradeRestore::InsertPortraitAlbum(std::vector<PortraitAlbumInfo> &portraitAlbumInfos)
984 {
985     CHECK_AND_RETURN_LOG(mediaLibraryRdb_ != nullptr, "mediaLibraryRdb_ is null");
986     CHECK_AND_RETURN_LOG(!portraitAlbumInfos.empty(), "portraitAlbumInfos are empty");
987 
988     int64_t startInsertAlbum = MediaFileUtils::UTCTimeMilliSeconds();
989     int32_t albumRowNum = InsertPortraitAlbumByTable(portraitAlbumInfos, true);
990     if (albumRowNum <= 0) {
991         BackupDatabaseUtils::PrintErrorLog("Insert portrait album failed", startInsertAlbum);
992         return;
993     }
994 
995     int64_t startInsertTag = MediaFileUtils::UTCTimeMilliSeconds();
996     int32_t tagRowNum = InsertPortraitAlbumByTable(portraitAlbumInfos, false);
997     if (tagRowNum <= 0) {
998         BackupDatabaseUtils::PrintErrorLog("Insert face tag failed", startInsertTag);
999         return;
1000     }
1001 
1002     int64_t startQuery = MediaFileUtils::UTCTimeMilliSeconds();
1003     BatchQueryAlbum(portraitAlbumInfos);
1004     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1005     MEDIA_INFO_LOG("insert %{public}ld albums cost %{public}ld, %{public}ld tags cost %{public}ld, query cost "
1006         "%{public}ld.", (long)albumRowNum, (long)(startInsertTag - startInsertAlbum), (long)tagRowNum,
1007         (long)(startQuery - startInsertTag), (long)(end - startQuery));
1008 }
1009 
InsertPortraitAlbumByTable(std::vector<PortraitAlbumInfo> & portraitAlbumInfos,bool isAlbum)1010 int32_t UpgradeRestore::InsertPortraitAlbumByTable(std::vector<PortraitAlbumInfo> &portraitAlbumInfos,
1011     bool isAlbum)
1012 {
1013     std::vector<NativeRdb::ValuesBucket> values = GetInsertValues(portraitAlbumInfos, isAlbum);
1014     int64_t rowNum = 0;
1015     std::string tableName = isAlbum ? ANALYSIS_ALBUM_TABLE : VISION_FACE_TAG_TABLE;
1016     int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
1017     CHECK_AND_RETURN_RET(errCode == E_OK, 0);
1018     return rowNum;
1019 }
1020 
GetInsertValues(std::vector<PortraitAlbumInfo> & portraitAlbumInfos,bool isAlbum)1021 std::vector<NativeRdb::ValuesBucket> UpgradeRestore::GetInsertValues(std::vector<PortraitAlbumInfo> &portraitAlbumInfos,
1022     bool isAlbum)
1023 {
1024     std::vector<NativeRdb::ValuesBucket> values;
1025     for (auto &portraitAlbumInfo : portraitAlbumInfos) {
1026         NativeRdb::ValuesBucket value = GetInsertValue(portraitAlbumInfo, isAlbum);
1027         values.emplace_back(value);
1028     }
1029     return values;
1030 }
1031 
GetInsertValue(const PortraitAlbumInfo & portraitAlbumInfo,bool isAlbum)1032 NativeRdb::ValuesBucket UpgradeRestore::GetInsertValue(const PortraitAlbumInfo &portraitAlbumInfo, bool isAlbum)
1033 {
1034     NativeRdb::ValuesBucket values;
1035     values.PutString(TAG_ID, portraitAlbumInfo.tagIdNew);
1036     values.PutInt(COUNT, 0);
1037     if (isAlbum) {
1038         values.PutString(ALBUM_NAME, portraitAlbumInfo.tagName);
1039         values.PutString(GROUP_TAG, portraitAlbumInfo.groupTagOld);
1040         values.PutInt(USER_OPERATION, portraitAlbumInfo.userOperation);
1041         values.PutInt(RENAME_OPERATION, RENAME_OPERATION_RENAMED);
1042         values.PutInt(ALBUM_TYPE, PhotoAlbumType::SMART);
1043         values.PutInt(ALBUM_SUBTYPE, PhotoAlbumSubType::PORTRAIT);
1044         values.PutInt(USER_DISPLAY_LEVEL, PortraitPages::FIRST_PAGE);
1045         values.PutInt(IS_LOCAL, IS_LOCAL_TRUE);
1046     } else {
1047         values.PutString(TAG_VERSION, E_VERSION); // updated by analysis service
1048     }
1049     return values;
1050 }
1051 
BatchQueryAlbum(std::vector<PortraitAlbumInfo> & portraitAlbumInfos)1052 void UpgradeRestore::BatchQueryAlbum(std::vector<PortraitAlbumInfo> &portraitAlbumInfos)
1053 {
1054     std::string tagIdSelection;
1055     for (auto &portraitAlbumInfo : portraitAlbumInfos) {
1056         BackupDatabaseUtils::UpdateSelection(tagIdSelection, portraitAlbumInfo.tagIdNew, true);
1057     }
1058     std::string querySql = "SELECT " + ALBUM_ID + ", " + TAG_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
1059         TAG_ID + " IN (" + tagIdSelection + ")";
1060     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaLibraryRdb_, querySql);
1061     CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr");
1062     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1063         int32_t albumId = GetInt32Val(ALBUM_ID, resultSet);
1064         std::string tagId = GetStringVal(TAG_ID, resultSet);
1065         if (albumId <= 0 || tagId.empty()) {
1066             continue;
1067         }
1068         portraitAlbumIdMap_[tagId] = albumId;
1069     }
1070 }
1071 
NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> & fileInfos,NeedQueryMap & needQueryMap)1072 bool UpgradeRestore::NeedBatchQueryPhotoForPortrait(const std::vector<FileInfo> &fileInfos, NeedQueryMap &needQueryMap)
1073 {
1074     if (portraitAlbumIdMap_.empty()) {
1075         return false;
1076     }
1077     std::string selection;
1078     for (const auto &fileInfo : fileInfos) {
1079         BackupDatabaseUtils::UpdateSelection(selection, std::to_string(fileInfo.fileIdOld), false);
1080     }
1081     std::unordered_set<std::string> needQuerySet;
1082     std::string querySql = "SELECT DISTINCT " + GALLERY_MERGE_FACE_HASH + " FROM " + GALLERY_FACE_TABLE_JOIN_TAG +
1083         " HAVING " + GALLERY_MEDIA_ID + " IN (" + selection + ") AND " + GALLERY_TAG_NAME_NOT_NULL_OR_EMPTY;
1084     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
1085     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "Query resultSql is null.");
1086     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1087         std::string hash = GetStringVal(GALLERY_MERGE_FACE_HASH, resultSet);
1088         if (hash.empty()) {
1089             continue;
1090         }
1091         needQuerySet.insert(hash);
1092     }
1093     CHECK_AND_RETURN_RET(!needQuerySet.empty(), false);
1094     needQueryMap[PhotoRelatedType::PORTRAIT] = needQuerySet;
1095     return true;
1096 }
1097 
InsertFaceAnalysisData(const std::vector<FileInfo> & fileInfos,const NeedQueryMap & needQueryMap,int64_t & faceRowNum,int64_t & mapRowNum,int64_t & photoNum)1098 void UpgradeRestore::InsertFaceAnalysisData(const std::vector<FileInfo> &fileInfos, const NeedQueryMap &needQueryMap,
1099     int64_t &faceRowNum, int64_t &mapRowNum, int64_t &photoNum)
1100 {
1101     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
1102     if (needQueryMap.count(PhotoRelatedType::PORTRAIT) == 0) {
1103         return;
1104     }
1105     bool cond = (mediaLibraryRdb_ == nullptr || fileInfos.empty());
1106     CHECK_AND_RETURN_LOG(!cond, "mediaLibraryRdb_ is null or fileInfos empty");
1107 
1108     std::string hashSelection;
1109     std::unordered_map<std::string, FileInfo> fileInfoMap;
1110     SetHashReference(fileInfos, needQueryMap, hashSelection, fileInfoMap);
1111 
1112     int32_t totalNumber = QueryFaceTotalNumber(hashSelection);
1113     MEDIA_INFO_LOG("Current %{public}zu / %{public}zu have %{public}d faces", fileInfoMap.size(), fileInfos.size(),
1114         totalNumber);
1115     std::unordered_set<std::string> excludedFiles;
1116     std::unordered_set<std::string> filesWithFace;
1117     auto uniqueFileIdPairs = BackupDatabaseUtils::CollectFileIdPairs(fileInfos);
1118     BackupDatabaseUtils::DeleteExistingImageFaceData(mediaLibraryRdb_, uniqueFileIdPairs);
1119 
1120     for (int32_t offset = 0; offset < totalNumber; offset += QUERY_COUNT) {
1121         std::vector<FaceInfo> faceInfos = QueryFaceInfos(hashSelection, fileInfoMap, offset, excludedFiles);
1122         int64_t startInsertFace = MediaFileUtils::UTCTimeMilliSeconds();
1123         faceRowNum += InsertFaceAnalysisDataByTable(faceInfos, false, excludedFiles);
1124         if (faceRowNum <= 0) {
1125             BackupDatabaseUtils::PrintErrorLog("Insert face failed", startInsertFace);
1126             continue;
1127         }
1128         int64_t startInsertMap = MediaFileUtils::UTCTimeMilliSeconds();
1129         mapRowNum += InsertFaceAnalysisDataByTable(faceInfos, true, excludedFiles);
1130         if (mapRowNum <= 0) {
1131             BackupDatabaseUtils::PrintErrorLog("Insert map failed", startInsertMap);
1132             continue;
1133         }
1134         UpdateFilesWithFace(filesWithFace, faceInfos);
1135         int64_t endInsert = MediaFileUtils::UTCTimeMilliSeconds();
1136         MEDIA_INFO_LOG("insert %{public}ld faces cost %{public}ld, %{public}ld maps cost %{public}ld", (long)faceRowNum,
1137             (long)(startInsertMap - startInsertFace), (long)mapRowNum, (long)(endInsert - startInsertMap));
1138     }
1139     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1140     photoNum = static_cast<int64_t>(filesWithFace.size());
1141     migratePortraitFaceNumber_ += faceRowNum;
1142     migratePortraitPhotoNumber_ += photoNum;
1143     migratePortraitTotalTimeCost_ += end - start;
1144 }
1145 
SetHashReference(const std::vector<FileInfo> & fileInfos,const NeedQueryMap & needQueryMap,std::string & hashSelection,std::unordered_map<std::string,FileInfo> & fileInfoMap)1146 void UpgradeRestore::SetHashReference(const std::vector<FileInfo> &fileInfos, const NeedQueryMap &needQueryMap,
1147     std::string &hashSelection, std::unordered_map<std::string, FileInfo> &fileInfoMap)
1148 {
1149     auto needQuerySet = needQueryMap.at(PhotoRelatedType::PORTRAIT);
1150     for (const auto &fileInfo : fileInfos) {
1151         if (needQuerySet.count(fileInfo.hashCode) == 0 || fileInfo.fileIdNew <= 0) {
1152             continue;
1153         }
1154         if (fileInfoMap.count(fileInfo.hashCode) > 0) {
1155             continue; // select the first one to build map
1156         }
1157         BackupDatabaseUtils::UpdateSelection(hashSelection, fileInfo.hashCode, true);
1158         fileInfoMap[fileInfo.hashCode] = fileInfo;
1159     }
1160 }
1161 
QueryFaceTotalNumber(const std::string & hashSelection)1162 int32_t UpgradeRestore::QueryFaceTotalNumber(const std::string &hashSelection)
1163 {
1164     std::string querySql = "SELECT count(1) as count FROM " + GALLERY_TABLE_MERGE_FACE + " WHERE " +
1165         GALLERY_MERGE_FACE_HASH + " IN (" + hashSelection + ")";
1166     return BackupDatabaseUtils::QueryInt(galleryRdb_, querySql, CUSTOM_COUNT);
1167 }
1168 
QueryFaceInfos(const std::string & hashSelection,const std::unordered_map<std::string,FileInfo> & fileInfoMap,int32_t offset,std::unordered_set<std::string> & excludedFiles)1169 std::vector<FaceInfo> UpgradeRestore::QueryFaceInfos(const std::string &hashSelection,
1170     const std::unordered_map<std::string, FileInfo> &fileInfoMap, int32_t offset,
1171     std::unordered_set<std::string> &excludedFiles)
1172 {
1173     vector<FaceInfo> result;
1174     result.reserve(QUERY_COUNT);
1175 
1176     std::string querySql = "SELECT " + GALLERY_SCALE_X + ", " + GALLERY_SCALE_Y + ", " + GALLERY_SCALE_WIDTH + ", " +
1177         GALLERY_SCALE_HEIGHT + ", " + GALLERY_PITCH + ", " + GALLERY_YAW + ", " + GALLERY_ROLL + ", " +
1178         GALLERY_PROB + ", " + GALLERY_TOTAL_FACE + ", " + GALLERY_MERGE_FACE_HASH + ", " + GALLERY_MERGE_FACE_FACE_ID +
1179         ", " + GALLERY_MERGE_FACE_TAG_ID + " FROM " + GALLERY_TABLE_MERGE_FACE + " WHERE " +
1180         GALLERY_MERGE_FACE_HASH + " IN (" + hashSelection + ") ";
1181     querySql += " AND " + GALLERY_MERGE_FACE_TAG_ID + " != \'-1\'";
1182     querySql += " ORDER BY " + GALLERY_MERGE_FACE_HASH + ", " + GALLERY_MERGE_FACE_FACE_ID +
1183         " LIMIT " + std::to_string(offset) + ", " + std::to_string(QUERY_COUNT);
1184 
1185     auto resultSet = BackupDatabaseUtils::GetQueryResultSet(galleryRdb_, querySql);
1186     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, result, "Query resultSql is null.");
1187     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1188         FaceInfo faceInfo;
1189         if (!ParseFaceResultSet(resultSet, faceInfo)) {
1190             MEDIA_ERR_LOG("Parse face result set failed, exclude %{public}s", faceInfo.hash.c_str());
1191             excludedFiles.insert(faceInfo.hash);
1192             continue;
1193         }
1194         if (!SetAttributes(faceInfo, fileInfoMap)) {
1195             MEDIA_ERR_LOG("Set attributes failed, exclude %{public}s", faceInfo.hash.c_str());
1196             excludedFiles.insert(faceInfo.hash);
1197             continue;
1198         }
1199         result.emplace_back(faceInfo);
1200     }
1201     return result;
1202 }
1203 
ParseFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FaceInfo & faceInfo)1204 bool UpgradeRestore::ParseFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FaceInfo &faceInfo)
1205 {
1206     faceInfo.scaleX = GetDoubleVal(GALLERY_SCALE_X, resultSet);
1207     faceInfo.scaleY = GetDoubleVal(GALLERY_SCALE_Y, resultSet);
1208     faceInfo.scaleWidth = GetDoubleVal(GALLERY_SCALE_WIDTH, resultSet);
1209     faceInfo.scaleHeight = GetDoubleVal(GALLERY_SCALE_HEIGHT, resultSet);
1210     faceInfo.pitch = GetDoubleVal(GALLERY_PITCH, resultSet);
1211     faceInfo.yaw = GetDoubleVal(GALLERY_YAW, resultSet);
1212     faceInfo.roll = GetDoubleVal(GALLERY_ROLL, resultSet);
1213     faceInfo.prob = GetDoubleVal(GALLERY_PROB, resultSet);
1214     faceInfo.totalFaces = GetInt32Val(GALLERY_TOTAL_FACE, resultSet);
1215     faceInfo.hash = GetStringVal(GALLERY_MERGE_FACE_HASH, resultSet);
1216     faceInfo.faceId = GetStringVal(GALLERY_MERGE_FACE_FACE_ID, resultSet);
1217     faceInfo.tagIdOld = GetStringVal(GALLERY_MERGE_FACE_TAG_ID, resultSet);
1218     return true;
1219 }
1220 
SetAttributes(FaceInfo & faceInfo,const std::unordered_map<std::string,FileInfo> & fileInfoMap)1221 bool UpgradeRestore::SetAttributes(FaceInfo &faceInfo, const std::unordered_map<std::string, FileInfo> &fileInfoMap)
1222 {
1223     return BackupDatabaseUtils::SetFileIdNew(faceInfo, fileInfoMap) &&
1224         BackupDatabaseUtils::SetTagIdNew(faceInfo, tagIdMap_) &&
1225         BackupDatabaseUtils::SetAlbumIdNew(faceInfo, portraitAlbumIdMap_);
1226 }
1227 
InsertFaceAnalysisDataByTable(const std::vector<FaceInfo> & faceInfos,bool isMap,const std::unordered_set<std::string> & excludedFiles)1228 int32_t UpgradeRestore::InsertFaceAnalysisDataByTable(const std::vector<FaceInfo> &faceInfos, bool isMap,
1229     const std::unordered_set<std::string> &excludedFiles)
1230 {
1231     std::vector<NativeRdb::ValuesBucket> values = GetInsertValues(faceInfos, isMap, excludedFiles);
1232     int64_t rowNum = 0;
1233     std::string tableName = isMap ? ANALYSIS_PHOTO_MAP_TABLE : VISION_IMAGE_FACE_TABLE;
1234     int32_t errCode = BatchInsertWithRetry(tableName, values, rowNum);
1235     CHECK_AND_RETURN_RET(errCode == E_OK, 0);
1236     return rowNum;
1237 }
1238 
GetInsertValues(const std::vector<FaceInfo> & faceInfos,bool isMap,const std::unordered_set<std::string> & excludedFiles)1239 std::vector<NativeRdb::ValuesBucket> UpgradeRestore::GetInsertValues(const std::vector<FaceInfo> &faceInfos, bool isMap,
1240     const std::unordered_set<std::string> &excludedFiles)
1241 {
1242     std::vector<NativeRdb::ValuesBucket> values;
1243     for (auto &faceInfo : faceInfos) {
1244         if (excludedFiles.count(faceInfo.hash) > 0) {
1245             continue;
1246         }
1247         if (isMap && faceInfo.tagIdNew == TAG_ID_UNPROCESSED) {
1248             continue;
1249         }
1250         NativeRdb::ValuesBucket value = GetInsertValue(faceInfo, isMap);
1251         values.emplace_back(value);
1252     }
1253     return values;
1254 }
1255 
GetInsertValue(const FaceInfo & faceInfo,bool isMap)1256 NativeRdb::ValuesBucket UpgradeRestore::GetInsertValue(const FaceInfo &faceInfo, bool isMap)
1257 {
1258     NativeRdb::ValuesBucket values;
1259     if (isMap) {
1260         values.PutInt(MAP_ALBUM, faceInfo.albumIdNew);
1261         values.PutInt(MAP_ASSET, faceInfo.fileIdNew);
1262     } else {
1263         values.PutDouble(SCALE_X, faceInfo.scaleX);
1264         values.PutDouble(SCALE_Y, faceInfo.scaleY);
1265         values.PutDouble(SCALE_WIDTH, faceInfo.scaleWidth);
1266         values.PutDouble(SCALE_HEIGHT, faceInfo.scaleHeight);
1267         values.PutDouble(PITCH, faceInfo.pitch);
1268         values.PutDouble(YAW, faceInfo.yaw);
1269         values.PutDouble(ROLL, faceInfo.roll);
1270         values.PutDouble(PROB, faceInfo.prob);
1271         values.PutInt(TOTAL_FACES, faceInfo.totalFaces);
1272         values.PutInt(FILE_ID, faceInfo.fileIdNew);
1273         values.PutString(FACE_ID, faceInfo.faceId);
1274         values.PutString(TAG_ID, faceInfo.tagIdNew);
1275         values.PutString(IMAGE_FACE_VERSION, DEFAULT_BACKUP_VERSION); // replaced by the latest
1276         values.PutString(IMAGE_FEATURES_VERSION, E_VERSION); // updated by analysis service
1277     }
1278     return values;
1279 }
1280 
UpdateFilesWithFace(std::unordered_set<std::string> & filesWithFace,const std::vector<FaceInfo> & faceInfos)1281 void UpgradeRestore::UpdateFilesWithFace(std::unordered_set<std::string> &filesWithFace,
1282     const std::vector<FaceInfo> &faceInfos)
1283 {
1284     for (const auto &faceInfo : faceInfos) {
1285         if (faceInfo.hash.empty()) {
1286             continue;
1287         }
1288         filesWithFace.insert(faceInfo.hash);
1289     }
1290 }
1291 
UpdateFaceAnalysisStatus()1292 void UpgradeRestore::UpdateFaceAnalysisStatus()
1293 {
1294     if (portraitAlbumIdMap_.empty()) {
1295         MEDIA_INFO_LOG("There is no need to update face analysis status");
1296         return;
1297     }
1298     int64_t startUpdateGroupTag = MediaFileUtils::UTCTimeMilliSeconds();
1299     BackupDatabaseUtils::UpdateFaceGroupTagOfDualFrame(mediaLibraryRdb_);
1300     int64_t startUpdateTotal = MediaFileUtils::UTCTimeMilliSeconds();
1301     BackupDatabaseUtils::UpdateAnalysisTotalStatus(mediaLibraryRdb_);
1302     int64_t startUpdateFaceTag = MediaFileUtils::UTCTimeMilliSeconds();
1303     BackupDatabaseUtils::UpdateAnalysisFaceTagStatus(mediaLibraryRdb_);
1304     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
1305     MEDIA_INFO_LOG("Update group tag cost %{public}lld, update total table cost %{public}lld, update face tag table "
1306         "cost %{public}lld", (long long)(startUpdateTotal - startUpdateGroupTag),
1307         (long long)(startUpdateFaceTag - startUpdateTotal), (long long)(end - startUpdateFaceTag));
1308     migratePortraitTotalTimeCost_ += end - startUpdateGroupTag;
1309 }
1310 
UpdateDualCloneFaceAnalysisStatus()1311 void UpgradeRestore::UpdateDualCloneFaceAnalysisStatus()
1312 {
1313     if (portraitAlbumIdMap_.empty()) {
1314         MEDIA_INFO_LOG("There is no need to update face analysis status");
1315         return;
1316     }
1317 
1318     BackupDatabaseUtils::UpdateFaceGroupTagOfDualFrame(mediaLibraryRdb_);
1319     BackupDatabaseUtils::UpdateAnalysisPhotoMapStatus(mediaLibraryRdb_);
1320     BackupDatabaseUtils::UpdateFaceAnalysisTblStatus(mediaLibraryRdb_);
1321 }
1322 
CheckInvalidFile(const FileInfo & fileInfo,int32_t errCode)1323 std::string UpgradeRestore::CheckInvalidFile(const FileInfo &fileInfo, int32_t errCode)
1324 {
1325     CHECK_AND_RETURN_RET(errCode == E_NO_SUCH_FILE, "");
1326     int32_t dbType = BackupDatabaseHelper::DbType::DEFAULT;
1327     int32_t dbStatus = E_OK;
1328     int32_t fileStatus = E_OK;
1329     backupDatabaseHelper_.IsFileExist(sceneCode_, fileInfo, dbType, dbStatus, fileStatus);
1330     MEDIA_INFO_LOG("Check status type: %{public}d, db: %{public}d, file: %{public}d", dbType, dbStatus, fileStatus);
1331     return BackupLogUtils::FileDbCheckInfoToString(FileDbCheckInfo(dbType, dbStatus, fileStatus));
1332 }
1333 
GetNoNeedMigrateCount()1334 int32_t UpgradeRestore::GetNoNeedMigrateCount()
1335 {
1336     return GalleryMediaDao(this->galleryRdb_).GetNoNeedMigrateCount(this->shouldIncludeSd_);
1337 }
1338 
IsBasicInfoValid(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,FileInfo & info,const std::string & dbName)1339 bool UpgradeRestore::IsBasicInfoValid(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
1340     const std::string &dbName)
1341 {
1342     info.displayName = GetStringVal(GALLERY_DISPLAY_NAME, resultSet);
1343     info.oldPath = GetStringVal(GALLERY_FILE_DATA, resultSet);
1344     info.fileType = GetInt32Val(GALLERY_MEDIA_TYPE, resultSet);
1345     info.fileSize = GetInt64Val(GALLERY_FILE_SIZE, resultSet); // read basic info from db first
1346     if (this->photosRestore_.IsDuplicateData(info.oldPath)) {
1347         ErrorInfo errorInfo(RestoreError::DUPLICATE_DATA, 1, "",
1348             BackupLogUtils::FileInfoToString(sceneCode_, info));
1349         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1350         return false;
1351     }
1352     if (info.thumbType != 0) {
1353         if (sceneCode_ == UPGRADE_RESTORE_ID ?
1354             !BaseRestore::ConvertPathToRealPath(info.oldPath, filePath_, info.filePath, info.relativePath) :
1355             !ConvertPathToRealPath(info.oldPath, filePath_, info.filePath, info.relativePath, info)) {
1356             ErrorInfo errorInfo(RestoreError::PATH_INVALID, 1, "",
1357                 BackupLogUtils::FileInfoToString(sceneCode_, info));
1358             UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1359             return false;
1360         }
1361     }
1362     info.fileType = this->photosRestore_.FindMediaType(info);
1363     if (info.fileType != MediaType::MEDIA_TYPE_IMAGE && info.fileType != MediaType::MEDIA_TYPE_VIDEO) {
1364         ErrorInfo errorInfo(RestoreError::MEDIA_TYPE_INVALID, 1, std::to_string(info.fileType),
1365             BackupLogUtils::FileInfoToString(sceneCode_, info));
1366         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1367         return false;
1368     }
1369     if (info.fileSize < fileMinSize_ && dbName == EXTERNAL_DB_NAME) {
1370         MEDIA_WARN_LOG("maybe garbage path = %{public}s, minSize:%{public}d.",
1371             BackupFileUtils::GarbleFilePath(info.oldPath, DEFAULT_RESTORE_ID).c_str(), fileMinSize_);
1372         ErrorInfo errorInfo(RestoreError::SIZE_INVALID, 1, "Db size < " + std::to_string(fileMinSize_),
1373             BackupLogUtils::FileInfoToString(sceneCode_, info));
1374         UpgradeRestoreTaskReport().SetSceneCode(this->sceneCode_).SetTaskId(this->taskId_).ReportError(errorInfo);
1375         return false;
1376     }
1377     return true;
1378 }
1379 
CheckGalleryDbIntegrity()1380 std::string UpgradeRestore::CheckGalleryDbIntegrity()
1381 {
1382     MEDIA_INFO_LOG("start handle gallery integrity check.");
1383     std::string dbIntegrityCheck = DB_INTEGRITY_CHECK;
1384     std::string dbSize = "";
1385     struct stat statInfo {};
1386     if (stat(galleryDbPath_.c_str(), &statInfo) == 0) {
1387         dbSize = std::to_string(statInfo.st_size);
1388     }
1389     int64_t dbIntegrityCheckTime = MediaFileUtils::UTCTimeMilliSeconds();
1390     dbIntegrityCheck = BackupDatabaseUtils::CheckDbIntegrity(galleryRdb_, sceneCode_, "GALLERY_DB_CORRUPTION");
1391     dbIntegrityCheckTime = MediaFileUtils::UTCTimeMilliSeconds() - dbIntegrityCheckTime;
1392     UpgradeRestoreTaskReport()
1393         .SetSceneCode(this->sceneCode_)
1394         .SetTaskId(this->taskId_)
1395         .ReportProgress("GalleryDbCheck", dbSize + ";" + std::to_string(dbIntegrityCheckTime));
1396     MEDIA_INFO_LOG("end handle gallery integrity check, cost %{public}lld, size %{public}s.", \
1397         (long long)(dbIntegrityCheckTime), dbSize.c_str());
1398     return dbIntegrityCheck;
1399 }
1400 
PrcoessBurstPhotos()1401 void UpgradeRestore::PrcoessBurstPhotos()
1402 {
1403     BackupDatabaseUtils::UpdateBurstPhotos(mediaLibraryRdb_);
1404     MEDIA_INFO_LOG("prcoess burst photos end");
1405 }
1406 } // namespace Media
1407 } // namespace OHOS