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