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