• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include "medialibrary_album_fusion_utils.h"
17 
18 #include <cerrno>
19 #include <functional>
20 #include <iomanip>
21 #include <sstream>
22 #include <string>
23 #include <unordered_map>
24 
25 #include "dfx_reporter.h"
26 #include "medialibrary_type_const.h"
27 #include "medialibrary_formmap_operations.h"
28 #include "medialibrary_notify.h"
29 #include "medialibrary_rdbstore.h"
30 #include "metadata.h"
31 #include "media_file_utils.h"
32 #include "medialibrary_album_compatibility_fusion_sql.h"
33 #include "medialibrary_album_refresh.h"
34 #include "parameters.h"
35 #include "photo_file_operation.h"
36 #include "photo_asset_copy_operation.h"
37 #include "result_set_utils.h"
38 #include "thumbnail_service.h"
39 #include "userfile_manager_types.h"
40 #include "photo_source_path_operation.h"
41 #include "medialibrary_rdb_transaction.h"
42 #include "photo_album_lpath_operation.h"
43 
44 namespace OHOS::Media {
45 using namespace std;
46 using namespace NativeRdb;
47 
48 constexpr int32_t POSITION_LOCAL_FLAG = 1;
49 constexpr int32_t POSITION_CLOUD_FLAG = 2;
50 constexpr int32_t POSITION_BOTH_FLAG = 3;
51 constexpr int32_t CLOUD_COPY_DIRTY_FLAG = 7;
52 constexpr int32_t PHOTO_HIDDEN_FLAG = 1;
53 
54 constexpr int32_t TIME_STAMP_OFFSET = 5;
55 const std::string ALBUM_FUSION_FLAG = "multimedia.medialibrary.cloneFlag";
56 const std::string ALBUM_FUSION_UPGRADE_STATUS_FLAG = "persist.multimedia.medialibrary.albumFusion.status";
57 const int32_t ALBUM_FUSION_UPGRADE_SUCCESS = 1;
58 const int32_t ALBUM_FUSION_UPGRADE_FAIL = 0;
59 const int32_t ALBUM_FUSION_BATCH_COUNT = 200;
60 const string SQL_GET_DUPLICATE_PHOTO = "SELECT p.file_id FROM Photos p "
61             "LEFT JOIN PhotoAlbum a ON p.owner_album_id = a.album_id "
62             "WHERE p.dirty = 7 AND a.album_id IS NULL LIMIT 500";
63 
64 
65 static unordered_map<string, ResultSetDataType> commonColumnTypeMap = {
66     {MediaColumn::MEDIA_SIZE, ResultSetDataType::TYPE_INT64},
67     {MediaColumn::MEDIA_TITLE, ResultSetDataType::TYPE_STRING},
68     {MediaColumn::MEDIA_NAME, ResultSetDataType::TYPE_STRING},
69     {MediaColumn::MEDIA_TYPE, ResultSetDataType::TYPE_INT32},
70     {MediaColumn::MEDIA_MIME_TYPE, ResultSetDataType::TYPE_STRING},
71     {MediaColumn::MEDIA_OWNER_PACKAGE, ResultSetDataType::TYPE_STRING},
72     {MediaColumn::MEDIA_OWNER_APPID, ResultSetDataType::TYPE_STRING},
73     {MediaColumn::MEDIA_PACKAGE_NAME, ResultSetDataType::TYPE_STRING},
74     {MediaColumn::MEDIA_DEVICE_NAME, ResultSetDataType::TYPE_STRING},
75     {MediaColumn::MEDIA_DATE_MODIFIED, ResultSetDataType::TYPE_INT64},
76     {MediaColumn::MEDIA_DATE_ADDED, ResultSetDataType::TYPE_INT64},
77     {MediaColumn::MEDIA_DATE_TAKEN, ResultSetDataType::TYPE_INT64},
78     {MediaColumn::MEDIA_DURATION, ResultSetDataType::TYPE_INT32},
79     {MediaColumn::MEDIA_IS_FAV, ResultSetDataType::TYPE_INT32},
80     {MediaColumn::MEDIA_DATE_TRASHED, ResultSetDataType::TYPE_INT64},
81     {MediaColumn::MEDIA_DATE_DELETED, ResultSetDataType::TYPE_INT64},
82     {MediaColumn::MEDIA_HIDDEN, ResultSetDataType::TYPE_INT32},
83     {MediaColumn::MEDIA_PARENT_ID, ResultSetDataType::TYPE_INT32},
84     {PhotoColumn::PHOTO_META_DATE_MODIFIED, ResultSetDataType::TYPE_INT64},
85     {PhotoColumn::PHOTO_ORIENTATION, ResultSetDataType::TYPE_INT32},
86     {PhotoColumn::PHOTO_LATITUDE, ResultSetDataType::TYPE_DOUBLE},
87     {PhotoColumn::PHOTO_LONGITUDE, ResultSetDataType::TYPE_DOUBLE},
88     {PhotoColumn::PHOTO_HEIGHT, ResultSetDataType::TYPE_INT32},
89     {PhotoColumn::PHOTO_WIDTH, ResultSetDataType::TYPE_INT32},
90     {PhotoColumn::PHOTO_EDIT_TIME, ResultSetDataType::TYPE_INT64},
91     {PhotoColumn::PHOTO_SUBTYPE, ResultSetDataType::TYPE_INT32},
92     {PhotoColumn::CAMERA_SHOT_KEY, ResultSetDataType::TYPE_STRING},
93     {PhotoColumn::PHOTO_USER_COMMENT, ResultSetDataType::TYPE_STRING},
94     {PhotoColumn::PHOTO_SHOOTING_MODE, ResultSetDataType::TYPE_STRING},
95     {PhotoColumn::PHOTO_SHOOTING_MODE_TAG, ResultSetDataType::TYPE_STRING},
96     {PhotoColumn::PHOTO_ALL_EXIF, ResultSetDataType::TYPE_STRING},
97     {PhotoColumn::PHOTO_DATE_YEAR, ResultSetDataType::TYPE_STRING},
98     {PhotoColumn::PHOTO_DATE_MONTH, ResultSetDataType::TYPE_STRING},
99     {PhotoColumn::PHOTO_DATE_DAY, ResultSetDataType::TYPE_STRING},
100     {PhotoColumn::PHOTO_HIDDEN_TIME, ResultSetDataType::TYPE_INT64},
101     {PhotoColumn::PHOTO_FIRST_VISIT_TIME, ResultSetDataType::TYPE_INT64},
102     {PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, ResultSetDataType::TYPE_INT32},
103     {PhotoColumn::PHOTO_DYNAMIC_RANGE_TYPE, ResultSetDataType::TYPE_INT32},
104     {PhotoColumn::MOVING_PHOTO_EFFECT_MODE, ResultSetDataType::TYPE_INT32},
105     {PhotoColumn::PHOTO_FRONT_CAMERA, ResultSetDataType::TYPE_STRING},
106     {PhotoColumn::PHOTO_BURST_COVER_LEVEL, ResultSetDataType::TYPE_INT32},
107     {PhotoColumn::SUPPORTED_WATERMARK_TYPE, ResultSetDataType::TYPE_INT32},
108 };
109 
110 static unordered_map<string, ResultSetDataType> thumbnailColumnTypeMap = {
111     {PhotoColumn::PHOTO_LCD_VISIT_TIME, ResultSetDataType::TYPE_INT64},
112     {PhotoColumn::PHOTO_THUMBNAIL_READY, ResultSetDataType::TYPE_INT64},
113     {PhotoColumn::PHOTO_LCD_SIZE, ResultSetDataType::TYPE_STRING},
114     {PhotoColumn::PHOTO_THUMB_SIZE, ResultSetDataType::TYPE_STRING},
115 };
116 
117 static unordered_map<string, ResultSetDataType> albumColumnTypeMap = {
118     {PhotoAlbumColumns::ALBUM_TYPE, ResultSetDataType::TYPE_INT32},
119     {PhotoAlbumColumns::ALBUM_SUBTYPE, ResultSetDataType::TYPE_INT32},
120     {PhotoAlbumColumns::ALBUM_NAME, ResultSetDataType::TYPE_STRING},
121     {PhotoAlbumColumns::ALBUM_COVER_URI, ResultSetDataType::TYPE_STRING},
122     {PhotoAlbumColumns::ALBUM_COUNT, ResultSetDataType::TYPE_INT32},
123     {PhotoAlbumColumns::ALBUM_DATE_MODIFIED, ResultSetDataType::TYPE_INT64},
124     {PhotoAlbumColumns::CONTAINS_HIDDEN, ResultSetDataType::TYPE_INT32},
125     {PhotoAlbumColumns::HIDDEN_COUNT, ResultSetDataType::TYPE_INT32},
126     {PhotoAlbumColumns::HIDDEN_COVER, ResultSetDataType::TYPE_STRING},
127     {PhotoAlbumColumns::ALBUM_ORDER, ResultSetDataType::TYPE_INT32},
128     {PhotoAlbumColumns::ALBUM_IMAGE_COUNT, ResultSetDataType::TYPE_INT32},
129     {PhotoAlbumColumns::ALBUM_VIDEO_COUNT, ResultSetDataType::TYPE_INT32},
130     {PhotoAlbumColumns::ALBUM_BUNDLE_NAME, ResultSetDataType::TYPE_STRING},
131     {PhotoAlbumColumns::ALBUM_LOCAL_LANGUAGE, ResultSetDataType::TYPE_STRING},
132     {PhotoAlbumColumns::ALBUM_IS_LOCAL, ResultSetDataType::TYPE_INT32},
133 };
134 
135 std::mutex MediaLibraryAlbumFusionUtils::cloudAlbumAndDataMutex_;
136 std::atomic<bool> MediaLibraryAlbumFusionUtils::isNeedRefreshAlbum = false;
137 
RemoveMisAddedHiddenData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)138 int32_t MediaLibraryAlbumFusionUtils::RemoveMisAddedHiddenData(
139     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
140 {
141     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_0: Start remove misadded hidden data");
142     if (upgradeStore == nullptr) {
143         MEDIA_INFO_LOG("fail to get rdbstore");
144         return E_DB_FAIL;
145     }
146     int64_t beginTime = MediaFileUtils::UTCTimeMilliSeconds();
147     int32_t err = upgradeStore->ExecuteSql(DROP_UNWANTED_ALBUM_RELATIONSHIP_FOR_HIDDEN_ALBUM_ASSET);
148     if (err != NativeRdb::E_OK) {
149         MEDIA_ERR_LOG("Failed to drop unwanted album relationship for .hiddenAlbum! Failed to exec: %{public}s",
150             DROP_UNWANTED_ALBUM_RELATIONSHIP_FOR_HIDDEN_ALBUM_ASSET.c_str());
151         return err;
152     }
153     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_0: End remove misadded hidden data, cost %{public}ld",
154         (long)(MediaFileUtils::UTCTimeMilliSeconds() - beginTime));
155     return E_OK;
156 }
157 
PrepareTempUpgradeTable(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,int32_t & matchedCount)158 static int32_t PrepareTempUpgradeTable(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore, int32_t &matchedCount)
159 {
160     int32_t err = upgradeStore->ExecuteSql(DROP_TEMP_UPGRADE_PHOTO_MAP_TABLE);
161     if (err != NativeRdb::E_OK) {
162         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", DROP_TEMP_UPGRADE_PHOTO_MAP_TABLE.c_str());
163         return err;
164     }
165     MEDIA_INFO_LOG("ALBUM_FUSE begin exec: %{public}s", CREATE_TEMP_UPGRADE_PHOTO_MAP_TABLE.c_str());
166     err = upgradeStore->ExecuteSql(CREATE_TEMP_UPGRADE_PHOTO_MAP_TABLE);
167     if (err != NativeRdb::E_OK) {
168         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", CREATE_TEMP_UPGRADE_PHOTO_MAP_TABLE.c_str());
169         return err;
170     }
171     auto resultSet = upgradeStore->QuerySql(QUERY_MATCHED_COUNT);
172     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
173         MEDIA_ERR_LOG("Query matched data fails");
174         return E_DB_FAIL;
175     }
176     resultSet->GetInt(0, matchedCount);
177     MEDIA_INFO_LOG("ALBUM_FUSE: There are %{public}d matched items", matchedCount);
178     err = upgradeStore->ExecuteSql(CREATE_UNIQUE_TEMP_UPGRADE_INDEX_ON_MAP_ASSET);
179     if (err != NativeRdb::E_OK) {
180         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", CREATE_UNIQUE_TEMP_UPGRADE_INDEX_ON_MAP_ASSET.c_str());
181         return err;
182     }
183     err = upgradeStore->ExecuteSql(CREATE_UNIQUE_TEMP_UPGRADE_INDEX_ON_PHOTO_MAP);
184     if (err != NativeRdb::E_OK) {
185         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", CREATE_UNIQUE_TEMP_UPGRADE_INDEX_ON_PHOTO_MAP.c_str());
186         return err;
187     }
188     return E_OK;
189 }
190 
IfHandledDataCountMatched(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,int32_t & exceptCount)191 static int32_t IfHandledDataCountMatched(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
192     int32_t &exceptCount)
193 {
194     if (upgradeStore == nullptr) {
195         MEDIA_INFO_LOG("fail to get rdbstore");
196         return E_DB_FAIL;
197     }
198     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_1: Check if compensate matched data owner_album_id success");
199     int32_t updatedSuccessCount = 0;
200     auto resultSet = upgradeStore->QuerySql(QUERY_SUCCESS_MATCHED_COUNT);
201     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
202         MEDIA_ERR_LOG("Query matched data fails");
203         return E_DB_FAIL;
204     }
205     resultSet->GetInt(0, updatedSuccessCount);
206     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_1: There are %{public}d items update success", updatedSuccessCount);
207     if (updatedSuccessCount >= exceptCount) {
208         MEDIA_INFO_LOG("Handled count matches!");
209         return E_OK;
210     }
211     return E_DB_FAIL;
212 }
213 
HandleMatchedDataFusion(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)214 int32_t MediaLibraryAlbumFusionUtils::HandleMatchedDataFusion(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
215 {
216     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_1: Start handle matched relationship");
217     if (upgradeStore == nullptr) {
218         MEDIA_INFO_LOG("fail to get rdbstore");
219         return E_DB_FAIL;
220     }
221     int64_t beginTime = MediaFileUtils::UTCTimeMilliSeconds();
222     int32_t matchedCount = 0;
223     int32_t err = PrepareTempUpgradeTable(upgradeStore, matchedCount);
224     if (err != E_OK) {
225         MEDIA_ERR_LOG("Prepare temp upgrade table fails");
226         return err;
227     }
228     MEDIA_INFO_LOG("ALBUM_FUSE: execute update!");
229     err = upgradeStore->ExecuteSql(UPDATE_ALBUM_ASSET_MAPPING_CONSISTENCY_DATA_SQL);
230     MEDIA_INFO_LOG("ALBUM_FUSE: execute finish!");
231     if (err != NativeRdb::E_OK) {
232         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s",
233             UPDATE_ALBUM_ASSET_MAPPING_CONSISTENCY_DATA_SQL.c_str());
234         return err;
235     }
236 
237     if (IfHandledDataCountMatched(upgradeStore, matchedCount) != E_OK) {
238         MEDIA_ERR_LOG("Handled count not match, may has other transaction!");
239         return E_HAS_DB_ERROR;
240     }
241     err = upgradeStore->ExecuteSql(DELETE_MATCHED_RELATIONSHIP_IN_PHOTOMAP_SQL);
242     if (err != NativeRdb::E_OK) {
243         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", DELETE_MATCHED_RELATIONSHIP_IN_PHOTOMAP_SQL.c_str());
244         return err;
245     }
246     err = upgradeStore->ExecuteSql(DROP_TEMP_UPGRADE_PHOTO_MAP_TABLE);
247     if (err != NativeRdb::E_OK) {
248         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", DROP_TEMP_UPGRADE_PHOTO_MAP_TABLE.c_str());
249         return err;
250     }
251     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_1: End handle matched relationship, cost %{public}ld",
252         (long)(MediaFileUtils::UTCTimeMilliSeconds() - beginTime));
253     return E_OK;
254 }
255 
AddToMap(std::multimap<int32_t,vector<int32_t>> & targetMap,int key,int value)256 static inline void AddToMap(std::multimap<int32_t, vector<int32_t>> &targetMap, int key, int value)
257 {
258     auto it = targetMap.find(key);
259     if (it == targetMap.end()) {
260         std::vector<int32_t> valueVector = {value};
261         targetMap.insert(std::make_pair(key, valueVector));
262     } else {
263         it->second.push_back(value);
264     }
265 }
266 
QueryNoMatchedMap(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,std::multimap<int32_t,vector<int32_t>> & notMathedMap,bool isUpgrade)267 int32_t MediaLibraryAlbumFusionUtils::QueryNoMatchedMap(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
268     std::multimap<int32_t, vector<int32_t>> &notMathedMap, bool isUpgrade)
269 {
270     if (upgradeStore == nullptr) {
271         MEDIA_ERR_LOG("invalid rdbstore or nullptr map");
272         return E_INVALID_ARGUMENTS;
273     }
274     std::string queryNotMatchedDataSql = "";
275     if (isUpgrade) {
276         queryNotMatchedDataSql = QUERY_NOT_MATCHED_DATA_IN_PHOTOMAP_BY_PAGE;
277     } else {
278         queryNotMatchedDataSql = QUERY_NEW_NOT_MATCHED_DATA_IN_PHOTOMAP_BY_PAGE;
279     }
280     auto resultSet = upgradeStore->QuerySql(queryNotMatchedDataSql);
281     MEDIA_INFO_LOG("query sql is %{public}s", queryNotMatchedDataSql.c_str());
282     if (resultSet == nullptr) {
283         MEDIA_ERR_LOG("Query not matched data fails");
284         return E_DB_FAIL;
285     }
286     int32_t notMatchedCount = 0;
287     resultSet->GetRowCount(notMatchedCount);
288     if (notMatchedCount == 0) {
289         MEDIA_INFO_LOG("Already matched, no need to handle");
290         return E_OK;
291     }
292     MEDIA_INFO_LOG("There are %{public}d assets need to copy", notMatchedCount);
293     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
294         int colIndex = -1;
295         int32_t assetId = 0;
296         int32_t albumId = 0;
297         resultSet->GetColumnIndex(PhotoMap::ALBUM_ID, colIndex);
298         if (resultSet->GetInt(colIndex, albumId) != NativeRdb::E_OK) {
299             return E_HAS_DB_ERROR;
300         }
301         resultSet->GetColumnIndex(PhotoMap::ASSET_ID, colIndex);
302         if (resultSet->GetInt(colIndex, assetId) != NativeRdb::E_OK) {
303             return E_HAS_DB_ERROR;
304         }
305         AddToMap(notMathedMap, assetId, albumId);
306     }
307     return E_OK;
308 }
309 
isLocalAsset(shared_ptr<NativeRdb::ResultSet> & resultSet)310 static bool isLocalAsset(shared_ptr<NativeRdb::ResultSet> &resultSet)
311 {
312     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
313         MEDIA_INFO_LOG("Query not matched data fails");
314         return E_DB_FAIL;
315     }
316     int colIndex = -1;
317     int32_t position = POSITION_CLOUD_FLAG;
318     resultSet->GetColumnIndex("position", colIndex);
319     if (resultSet->GetInt(colIndex, position) != NativeRdb::E_OK) {
320         return E_HAS_DB_ERROR;
321     }
322     return position != POSITION_CLOUD_FLAG;
323 }
324 
buildTargetFilePath(std::string & targetPath,std::string displayName,int32_t mediaType)325 static inline void buildTargetFilePath(std::string &targetPath, std::string displayName, int32_t mediaType)
326 {
327     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
328     std::function<int(void)> tryReuseDeleted = [&]()->int {
329         int32_t uniqueId = MediaLibraryAssetOperations::CreateAssetUniqueId(mediaType, trans);
330         return MediaLibraryAssetOperations::CreateAssetPathById(uniqueId, mediaType,
331             MediaFileUtils::GetExtensionFromPath(displayName), targetPath);
332     };
333     int ret = trans->RetryTrans(tryReuseDeleted);
334     if (ret != E_OK) {
335         MEDIA_ERR_LOG("Create targetPath failed, ret=%{public}d", ret);
336     }
337 }
338 
getThumbnailPathFromOrignalPath(std::string srcPath)339 static std::string getThumbnailPathFromOrignalPath(std::string srcPath)
340 {
341     if (srcPath.empty()) {
342         MEDIA_ERR_LOG("source file invalid!");
343         return "";
344     }
345     std::string photoRelativePath = "/Photo/";
346     std::string thumbRelativePath = "/.thumbs/Photo/";
347     size_t pos = srcPath.find(photoRelativePath);
348     std::string thumbnailPath = "";
349     if (pos != string::npos) {
350         thumbnailPath = srcPath.replace(pos, photoRelativePath.length(), thumbRelativePath);
351     }
352     return thumbnailPath;
353 }
354 
CopyDirectory(const std::string & srcDir,const std::string & dstDir)355 int32_t CopyDirectory(const std::string &srcDir, const std::string &dstDir)
356 {
357     if (!MediaFileUtils::CreateDirectory(dstDir)) {
358         MEDIA_ERR_LOG("Create dstDir %{public}s failed", dstDir.c_str());
359         return E_FAIL;
360     }
361     if (!MediaFileUtils::IsFileExists(srcDir)) {
362         MEDIA_WARN_LOG("%{public}s doesn't exist, skip.", srcDir.c_str());
363         return E_OK;
364     }
365     for (const auto &dirEntry : std::filesystem::directory_iterator{ srcDir }) {
366         std::string srcFilePath = dirEntry.path();
367         std::string tmpFilePath = srcFilePath;
368         std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
369         if (!MediaFileUtils::IsFileExists(srcFilePath) || !MediaFileUtils::IsFileValid(srcFilePath)) {
370             MEDIA_ERR_LOG("Copy file from %{public}s failed , because of thumbnail is invalid", srcFilePath.c_str());
371         }
372         if (!MediaFileUtils::CopyFileUtil(srcFilePath, dstFilePath)) {
373             MEDIA_ERR_LOG("Copy file from %{public}s to %{public}s failed",
374                 srcFilePath.c_str(), dstFilePath.c_str());
375             return E_FAIL;
376         }
377     }
378     return E_OK;
379 }
380 
CopyOriginThumbnail(const std::string & srcPath,std::string & targetPath)381 static int32_t CopyOriginThumbnail(const std::string &srcPath, std::string &targetPath)
382 {
383     if (srcPath.empty() || targetPath.empty()) {
384         MEDIA_ERR_LOG("source file or targetPath empty");
385         return E_INVALID_PATH;
386     }
387     std::string originalThumbnailDirPath = getThumbnailPathFromOrignalPath(srcPath);
388     std::string targetThumbnailDirPath = getThumbnailPathFromOrignalPath(targetPath);
389     if (!targetThumbnailDirPath.empty()) {
390         int32_t err = MediaFileUtils::CopyDirectory(originalThumbnailDirPath, targetThumbnailDirPath);
391         if (err != E_OK) {
392             MEDIA_ERR_LOG("copy thumbnail dir fail because of %{public}d, dir:%{public}s",
393                 err, originalThumbnailDirPath.c_str());
394         }
395     }
396     return E_OK;
397 }
398 
DeleteFile(const std::string & targetPath)399 static int32_t DeleteFile(const std::string &targetPath)
400 {
401     if (targetPath.empty()) {
402         MEDIA_ERR_LOG("targetPath empty");
403         return E_INVALID_PATH;
404     }
405     MediaFileUtils::DeleteFile(targetPath);
406     return E_OK;
407 }
408 
DeleteThumbnail(const std::string & targetPath)409 static int32_t DeleteThumbnail(const std::string &targetPath)
410 {
411     if (targetPath.empty()) {
412         MEDIA_ERR_LOG("targetPath empty");
413         return E_INVALID_PATH;
414     }
415     std::string targetThumbnailDirPath = getThumbnailPathFromOrignalPath(targetPath);
416     MediaFileUtils::DeleteDir(targetThumbnailDirPath);
417     return E_OK;
418 }
419 
GetIntValueFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,int & value)420 static int32_t GetIntValueFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, int &value)
421 {
422     if (resultSet == nullptr) {
423         return E_HAS_DB_ERROR;
424     }
425     int index = -1;
426     resultSet->GetColumnIndex(column, index);
427     if (index == -1) {
428         return E_HAS_DB_ERROR;
429     }
430     if (resultSet->GetInt(index, value) != NativeRdb::E_OK) {
431         return E_HAS_DB_ERROR;
432     }
433     return E_OK;
434 }
435 
GetDoubleValueFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,double & value)436 static int32_t GetDoubleValueFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, double &value)
437 {
438     if (resultSet == nullptr) {
439         return E_HAS_DB_ERROR;
440     }
441     int index = -1;
442     resultSet->GetColumnIndex(column, index);
443     if (index == -1) {
444         return E_HAS_DB_ERROR;
445     }
446     if (resultSet->GetDouble(index, value) != NativeRdb::E_OK) {
447         return E_HAS_DB_ERROR;
448     }
449     return E_OK;
450 }
451 
GetLongValueFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,int64_t & value)452 static int64_t GetLongValueFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, int64_t &value)
453 {
454     if (resultSet == nullptr) {
455         return E_HAS_DB_ERROR;
456     }
457     int index = -1;
458     resultSet->GetColumnIndex(column, index);
459     if (index == -1) {
460         return E_HAS_DB_ERROR;
461     }
462     if (resultSet->GetLong(index, value) != NativeRdb::E_OK) {
463         return E_HAS_DB_ERROR;
464     }
465     return E_OK;
466 }
467 
GetStringValueFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,string & value)468 static int32_t GetStringValueFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, string &value)
469 {
470     if (resultSet == nullptr) {
471         return E_HAS_DB_ERROR;
472     }
473     int index = -1;
474     resultSet->GetColumnIndex(column, index);
475     if (index == -1) {
476         return E_HAS_DB_ERROR;
477     }
478     if (resultSet->GetString(index, value) != NativeRdb::E_OK) {
479         return E_HAS_DB_ERROR;
480     }
481     return E_OK;
482 }
483 
ParsingAndFillValue(NativeRdb::ValuesBucket & values,const string & columnName,ResultSetDataType columnType,shared_ptr<NativeRdb::ResultSet> & resultSet)484 static void ParsingAndFillValue(NativeRdb::ValuesBucket &values, const string &columnName,
485     ResultSetDataType columnType, shared_ptr<NativeRdb::ResultSet> &resultSet)
486 {
487     switch (columnType) {
488         case ResultSetDataType::TYPE_INT32: {
489             int32_t intColumnValue;
490             GetIntValueFromResultSet(resultSet, columnName, intColumnValue);
491             values.PutInt(columnName, intColumnValue);
492             break;
493         }
494         case ResultSetDataType::TYPE_INT64: {
495             int64_t longColumnValue;
496             GetLongValueFromResultSet(resultSet, columnName, longColumnValue);
497             values.PutLong(columnName, longColumnValue);
498             break;
499         }
500         case ResultSetDataType::TYPE_DOUBLE: {
501             double doubleColumnValue;
502             GetDoubleValueFromResultSet(resultSet, columnName, doubleColumnValue);
503             values.PutDouble(columnName, doubleColumnValue);
504             break;
505         }
506         case ResultSetDataType::TYPE_STRING: {
507             std::string stringValue = "";
508             GetStringValueFromResultSet(resultSet, columnName, stringValue);
509             values.PutString(columnName, stringValue);
510             break;
511         }
512         default:
513             MEDIA_ERR_LOG("No such column type");
514     }
515 }
516 
517 struct MediaAssetCopyInfo {
518     std::string targetPath;
519     bool isCopyThumbnail;
520     int32_t ownerAlbumId;
521     std::string displayName;
MediaAssetCopyInfoOHOS::Media::MediaAssetCopyInfo522     MediaAssetCopyInfo(const std::string& targetPath, bool isCopyThumbnail, int32_t ownerAlbumId,
523         const std::string& displayName = "")
524         : targetPath(targetPath), isCopyThumbnail(isCopyThumbnail), ownerAlbumId(ownerAlbumId),
525         displayName(displayName) {}
526 };
527 
HandleLowQualityAssetValuesBucket(shared_ptr<NativeRdb::ResultSet> & resultSet,NativeRdb::ValuesBucket & values)528 static void HandleLowQualityAssetValuesBucket(shared_ptr<NativeRdb::ResultSet>& resultSet,
529     NativeRdb::ValuesBucket& values)
530 {
531     int32_t dirty = -1;
532     GetIntValueFromResultSet(resultSet, PhotoColumn::PHOTO_DIRTY, dirty);
533     int32_t photoQuality = 0;
534     GetIntValueFromResultSet(resultSet, PhotoColumn::PHOTO_QUALITY, photoQuality);
535     if (photoQuality == static_cast<int32_t>(MultiStagesPhotoQuality::LOW)) {
536         photoQuality = static_cast<int32_t>(MultiStagesPhotoQuality::FULL);
537         dirty = static_cast<int32_t>(DirtyType::TYPE_NEW);
538         values.PutInt(PhotoColumn::PHOTO_DIRTY, dirty);
539     }
540     values.PutInt(PhotoColumn::PHOTO_QUALITY, photoQuality);
541     if (dirty == -1 && photoQuality != static_cast<int32_t>(MultiStagesPhotoQuality::LOW)) {
542         MEDIA_WARN_LOG("Status error, dirty is -1, cannot upload");
543         values.PutInt(PhotoColumn::PHOTO_DIRTY, -1);
544     }
545 }
546 
BuildInsertValuesBucket(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,NativeRdb::ValuesBucket & values,shared_ptr<NativeRdb::ResultSet> & resultSet,const MediaAssetCopyInfo & copyInfo)547 static int32_t BuildInsertValuesBucket(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,
548     NativeRdb::ValuesBucket &values, shared_ptr<NativeRdb::ResultSet> &resultSet, const MediaAssetCopyInfo &copyInfo)
549 {
550     values.PutString(MediaColumn::MEDIA_FILE_PATH, copyInfo.targetPath);
551     PhotoAssetCopyOperation()
552         .SetTargetPhotoInfo(resultSet)
553         .SetTargetAlbumId(copyInfo.ownerAlbumId)
554         .SetDisplayName(copyInfo.displayName)
555         .CopyPhotoAsset(rdbStore, values);
556     for (auto it = commonColumnTypeMap.begin(); it != commonColumnTypeMap.end(); ++it) {
557         string columnName = it->first;
558         ResultSetDataType columnType = it->second;
559         ParsingAndFillValue(values, columnName, columnType, resultSet);
560     }
561     if (copyInfo.isCopyThumbnail) {
562         for (auto it = thumbnailColumnTypeMap.begin(); it != thumbnailColumnTypeMap.end(); ++it) {
563             string columnName = it->first;
564             ResultSetDataType columnType = it->second;
565             ParsingAndFillValue(values, columnName, columnType, resultSet);
566         }
567         // Indicate original file cloud_id for cloud copy
568         std::string cloudId = "";
569         GetStringValueFromResultSet(resultSet, PhotoColumn::PHOTO_CLOUD_ID, cloudId);
570         if (cloudId.empty()) {
571             // copy from copyed asset, may not synced, need copy from original asset
572             GetStringValueFromResultSet(resultSet, PhotoColumn::PHOTO_ORIGINAL_ASSET_CLOUD_ID, cloudId);
573         }
574         values.PutString(PhotoColumn::PHOTO_ORIGINAL_ASSET_CLOUD_ID, cloudId);
575         values.PutInt(PhotoColumn::PHOTO_POSITION, POSITION_CLOUD_FLAG);
576         values.PutInt(PhotoColumn::PHOTO_DIRTY, CLOUD_COPY_DIRTY_FLAG);
577     }
578     HandleLowQualityAssetValuesBucket(resultSet, values);
579     return E_OK;
580 }
581 
copyMetaData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,int64_t & newAssetId,NativeRdb::ValuesBucket & values)582 static int32_t copyMetaData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, int64_t &newAssetId,
583     NativeRdb::ValuesBucket &values)
584 {
585     int32_t ret = rdbStore->Insert(newAssetId, PhotoColumn::PHOTOS_TABLE, values);
586     if (ret != NativeRdb::E_OK) {
587         MEDIA_ERR_LOG("upgradeStore->Insert failed, ret = %{public}d", ret);
588         return E_HAS_DB_ERROR;
589     }
590     MEDIA_DEBUG_LOG("Insert copy meta data success, rowId=%{public}" PRId64", ret=%{public}d", newAssetId, ret);
591     return ret;
592 }
593 
GetSourceFilePath(std::string & srcPath,shared_ptr<NativeRdb::ResultSet> & resultSet)594 static int32_t GetSourceFilePath(std::string &srcPath, shared_ptr<NativeRdb::ResultSet> &resultSet)
595 {
596     int colIndex = -1;
597     resultSet->GetColumnIndex(MediaColumn::MEDIA_FILE_PATH, colIndex);
598     if (resultSet->GetString(colIndex, srcPath) != NativeRdb::E_OK) {
599         return E_HAS_DB_ERROR;
600     }
601     return E_OK;
602 }
603 
UpdateRelationship(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,const int32_t & assetId,const int32_t & newAssetId,const int32_t & ownerAlbumId,bool isLocalAsset)604 static int32_t UpdateRelationship(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, const int32_t &assetId,
605     const int32_t &newAssetId, const int32_t &ownerAlbumId, bool isLocalAsset)
606 {
607     const std::string UPDATE_ALBUM_ID_FOR_COPY_ASSET =
608         "UPDATE Photos SET owner_album_id = " + to_string(ownerAlbumId) + " WHERE file_id = " + to_string(newAssetId);
609     int32_t ret = rdbStore->ExecuteSql(UPDATE_ALBUM_ID_FOR_COPY_ASSET);
610     if (ret != NativeRdb::E_OK) {
611         MEDIA_ERR_LOG("UPDATE_ALBUM_ID_FOR_COPY_ASSET failed, ret = %{public}d", ret);
612         return E_HAS_DB_ERROR;
613     }
614     const std::string DROP_HANDLED_MAP_RELATIONSHIP =
615     "UPDATE PhotoMap SET dirty = '4' WHERE " + PhotoMap::ASSET_ID + " = '" + to_string(assetId) +
616         "' AND " + PhotoMap::ALBUM_ID + " = '" + to_string(ownerAlbumId) + "'";
617     ret = rdbStore->ExecuteSql(DROP_HANDLED_MAP_RELATIONSHIP);
618     if (ret != NativeRdb::E_OK) {
619         MEDIA_ERR_LOG("DROP_HANDLED_MAP_RELATIONSHIP failed, ret = %{public}d", ret);
620         return E_HAS_DB_ERROR;
621     }
622     if (!isLocalAsset) {
623         const std::string INDICATE_FILE_NEED_CLOUD_COPY =
624         "UPDATE Photos SET dirty = '7' WHERE " + PhotoMap::ASSET_ID + " = '" + to_string(newAssetId);
625     }
626     MEDIA_INFO_LOG("Update handled copy meta success, rowId = %{public}d, ", newAssetId);
627     return E_OK;
628 }
629 
GenerateThumbnail(const int32_t & assetId,const std::string & targetPath,shared_ptr<NativeRdb::ResultSet> & resultSet,bool isSyncGenerateThumbnail)630 static int32_t GenerateThumbnail(const int32_t &assetId, const std::string &targetPath,
631     shared_ptr<NativeRdb::ResultSet> &resultSet, bool isSyncGenerateThumbnail)
632 {
633     if (ThumbnailService::GetInstance() == nullptr) {
634         return E_FAIL;
635     }
636     std::string displayName = "";
637     GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_NAME, displayName);
638     int64_t dateTaken = 0;
639     GetLongValueFromResultSet(resultSet, MediaColumn::MEDIA_DATE_TAKEN, dateTaken);
640     std::string uri = PHOTO_URI_PREFIX + to_string(assetId) + MediaFileUtils::GetExtraUri(displayName, targetPath) +
641         "?api_version=10&date_taken=" + to_string(dateTaken);
642     MEDIA_INFO_LOG("Begin generate thumbnail %{public}s, ", uri.c_str());
643     int32_t err = ThumbnailService::GetInstance()->CreateThumbnailFileScaned(uri, targetPath, isSyncGenerateThumbnail);
644     if (err != E_SUCCESS) {
645         MEDIA_ERR_LOG("ThumbnailService CreateThumbnailFileScaned failed : %{public}d", err);
646     }
647     MEDIA_INFO_LOG("Generate thumbnail %{public}s, success ", uri.c_str());
648     return err;
649 }
650 
UpdateCoverInfoForAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & oldAssetId,const int32_t & ownerAlbumId,int64_t & newAssetId,const std::string & targetPath)651 static int32_t UpdateCoverInfoForAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
652     const int32_t &oldAssetId, const int32_t &ownerAlbumId, int64_t &newAssetId, const std::string &targetPath)
653 {
654     if (upgradeStore == nullptr) {
655         MEDIA_INFO_LOG("fail to get rdbstore");
656         return E_DB_FAIL;
657     }
658     const std::string QUERY_ALBUM_COVER_INFO =
659         "SELECT cover_uri FROM PhotoAlbum WHERE album_id = " + to_string(ownerAlbumId) +
660         " AND cover_uri like 'file://media/Photo/" + to_string(oldAssetId) + "%'";
661     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_ALBUM_COVER_INFO);
662     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
663         MEDIA_INFO_LOG("No need to update cover_uri");
664         return E_OK;
665     }
666     string newCoverUri = MediaLibraryFormMapOperations::GetUriByFileId(newAssetId, targetPath);
667     MEDIA_INFO_LOG("New cover uri is %{public}s", targetPath.c_str());
668     const std::string UPDATE_ALBUM_COVER_URI =
669         "UPDATE PhotoAlbum SET cover_uri = '" + newCoverUri +"' WHERE album_id = " + to_string(ownerAlbumId);
670     int32_t ret = upgradeStore->ExecuteSql(UPDATE_ALBUM_COVER_URI);
671     if (ret != NativeRdb::E_OK) {
672         MEDIA_ERR_LOG("update cover uri failed, ret = %{public}d, target album is %{public}d", ret, ownerAlbumId);
673         return E_HAS_DB_ERROR;
674     }
675     return E_OK;
676 }
677 
CopyLocalFile(shared_ptr<NativeRdb::ResultSet> & resultSet,const int32_t & ownerAlbumId,const std::string displayName,std::string & targetPath,const int32_t & assetId)678 static int32_t CopyLocalFile(shared_ptr<NativeRdb::ResultSet> &resultSet, const int32_t &ownerAlbumId,
679     const std::string displayName, std::string &targetPath, const int32_t &assetId)
680 {
681     MEDIA_INFO_LOG("begin copy local file, fileId:%{public}d, and target album:%{public}d", assetId, ownerAlbumId);
682     std::string srcPath = "";
683     GetSourceFilePath(srcPath, resultSet);
684 
685     int32_t mediaType;
686     GetIntValueFromResultSet(resultSet, MediaColumn::MEDIA_TYPE, mediaType);
687     buildTargetFilePath(targetPath, displayName, mediaType);
688     if (targetPath.empty()) {
689         MEDIA_ERR_LOG("Build target path fail, origin file is %{public}s", srcPath.c_str());
690         return E_INVALID_PATH;
691     }
692     MEDIA_INFO_LOG("begin copy local file, scrPath is %{public}s, and target path is %{public}s",
693         srcPath.c_str(), targetPath.c_str());
694     // Copy photo files, supporting copy moving photo's video and extraData folder.
695     int32_t err = PhotoFileOperation().CopyPhoto(resultSet, targetPath);
696     if (err != E_OK) {
697         MEDIA_ERR_LOG("CopyPhoto failed, srcPath = %{public}s, targetPath = %{public}s, ret = %{public}d",
698             srcPath.c_str(), targetPath.c_str(), err);
699         return err;
700     }
701     return E_OK;
702 }
703 
CopyMateData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,shared_ptr<NativeRdb::ResultSet> & resultSet,int64_t & newAssetId,std::string & targetPath,const MediaAssetCopyInfo & copyInfo)704 static int32_t CopyMateData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore, shared_ptr<NativeRdb::ResultSet>
705     &resultSet, int64_t &newAssetId, std::string &targetPath, const MediaAssetCopyInfo &copyInfo)
706 {
707     NativeRdb::ValuesBucket values;
708     int32_t err = BuildInsertValuesBucket(upgradeStore, values, resultSet, copyInfo);
709     if (err != E_OK) {
710         MEDIA_ERR_LOG("Insert meta data fail and delete migrated file %{public}s ", targetPath.c_str());
711         DeleteFile(targetPath);
712         return err;
713     }
714     err = copyMetaData(upgradeStore, newAssetId, values);
715     if (err != E_OK) {
716         MEDIA_ERR_LOG("Insert meta data fail and delete migrated file err %{public}d ", err);
717         // If insert fails, delete the moved file to avoid wasted space
718         DeleteFile(targetPath);
719         return err;
720     }
721     return E_OK;
722 }
723 
CopyLocalSingleFile(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & ownerAlbumId,shared_ptr<NativeRdb::ResultSet> & resultSet,int64_t & newAssetId,std::string displayName)724 int32_t MediaLibraryAlbumFusionUtils::CopyLocalSingleFile(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
725     const int32_t &ownerAlbumId, shared_ptr<NativeRdb::ResultSet> &resultSet, int64_t &newAssetId,
726     std::string displayName)
727 {
728     if (upgradeStore == nullptr) {
729         MEDIA_INFO_LOG("fail to get rdbstore");
730         return E_DB_FAIL;
731     }
732 
733     int32_t assetId;
734     GetIntValueFromResultSet(resultSet, MediaColumn::MEDIA_ID, assetId);
735     GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_NAME, displayName);
736     std::string targetPath = "";
737     int32_t err = CopyLocalFile(resultSet, ownerAlbumId, displayName, targetPath, assetId);
738     if (err != E_OK) {
739         MEDIA_INFO_LOG("Failed to copy local file.");
740         return E_ERR;
741     }
742 
743     MediaAssetCopyInfo copyInfo(targetPath, false, ownerAlbumId, displayName);
744     err = CopyMateData(upgradeStore, resultSet, newAssetId, targetPath, copyInfo);
745     if (err != E_OK) {
746         MEDIA_INFO_LOG("Failed to copy local file.");
747         return E_ERR;
748     }
749 
750     err = UpdateRelationship(upgradeStore, assetId, newAssetId, ownerAlbumId, true);
751     if (err != E_OK) {
752         MEDIA_ERR_LOG("UpdateRelationship fail, assetId: %{public}d, newAssetId: %{public}" PRId64
753             "ownerAlbumId: %{public}d, ret = %{public}d", assetId, newAssetId, ownerAlbumId, err);
754         return E_OK;
755     }
756 
757     err = PhotoFileOperation().CopyThumbnail(resultSet, targetPath, newAssetId);
758     if (err != E_OK && GenerateThumbnail(newAssetId, targetPath, resultSet, false) != E_SUCCESS) {
759         MediaLibraryRdbUtils::UpdateThumbnailRelatedDataToDefault(upgradeStore, newAssetId);
760         MEDIA_ERR_LOG("Copy thumbnail failed, targetPath = %{public}s, ret = %{public}d, newAssetId = %{public}" PRId64,
761             targetPath.c_str(), err, newAssetId);
762         return err;
763     }
764     UpdateCoverInfoForAlbum(upgradeStore, assetId, ownerAlbumId, newAssetId, targetPath);
765     return E_OK;
766 }
767 
CopyLocalSingleFileSync(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & ownerAlbumId,shared_ptr<NativeRdb::ResultSet> & resultSet,int64_t & newAssetId,const std::string displayName)768 static int32_t CopyLocalSingleFileSync(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore, const int32_t
769     &ownerAlbumId, shared_ptr<NativeRdb::ResultSet> &resultSet, int64_t &newAssetId, const std::string displayName)
770 {
771     if (upgradeStore == nullptr) {
772         MEDIA_INFO_LOG("fail to get rdbstore");
773         return E_DB_FAIL;
774     }
775 
776     int32_t assetId;
777     GetIntValueFromResultSet(resultSet, MediaColumn::MEDIA_ID, assetId);
778     std::string targetPath = "";
779     int32_t err = CopyLocalFile(resultSet, ownerAlbumId, displayName, targetPath, assetId);
780     if (err != E_OK) {
781         MEDIA_INFO_LOG("Failed to copy local file.");
782         return E_ERR;
783     }
784 
785     MediaAssetCopyInfo copyInfo(targetPath, false, ownerAlbumId, displayName);
786     err = CopyMateData(upgradeStore, resultSet, newAssetId, targetPath, copyInfo);
787     if (err != E_OK) {
788         MEDIA_INFO_LOG("Failed to copy local file.");
789         return E_ERR;
790     }
791 
792     err = UpdateRelationship(upgradeStore, assetId, newAssetId, ownerAlbumId, true);
793     if (err != E_OK) {
794         MEDIA_ERR_LOG("UpdateRelationship fail, assetId: %{public}d, newAssetId: %{public}" PRId64
795             "ownerAlbumId: %{public}d, ret = %{public}d", assetId, newAssetId, ownerAlbumId, err);
796         return E_OK;
797     }
798 
799     err = PhotoFileOperation().CopyThumbnail(resultSet, targetPath, newAssetId);
800     if (err != E_OK && GenerateThumbnail(newAssetId, targetPath, resultSet, true) != E_SUCCESS) {
801         MediaLibraryRdbUtils::UpdateThumbnailRelatedDataToDefault(upgradeStore, newAssetId);
802         MEDIA_ERR_LOG("Copy thumbnail failed, targetPath = %{public}s, ret = %{public}d, newAssetId = %{public}" PRId64,
803             targetPath.c_str(), err, newAssetId);
804         return err;
805     }
806     UpdateCoverInfoForAlbum(upgradeStore, assetId, ownerAlbumId, newAssetId, targetPath);
807     return E_OK;
808 }
809 
SetRefreshAlbum(bool needRefresh)810 void MediaLibraryAlbumFusionUtils::SetRefreshAlbum(bool needRefresh)
811 {
812     isNeedRefreshAlbum = needRefresh;
813 }
814 
CopyCloudSingleFile(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & assetId,const int32_t & ownerAlbumId,shared_ptr<NativeRdb::ResultSet> & resultSet,int64_t & newAssetId)815 int32_t MediaLibraryAlbumFusionUtils::CopyCloudSingleFile(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
816     const int32_t &assetId, const int32_t &ownerAlbumId, shared_ptr<NativeRdb::ResultSet> &resultSet,
817     int64_t &newAssetId)
818 {
819     if (upgradeStore == nullptr) {
820         MEDIA_INFO_LOG("fail to get rdbstore");
821         return E_DB_FAIL;
822     }
823     MEDIA_INFO_LOG("Begin copy cloud file, fileId is %{public}d, and target album is %{public}d",
824         assetId, ownerAlbumId);
825     std::string srcPath = "";
826     std::string targetPath = "";
827     GetSourceFilePath(srcPath, resultSet);
828 
829     std::string displayName;
830     int32_t mediaType;
831     GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_NAME, displayName);
832     GetIntValueFromResultSet(resultSet, MediaColumn::MEDIA_TYPE, mediaType);
833     buildTargetFilePath(targetPath, displayName, mediaType);
834     if (targetPath.empty()) {
835         MEDIA_ERR_LOG("Build target path fail, origin file is %{public}s", srcPath.c_str());
836         return E_INVALID_PATH;
837     }
838     MEDIA_INFO_LOG("Begin copy thumbnail original scrPath is %{public}s, and target path is %{public}s",
839         srcPath.c_str(), targetPath.c_str());
840     int32_t err = CopyOriginThumbnail(srcPath, targetPath);
841     if (err != E_OK) {
842         return err;
843     }
844     MediaAssetCopyInfo copyInfo(targetPath, true, ownerAlbumId);
845     NativeRdb::ValuesBucket values;
846     err = BuildInsertValuesBucket(upgradeStore, values, resultSet, copyInfo);
847     if (err != E_OK) {
848         MEDIA_ERR_LOG("Build meta data fail and delete migrated file %{public}s ", targetPath.c_str());
849         DeleteThumbnail(targetPath);
850         return err;
851     }
852     err = copyMetaData(upgradeStore, newAssetId, values);
853     if (err != E_OK) {
854         // If insert fails, delete the moved file to avoid wasted space
855         MEDIA_ERR_LOG("Build meta data fail and delete migrated file %{public}s ", targetPath.c_str());
856         DeleteThumbnail(targetPath);
857         return err;
858     }
859     ThumbnailService::GetInstance()->CreateAstcCloudDownload(to_string(newAssetId), true);
860     err = UpdateRelationship(upgradeStore, assetId, newAssetId, ownerAlbumId, false);
861     if (err != E_OK) {
862         return err;
863     }
864     UpdateCoverInfoForAlbum(upgradeStore, assetId, ownerAlbumId, newAssetId, targetPath);
865     return E_OK;
866 }
867 
SendNewAssetNotify(string newFileAssetUri,const shared_ptr<MediaLibraryRdbStore> & rdbStore)868 void SendNewAssetNotify(string newFileAssetUri, const shared_ptr<MediaLibraryRdbStore> &rdbStore)
869 {
870     vector<string> systemAlbumsExcludeSource = {
871         to_string(PhotoAlbumSubType::FAVORITE),
872         to_string(PhotoAlbumSubType::VIDEO),
873         to_string(PhotoAlbumSubType::HIDDEN),
874         to_string(PhotoAlbumSubType::TRASH),
875         to_string(PhotoAlbumSubType::IMAGE),
876         to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
877     };
878     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, systemAlbumsExcludeSource, true);
879     MediaLibraryRdbUtils::UpdateUserAlbumByUri(rdbStore, { newFileAssetUri });
880 
881     auto watch = MediaLibraryNotify::GetInstance();
882     if (watch == nullptr) {
883         MEDIA_ERR_LOG("Can not get MediaLibraryNotify, fail to send new asset notify.");
884         return;
885     }
886     watch->Notify(newFileAssetUri, NotifyType::NOTIFY_ADD);
887     watch->Notify(newFileAssetUri, NotifyType::NOTIFY_THUMB_ADD);
888     watch->Notify(newFileAssetUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET);
889 }
890 
CloneSingleAsset(const int64_t & assetId,const string title)891 int32_t MediaLibraryAlbumFusionUtils::CloneSingleAsset(const int64_t &assetId, const string title)
892 {
893     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
894     if (rdbStore == nullptr) {
895         MEDIA_ERR_LOG("Failed to get rdbStore.");
896         return E_DB_FAIL;
897     }
898 
899     const std::string querySql = "SELECT * FROM Photos WHERE file_id = ?";
900     std::vector<NativeRdb::ValueObject> params = { assetId };
901     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(querySql, params);
902     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
903         MEDIA_INFO_LOG("Query not matched data fails");
904         return E_DB_FAIL;
905     }
906 
907     string oldDisplayName = GetStringVal(MediaColumn::MEDIA_NAME, resultSet);
908     string suffix = MediaFileUtils::SplitByChar(oldDisplayName, '.');
909     if (suffix.empty()) {
910         MEDIA_ERR_LOG("Failed to get file suffix.");
911         return E_FAIL;
912     }
913 
914     string displayName = title + "." + suffix;
915     int32_t ownerAlbumId;
916     GetIntValueFromResultSet(resultSet, PhotoColumn::PHOTO_OWNER_ALBUM_ID, ownerAlbumId);
917     int64_t newAssetId = -1;
918     int32_t err = CopyLocalSingleFileSync(rdbStore, ownerAlbumId, resultSet, newAssetId, displayName);
919     if (err != E_OK) {
920         MEDIA_ERR_LOG("Clone local asset failed, ret = %{public}d, assetId = %{public}" PRId64, err, assetId);
921         return err;
922     }
923 
924     RdbPredicates newPredicates(PhotoColumn::PHOTOS_TABLE);
925     newPredicates.EqualTo(PhotoColumn::MEDIA_ID, newAssetId);
926     vector<string> columns = {
927         PhotoColumn::MEDIA_FILE_PATH, MediaColumn::MEDIA_HIDDEN
928     };
929     shared_ptr<NativeRdb::ResultSet> newResultSet = rdbStore->Query(newPredicates, columns);
930     if (newResultSet == nullptr || newResultSet->GoToFirstRow() != NativeRdb::E_OK) {
931         MEDIA_INFO_LOG("Query not matched data fails");
932         return E_DB_FAIL;
933     }
934 
935     string newFileAssetUri = MediaFileUtils::GetFileAssetUri(GetStringVal(MediaColumn::MEDIA_FILE_PATH, newResultSet),
936         displayName, newAssetId);
937     int32_t isHidden = GetInt32Val(MediaColumn::MEDIA_HIDDEN, newResultSet);
938     if (isHidden == PHOTO_HIDDEN_FLAG) {
939         MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(rdbStore);
940     }
941     SendNewAssetNotify(newFileAssetUri, rdbStore);
942     MEDIA_INFO_LOG("End clone asset, newAssetId = %{public}" PRId64, newAssetId);
943     return newAssetId;
944 }
945 
GetNoOwnerDataCnt(const std::shared_ptr<MediaLibraryRdbStore> store)946 static int32_t GetNoOwnerDataCnt(const std::shared_ptr<MediaLibraryRdbStore> store)
947 {
948     NativeRdb::RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
949     rdbPredicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, 0);
950     vector<string> columns;
951     int rowCount = 0;
952     shared_ptr<NativeRdb::ResultSet> resultSet = store->Query(rdbPredicates, columns);
953     if (resultSet == nullptr || resultSet->GetRowCount(rowCount) != NativeRdb::E_OK) {
954         MEDIA_ERR_LOG("Query not matched data fails");
955     }
956     MEDIA_INFO_LOG("Begin handle no owner data: count %{public}d", rowCount);
957     return rowCount;
958 }
959 
HandleNoOwnerData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)960 int32_t MediaLibraryAlbumFusionUtils::HandleNoOwnerData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
961 {
962     if (upgradeStore == nullptr) {
963         MEDIA_INFO_LOG("fail to get rdbstore");
964         return E_DB_FAIL;
965     }
966     auto rowCount = GetNoOwnerDataCnt(upgradeStore);
967     SetRefreshAlbum(rowCount > 0);
968     const std::string UPDATE_NO_OWNER_ASSET_INTO_OTHER_ALBUM = "UPDATE PHOTOS SET owner_album_id = "
969         "(SELECT album_id FROM PhotoAlbum where album_name = '其它') WHERE owner_album_id = 0";
970     int32_t ret = upgradeStore->ExecuteSql(UPDATE_NO_OWNER_ASSET_INTO_OTHER_ALBUM);
971     if (ret != NativeRdb::E_OK) {
972         MEDIA_ERR_LOG("UPDATE_NO_OWNER_ASSET_INTO_OTHER_ALBUM failed, ret = %{public}d", ret);
973         return E_HAS_DB_ERROR;
974     }
975     return E_OK;
976 }
977 
HandleRestData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & assetId,const std::vector<int32_t> & restOwnerAlbumIds,int32_t & handledCount)978 int32_t MediaLibraryAlbumFusionUtils::HandleRestData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
979     const int32_t &assetId, const std::vector<int32_t> &restOwnerAlbumIds, int32_t &handledCount)
980 {
981     MEDIA_INFO_LOG("Begin handle rest data assetId is %{public}d", assetId);
982     if (upgradeStore == nullptr) {
983         MEDIA_INFO_LOG("fail to get rdbstore");
984         return E_DB_FAIL;
985     }
986     const std::string QUERY_FILE_META_INFO =
987         "SELECT * FROM Photos WHERE file_id = " + to_string(assetId);
988     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_FILE_META_INFO);
989     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
990         MEDIA_INFO_LOG("Query not matched data fails");
991         return E_DB_FAIL;
992     }
993     int64_t newAssetId = -1;
994     if (isLocalAsset(resultSet)) {
995         MEDIA_INFO_LOG("file is local asset %{public}d", assetId);
996         // skip first one, already handled
997         for (size_t i = 0; i < restOwnerAlbumIds.size(); i++) {
998             int32_t err = CopyLocalSingleFile(upgradeStore, restOwnerAlbumIds[i], resultSet, newAssetId);
999             if (err != E_OK) {
1000                 MEDIA_WARN_LOG("Copy file fails, fileId is %{public}d", assetId);
1001                 continue;
1002             }
1003             MEDIA_INFO_LOG("Copy file success, fileId is %{public}d, albumId is %{public}d",
1004                 assetId, restOwnerAlbumIds[i]);
1005             handledCount++;
1006         }
1007     } else {
1008         MEDIA_INFO_LOG("file is cloud asset %{public}d", assetId);
1009         // skip first one, already handled
1010         for (size_t i = 0; i < restOwnerAlbumIds.size(); i++) {
1011             int32_t err = CopyCloudSingleFile(upgradeStore, assetId, restOwnerAlbumIds[i], resultSet, newAssetId);
1012             if (err != E_OK) {
1013                 MEDIA_WARN_LOG("Copy cloud file fails, fileId is %{public}d", assetId);
1014                 continue;
1015             }
1016             MEDIA_INFO_LOG("Copy cloud file success, fileId is %{public}d, albumId is %{public}d",
1017                 assetId, restOwnerAlbumIds[i]);
1018             handledCount++;
1019         }
1020     }
1021     return E_OK;
1022 }
1023 
HandleNotMatchedDataMigration(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,std::multimap<int32_t,vector<int32_t>> & notMathedMap)1024 int32_t MediaLibraryAlbumFusionUtils::HandleNotMatchedDataMigration(
1025     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore, std::multimap<int32_t, vector<int32_t>> &notMathedMap)
1026 {
1027     if (upgradeStore == nullptr) {
1028         MEDIA_INFO_LOG("fail to get rdbstore");
1029         return E_DB_FAIL;
1030     }
1031     static int handledCount = 0;
1032     for (auto it = notMathedMap.begin(); it != notMathedMap.end(); ++it) {
1033         HandleRestData(upgradeStore, it->first, it->second, handledCount);
1034     }
1035     MEDIA_INFO_LOG("handled %{public}d not matched items", handledCount);
1036     // Put no relationship asset into other album
1037     HandleNoOwnerData(upgradeStore);
1038     return E_OK;
1039 }
1040 
HandleSingleFileCopy(const shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & assetId,const int32_t & ownerAlbumId,int64_t & newAssetId)1041 int32_t MediaLibraryAlbumFusionUtils::HandleSingleFileCopy(const shared_ptr<MediaLibraryRdbStore> upgradeStore,
1042     const int32_t &assetId, const int32_t &ownerAlbumId, int64_t &newAssetId)
1043 {
1044     MEDIA_INFO_LOG("Begin copy single file assetId is %{public}d", assetId);
1045     if (upgradeStore == nullptr) {
1046         MEDIA_INFO_LOG("fail to get rdbstore");
1047         return E_DB_FAIL;
1048     }
1049     const std::string QUERY_FILE_META_INFO =
1050         "SELECT * FROM Photos WHERE file_id = " + to_string(assetId);
1051     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_FILE_META_INFO);
1052     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1053         MEDIA_INFO_LOG("Query not matched data fails");
1054         return E_DB_FAIL;
1055     }
1056     int32_t err = E_OK;
1057     if (isLocalAsset(resultSet)) {
1058         err = CopyLocalSingleFile(upgradeStore, ownerAlbumId, resultSet, newAssetId);
1059     } else {
1060         err = CopyCloudSingleFile(upgradeStore, assetId, ownerAlbumId, resultSet, newAssetId);
1061     }
1062     if (err != E_OK) {
1063         MEDIA_ERR_LOG("Copy file fails, is file local : %{public}d, fileId is %{public}d",
1064             isLocalAsset(resultSet), assetId);
1065         return err;
1066     }
1067     MEDIA_INFO_LOG("Copy file success, fileId is %{public}d, albumId is %{public}d,"
1068         "and copyed file id is %{public}" PRId64, assetId, ownerAlbumId, newAssetId);
1069     return E_OK;
1070 }
1071 
QueryTotalNumberNeedToHandle(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const std::string & querySql)1072 static int32_t QueryTotalNumberNeedToHandle(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1073     const std::string &querySql)
1074 {
1075     int32_t rowCount = 0;
1076     if (upgradeStore == nullptr) {
1077         MEDIA_INFO_LOG("fail to get rdbstore");
1078         return rowCount;
1079     }
1080     if (querySql.empty()) {
1081         return rowCount;
1082     }
1083     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(querySql);
1084     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1085         MEDIA_INFO_LOG("No need to update cover_uri");
1086         return rowCount;
1087     }
1088     if (resultSet->GetInt(0, rowCount) != NativeRdb::E_OK) {
1089         return rowCount;
1090     }
1091     return rowCount;
1092 }
1093 
HandleNotMatchedDataFusion(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1094 int32_t MediaLibraryAlbumFusionUtils::HandleNotMatchedDataFusion(
1095     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1096 {
1097     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_2: Start handle not matched relationship");
1098     if (upgradeStore == nullptr) {
1099         MEDIA_INFO_LOG("fail to get rdbstore");
1100         return E_DB_FAIL;
1101     }
1102     int64_t beginTime = MediaFileUtils::UTCTimeMilliSeconds();
1103     int32_t totalNumber = QueryTotalNumberNeedToHandle(upgradeStore, QUERY_NOT_MATCHED_COUNT_IN_PHOTOMAP);
1104     MEDIA_INFO_LOG("QueryTotalNumberNeedToHandle, totalNumber=%{public}d", totalNumber);
1105     std::multimap<int32_t, vector<int32_t>> notMatchedMap;
1106     for (int32_t offset = 0; offset < totalNumber; offset += ALBUM_FUSION_BATCH_COUNT) {
1107         MEDIA_INFO_LOG("ALBUM_FUSE: handle batch clean, offset: %{public}d", offset);
1108         notMatchedMap.clear();
1109         int32_t err = QueryNoMatchedMap(upgradeStore, notMatchedMap, true);
1110         if (err != NativeRdb::E_OK) {
1111             MEDIA_ERR_LOG("Fatal error! Failed to query not matched map data");
1112             break;
1113         }
1114         if (notMatchedMap.size() != 0) {
1115             MEDIA_INFO_LOG("There are %{public}d items need to migrate", (int)notMatchedMap.size());
1116             HandleNotMatchedDataMigration(upgradeStore, notMatchedMap);
1117         }
1118     }
1119     MEDIA_INFO_LOG("ALBUM_FUSE: STEP_2: end handle not matched relationship, cost %{public}ld",
1120         (long)(MediaFileUtils::UTCTimeMilliSeconds() - beginTime));
1121     return E_OK;
1122 }
1123 
QuerySourceAlbumLPath(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,std::string & lPath,const std::string bundle_name,const std::string album_name)1124 static void QuerySourceAlbumLPath(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1125     std::string &lPath, const std::string bundle_name, const std::string album_name)
1126 {
1127     std::string queryExpiredAlbumInfo = "";
1128     if (bundle_name.empty()) {
1129         queryExpiredAlbumInfo = "SELECT lPath FROM album_plugin WHERE "
1130             "album_name = '" + album_name + "' AND priority = '1'";
1131     } else {
1132         queryExpiredAlbumInfo = "SELECT lPath FROM album_plugin WHERE bundle_name = '" + bundle_name +
1133             "' OR album_name = '" + album_name + "' AND priority = '1'";
1134     }
1135     shared_ptr<NativeRdb::ResultSet> albumPluginResultSet = upgradeStore->QuerySql(queryExpiredAlbumInfo);
1136     if (albumPluginResultSet == nullptr || albumPluginResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1137         MEDIA_INFO_LOG("Query lpath data fails, bundleName is %{public}s and albumName is %{public}s",
1138             bundle_name.c_str(), album_name.c_str());
1139         lPath = "/Pictures/" + album_name;
1140         return;
1141     }
1142     GetStringValueFromResultSet(albumPluginResultSet, PhotoAlbumColumns::ALBUM_LPATH, lPath);
1143     if (lPath.empty()) {
1144         lPath = "/Pictures/" + album_name;
1145     }
1146     MEDIA_ERR_LOG("Album lPath is %{public}s", lPath.c_str());
1147 }
1148 
BuildAlbumInsertValuesSetName(const std::shared_ptr<MediaLibraryRdbStore> & upgradeStore,NativeRdb::ValuesBucket & values,shared_ptr<NativeRdb::ResultSet> & resultSet,const string & newAlbumName)1149 void MediaLibraryAlbumFusionUtils::BuildAlbumInsertValuesSetName(
1150     const std::shared_ptr<MediaLibraryRdbStore>& upgradeStore, NativeRdb::ValuesBucket &values,
1151     shared_ptr<NativeRdb::ResultSet> &resultSet, const string &newAlbumName)
1152 {
1153     for (auto it = albumColumnTypeMap.begin(); it != albumColumnTypeMap.end(); ++it) {
1154         string columnName = it->first;
1155         ResultSetDataType columnType = it->second;
1156         ParsingAndFillValue(values, columnName, columnType, resultSet);
1157     }
1158 
1159     std::string lPath = "/Pictures/Users/" + newAlbumName;
1160     values.PutInt(PhotoAlbumColumns::ALBUM_PRIORITY, 1);
1161     values.PutString(PhotoAlbumColumns::ALBUM_LPATH, lPath);
1162     values.Delete(PhotoAlbumColumns::ALBUM_NAME);
1163     values.PutString(PhotoAlbumColumns::ALBUM_NAME, newAlbumName);
1164     int64_t albumDataAdded = 0;
1165     GetLongValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_DATE_ADDED, albumDataAdded);
1166     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_ADDED, albumDataAdded);
1167 }
1168 
BuildAlbumInsertValues(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,NativeRdb::ValuesBucket & values,const int32_t & oldAlbumId,shared_ptr<NativeRdb::ResultSet> & resultSet)1169 static int32_t BuildAlbumInsertValues(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1170     NativeRdb::ValuesBucket &values, const int32_t &oldAlbumId, shared_ptr<NativeRdb::ResultSet> &resultSet)
1171 {
1172     MEDIA_ERR_LOG("Begin build inset values Meta Data!");
1173     for (auto it = albumColumnTypeMap.begin(); it != albumColumnTypeMap.end(); ++it) {
1174         string columnName = it->first;
1175         ResultSetDataType columnType = it->second;
1176         ParsingAndFillValue(values, columnName, columnType, resultSet);
1177     }
1178 
1179     std::string lPath = "";
1180     std::string bundle_name = "";
1181     int32_t album_type = -1;
1182     std::string album_name = "";
1183     ValueObject valueObject;
1184     if (values.GetObject(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, valueObject)) {
1185         valueObject.GetString(bundle_name);
1186         if (bundle_name == "com.huawei.ohos.screenshot") {
1187             bundle_name = "com.huawei.hmos.screenshot";
1188             values.Delete(PhotoAlbumColumns::ALBUM_BUNDLE_NAME);
1189             values.PutString(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, bundle_name);
1190         }
1191         if (bundle_name == "com.huawei.ohos.screenrecorder") {
1192             bundle_name = "com.huawei.hmos.screenrecorder";
1193             values.Delete(PhotoAlbumColumns::ALBUM_BUNDLE_NAME);
1194             values.PutString(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, bundle_name);
1195         }
1196     }
1197     if (values.GetObject(PhotoAlbumColumns::ALBUM_TYPE, valueObject)) {
1198         valueObject.GetInt(album_type);
1199     }
1200     if (values.GetObject(PhotoAlbumColumns::ALBUM_NAME, valueObject)) {
1201         valueObject.GetString(album_name);
1202     }
1203     if (album_type == OHOS::Media::PhotoAlbumType::SOURCE) {
1204         QuerySourceAlbumLPath(upgradeStore, lPath, bundle_name, album_name);
1205     } else {
1206         lPath = "/Pictures/Users/" + album_name;
1207         MEDIA_INFO_LOG("Album type is user type and lPath is %{public}s!!!", lPath.c_str());
1208     }
1209     values.PutInt(PhotoAlbumColumns::ALBUM_PRIORITY, 1);
1210     values.PutString(PhotoAlbumColumns::ALBUM_LPATH, lPath);
1211     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_ADDED, MediaFileUtils::UTCTimeMilliSeconds());
1212     return E_OK;
1213 }
1214 
QueryExistsAlbumId(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,NativeRdb::ValuesBucket values,int64_t & newAlbumId)1215 static int64_t QueryExistsAlbumId(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1216     NativeRdb::ValuesBucket values, int64_t &newAlbumId)
1217 {
1218     std::string lPath = "";
1219     ValueObject valueObject;
1220     if (values.GetObject(PhotoAlbumColumns::ALBUM_LPATH, valueObject)) {
1221         valueObject.GetString(lPath);
1222     }
1223     MEDIA_ERR_LOG("Insert copyed album failed, lapth is = %{public}s", lPath.c_str());
1224     std::string queryExistsAlbumId = "SELECT album_id from PhotoAlbum where lpath ='" + lPath + "' and dirty !='4'";
1225     shared_ptr<NativeRdb::ResultSet> existsAlbumResult = upgradeStore->QuerySql(queryExistsAlbumId);
1226     if (existsAlbumResult != nullptr && existsAlbumResult->GoToFirstRow() == NativeRdb::E_OK) {
1227         MEDIA_ERR_LOG("Insert copyed album find same album = %{public}s", lPath.c_str());
1228         if (existsAlbumResult->GetLong(0, newAlbumId) != NativeRdb::E_OK) {
1229             MEDIA_ERR_LOG("Insert copyed album find same album album id is  = %{public}" PRId64, newAlbumId);
1230             return E_HAS_DB_ERROR;
1231         }
1232         MEDIA_INFO_LOG("There is an album matches new scheme, no need to insert, "
1233             "albumId : %{public}" PRId64, newAlbumId);
1234     }
1235     return E_OK;
1236 }
1237 
CopyAlbumMetaData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,std::shared_ptr<NativeRdb::ResultSet> & resultSet,const int32_t & oldAlbumId,int64_t & newAlbumId)1238 static int32_t CopyAlbumMetaData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1239     std::shared_ptr<NativeRdb::ResultSet> &resultSet, const int32_t &oldAlbumId, int64_t &newAlbumId)
1240 {
1241     MEDIA_INFO_LOG("Begin copy album Meta Data!!!");
1242     if (upgradeStore == nullptr || resultSet == nullptr || oldAlbumId == -1) {
1243         MEDIA_ERR_LOG("invalid parameter");
1244         return E_INVALID_ARGUMENTS;
1245     }
1246     NativeRdb::ValuesBucket values;
1247     int32_t err = BuildAlbumInsertValues(upgradeStore, values, oldAlbumId, resultSet);
1248     int32_t ret = upgradeStore->Insert(newAlbumId, PhotoAlbumColumns::TABLE, values);
1249     MEDIA_INFO_LOG("Insert copyed album err number  %{public}d", ret);
1250     if (ret != NativeRdb::E_OK) {
1251         if (ret == NativeRdb::E_SQLITE_CONSTRAINT) {
1252             QueryExistsAlbumId(upgradeStore, values, newAlbumId);
1253         } else {
1254             MEDIA_ERR_LOG("Insert copyed album failed, ret = %{public}d", ret);
1255             return E_HAS_DB_ERROR;
1256         }
1257     }
1258     MEDIA_INFO_LOG("Insert copyed album success,oldAlbumId is = %{public}d newAlbumId is %{public}" PRId64,
1259         oldAlbumId, newAlbumId);
1260     return ret;
1261 }
1262 
BatchDeleteAlbumAndUpdateRelation(const int32_t & oldAlbumId,const int64_t & newAlbumId,bool isCloudAblum,std::shared_ptr<TransactionOperations> trans)1263 static int32_t BatchDeleteAlbumAndUpdateRelation(const int32_t &oldAlbumId, const int64_t &newAlbumId,
1264     bool isCloudAblum, std::shared_ptr<TransactionOperations> trans)
1265 {
1266     if (trans == nullptr) {
1267         MEDIA_ERR_LOG("transactionOprn is null");
1268         return E_HAS_DB_ERROR;
1269     }
1270     std::string DELETE_EXPIRED_ALBUM = "";
1271     if (isCloudAblum) {
1272         DELETE_EXPIRED_ALBUM = "UPDATE PhotoAlbum SET dirty = '4' WHERE album_id = " + to_string(oldAlbumId);
1273     } else {
1274         DELETE_EXPIRED_ALBUM = "DELETE FROM PhotoAlbum WHERE album_id = " + to_string(oldAlbumId);
1275     }
1276     int32_t ret = trans->ExecuteSql(DELETE_EXPIRED_ALBUM);
1277     if (ret != NativeRdb::E_OK) {
1278         MEDIA_ERR_LOG("DELETE expired album failed, ret = %{public}d, albumId is %{public}d",
1279             ret, oldAlbumId);
1280         return E_HAS_DB_ERROR;
1281     }
1282     const std::string UPDATE_NEW_ALBUM_ID_IN_PHOTO_MAP = "UPDATE PhotoMap SET map_album = " +
1283         to_string(newAlbumId) + " WHERE dirty != '4' AND map_album = " + to_string(oldAlbumId);
1284     ret = trans->ExecuteSql(UPDATE_NEW_ALBUM_ID_IN_PHOTO_MAP);
1285     if (ret != NativeRdb::E_OK) {
1286         MEDIA_ERR_LOG("Update relationship in photo map fails, ret = %{public}d, albumId is %{public}d",
1287             ret, oldAlbumId);
1288         return E_HAS_DB_ERROR;
1289     }
1290     const std::string UPDATE_NEW_ALBUM_ID_IN_PHOTOS = "UPDATE Photos SET owner_album_id = " +
1291         to_string(newAlbumId) + " WHERE dirty != '4' AND owner_album_id = " + to_string(oldAlbumId);
1292     ret = trans->ExecuteSql(UPDATE_NEW_ALBUM_ID_IN_PHOTOS);
1293     if (ret != NativeRdb::E_OK) {
1294         MEDIA_ERR_LOG("Update relationship in photo map fails, ret = %{public}d, albumId is %{public}d",
1295             ret, oldAlbumId);
1296         return E_HAS_DB_ERROR;
1297     }
1298     return E_OK;
1299 }
1300 
DeleteAlbumAndUpdateRelationship(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,const int32_t & oldAlbumId,const int64_t & newAlbumId,bool isCloudAblum)1301 int32_t MediaLibraryAlbumFusionUtils::DeleteAlbumAndUpdateRelationship(
1302     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore, const int32_t &oldAlbumId, const int64_t &newAlbumId,
1303     bool isCloudAblum)
1304 {
1305     if (upgradeStore == nullptr) {
1306         MEDIA_ERR_LOG("invalid rdbstore or nullptr map");
1307         return E_INVALID_ARGUMENTS;
1308     }
1309     if (newAlbumId == -1) {
1310         MEDIA_ERR_LOG("Target album id error, origin albumId is %{public}d", oldAlbumId);
1311         return E_INVALID_ARGUMENTS;
1312     }
1313 
1314     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
1315     int32_t errCode = E_OK;
1316     std::function<int(void)> func = [&]()->int {
1317         return BatchDeleteAlbumAndUpdateRelation(oldAlbumId, newAlbumId, isCloudAblum, trans);
1318     };
1319     errCode = trans->RetryTrans(func);
1320     if (errCode != E_OK) {
1321         MEDIA_ERR_LOG("DeleteAlbumAndUpdateRelationship trans retry fail!, ret = %{public}d", errCode);
1322     }
1323     return errCode;
1324 }
1325 
IsCloudAlbum(shared_ptr<NativeRdb::ResultSet> resultSet)1326 bool MediaLibraryAlbumFusionUtils::IsCloudAlbum(shared_ptr<NativeRdb::ResultSet> resultSet)
1327 {
1328     string cloudId = "";
1329     GetStringValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_CLOUD_ID, cloudId);
1330     return !cloudId.empty();
1331 }
1332 
HandleExpiredAlbumData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1333 int32_t MediaLibraryAlbumFusionUtils::HandleExpiredAlbumData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1334 {
1335     if (upgradeStore == nullptr) {
1336         MEDIA_ERR_LOG("invalid rdbstore or nullptr map");
1337         return E_INVALID_ARGUMENTS;
1338     }
1339     const std::string QUERY_EXPIRED_ALBUM_INFO =
1340         "SELECT * FROM PhotoAlbum WHERE (album_type = 2048 OR album_type = 0) "
1341         "AND cloud_id not like '%default-album%' AND (lpath IS NULL OR lpath = '') AND dirty != 4";
1342     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_EXPIRED_ALBUM_INFO);
1343     if (resultSet == nullptr) {
1344         MEDIA_ERR_LOG("Query not matched data fails");
1345         return E_HAS_DB_ERROR;
1346     }
1347     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1348         int32_t oldAlbumId = -1;
1349         int64_t newAlbumId = -1;
1350         GetIntValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_ID, oldAlbumId);
1351         CopyAlbumMetaData(upgradeStore, resultSet, oldAlbumId, newAlbumId);
1352         DeleteAlbumAndUpdateRelationship(upgradeStore, oldAlbumId, newAlbumId, IsCloudAlbum(resultSet));
1353         MEDIA_ERR_LOG("Finish handle old album %{public}d, new inserted album id is %{public}" PRId64,
1354             oldAlbumId, newAlbumId);
1355     }
1356     return E_OK;
1357 }
1358 
KeepHiddenAlbumAssetSynced(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1359 static int32_t KeepHiddenAlbumAssetSynced(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1360 {
1361     if (upgradeStore == nullptr) {
1362         MEDIA_INFO_LOG("fail to get rdbstore");
1363         return E_DB_FAIL;
1364     }
1365     const std::string UPDATE_DIRTY_FLAG_FOR_DUAL_HIDDEN_ASSET =
1366     "UPDATE " + PhotoColumn::PHOTOS_TABLE + " SET dirty = 0 WHERE owner_album_id ="
1367         "(SELECT album_id FROM PhotoALbum where (cloud_id = "
1368         "'default-album-4' OR album_name = '.hiddenAlbum') and dirty != 4)";
1369     int32_t err = upgradeStore->ExecuteSql(UPDATE_DIRTY_FLAG_FOR_DUAL_HIDDEN_ASSET);
1370     if (err != NativeRdb::E_OK) {
1371         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s",
1372             UPDATE_DIRTY_FLAG_FOR_DUAL_HIDDEN_ASSET.c_str());
1373         return err;
1374     }
1375     return E_OK;
1376 }
1377 
RemediateErrorSourceAlbumSubType(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1378 static int32_t RemediateErrorSourceAlbumSubType(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1379 {
1380     if (upgradeStore == nullptr) {
1381         MEDIA_INFO_LOG("fail to get rdbstore");
1382         return E_DB_FAIL;
1383     }
1384     const std::string REMEDIATE_ERROR_SOURCE_ALBUM_SUBTYPE =
1385         "UPDATE " + PhotoAlbumColumns::TABLE + " SET album_subtype = 2049 "
1386         "WHERE album_type = 2048 and album_subtype <> 2049";
1387     int32_t err = upgradeStore->ExecuteSql(REMEDIATE_ERROR_SOURCE_ALBUM_SUBTYPE);
1388     if (err != NativeRdb::E_OK) {
1389         MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s",
1390             REMEDIATE_ERROR_SOURCE_ALBUM_SUBTYPE.c_str());
1391         return err;
1392     }
1393     return E_OK;
1394 }
1395 
RebuildAlbumAndFillCloudValue(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1396 int32_t MediaLibraryAlbumFusionUtils::RebuildAlbumAndFillCloudValue(
1397     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1398 {
1399     MEDIA_INFO_LOG("Start rebuild album table and compensate loss value");
1400     if (upgradeStore == nullptr) {
1401         MEDIA_INFO_LOG("fail to get rdbstore");
1402         return E_DB_FAIL;
1403     }
1404     int32_t err = HandleChangeNameAlbum(upgradeStore);
1405     CompensateLpathForLocalAlbum(upgradeStore);
1406     HandleExpiredAlbumData(upgradeStore);
1407     // Keep dual hidden assets dirty state synced, let cloudsync handle compensating for hidden flags
1408     KeepHiddenAlbumAssetSynced(upgradeStore);
1409     RemediateErrorSourceAlbumSubType(upgradeStore);
1410     HandleMisMatchScreenRecord(upgradeStore);
1411     int32_t albumAffectedCount = PhotoAlbumLPathOperation::GetInstance()
1412                                      .SetRdbStore(upgradeStore)
1413                                      .Start()
1414                                      .CleanInvalidPhotoAlbums()
1415                                      .CleanDuplicatePhotoAlbums()
1416                                      .CleanEmptylPathPhotoAlbums()
1417                                      .GetAlbumAffectedCount();
1418     MediaLibraryAlbumFusionUtils::SetRefreshAlbum(albumAffectedCount > 0);
1419     MEDIA_INFO_LOG("End rebuild album table and compensate loss value");
1420     return E_OK;
1421 }
1422 
MergeClashSourceAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,shared_ptr<NativeRdb::ResultSet> & resultSet,const int32_t & sourceAlbumId,const int64_t & targetAlbumId)1423 int32_t MediaLibraryAlbumFusionUtils::MergeClashSourceAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1424     shared_ptr<NativeRdb::ResultSet> &resultSet, const int32_t &sourceAlbumId, const int64_t &targetAlbumId)
1425 {
1426     if (upgradeStore == nullptr) {
1427         MEDIA_INFO_LOG("fail to get rdbstore");
1428         return E_DB_FAIL;
1429     }
1430     MEDIA_INFO_LOG("MergeClashSourceAlbum %{public}d, target album is %{public}" PRId64,
1431         sourceAlbumId, targetAlbumId);
1432     if (sourceAlbumId == targetAlbumId) {
1433         return E_OK;
1434     }
1435 
1436     DeleteAlbumAndUpdateRelationship(upgradeStore, sourceAlbumId, targetAlbumId, IsCloudAlbum(resultSet));
1437     return E_OK;
1438 }
1439 
MergeScreenShotAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,shared_ptr<NativeRdb::ResultSet> & resultSet)1440 static int32_t MergeScreenShotAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1441     shared_ptr<NativeRdb::ResultSet> &resultSet)
1442 {
1443     if (upgradeStore == nullptr) {
1444         MEDIA_INFO_LOG("fail to get rdbstore");
1445         return E_DB_FAIL;
1446     }
1447     MEDIA_INFO_LOG("Begin handle expired screen shot album data ");
1448     int32_t oldAlbumId = -1;
1449     int64_t newAlbumId = -1;
1450     GetIntValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_ID, oldAlbumId);
1451     const std::string QUERY_NEW_SCREEN_SHOT_ALBUM_INFO =
1452         "SELECT * FROM PhotoAlbum WHERE album_type = 2048 AND bundle_name = 'com.huawei.hmos.screenshot'"
1453         " AND dirty != 4";
1454     shared_ptr<NativeRdb::ResultSet> newAlbumResultSet = upgradeStore->QuerySql(QUERY_NEW_SCREEN_SHOT_ALBUM_INFO);
1455     MEDIA_INFO_LOG("Begin merge screenshot album, old album is %{public}d", oldAlbumId);
1456     if (newAlbumResultSet == nullptr || newAlbumResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1457         // Create a new bundle name screenshot album
1458         CopyAlbumMetaData(upgradeStore, resultSet, oldAlbumId, newAlbumId);
1459         MEDIA_INFO_LOG("Create new screenshot album, album id is %{public}" PRId64, newAlbumId);
1460     } else {
1461         GetLongValueFromResultSet(newAlbumResultSet, PhotoAlbumColumns::ALBUM_ID, newAlbumId);
1462     }
1463     MEDIA_INFO_LOG("Begin merge screenshot album, new album is %{public}" PRId64, newAlbumId);
1464     MediaLibraryAlbumFusionUtils::MergeClashSourceAlbum(upgradeStore, resultSet, oldAlbumId, newAlbumId);
1465     MEDIA_INFO_LOG("End handle expired screen shot album data ");
1466     return E_OK;
1467 }
1468 
MergeScreenRecordAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,shared_ptr<NativeRdb::ResultSet> & resultSet)1469 static int32_t MergeScreenRecordAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1470     shared_ptr<NativeRdb::ResultSet> &resultSet)
1471 {
1472     if (upgradeStore == nullptr) {
1473         MEDIA_INFO_LOG("fail to get rdbstore");
1474         return E_DB_FAIL;
1475     }
1476     MEDIA_INFO_LOG("Begin merge screenrecord album");
1477     int32_t oldAlbumId = -1;
1478     int64_t newAlbumId = -1;
1479     GetIntValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_ID, oldAlbumId);
1480     const std::string QUERY_NEW_SCREEN_RECORD_ALBUM_INFO =
1481         "SELECT * FROM PhotoAlbum WHERE album_type = 2048 AND bundle_name = 'com.huawei.hmos.screenrecorder'"
1482         " AND dirty != 4";
1483     shared_ptr<NativeRdb::ResultSet> newAlbumResultSet = upgradeStore->QuerySql(QUERY_NEW_SCREEN_RECORD_ALBUM_INFO);
1484     if (newAlbumResultSet == nullptr || newAlbumResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1485         // Create a new bundle name screenshot album
1486         CopyAlbumMetaData(upgradeStore, resultSet, oldAlbumId, newAlbumId);
1487         MEDIA_INFO_LOG("Create new screenrecord album, album id is %{public}" PRId64, newAlbumId);
1488     } else {
1489         GetLongValueFromResultSet(newAlbumResultSet, PhotoAlbumColumns::ALBUM_ID, newAlbumId);
1490     }
1491     MediaLibraryAlbumFusionUtils::MergeClashSourceAlbum(upgradeStore, resultSet, oldAlbumId, newAlbumId);
1492     MEDIA_INFO_LOG("End merge screenrecord album");
1493     return E_OK;
1494 }
1495 
HandleChangeNameAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1496 int32_t MediaLibraryAlbumFusionUtils::HandleChangeNameAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1497 {
1498     MEDIA_INFO_LOG("Begin handle change name album data");
1499     if (upgradeStore == nullptr) {
1500         MEDIA_ERR_LOG("invalid rdbstore or nullptr map");
1501         return E_INVALID_ARGUMENTS;
1502     }
1503     const std::string QUERY_CHANGE_NAME_ALBUM_INFO =
1504         "SELECT * FROM PhotoAlbum WHERE album_type = 2048"
1505         " AND (bundle_name = 'com.huawei.ohos.screenshot' OR bundle_name = 'com.huawei.ohos.screenrecorder')"
1506         " AND dirty != 4";
1507     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_CHANGE_NAME_ALBUM_INFO);
1508     if (resultSet == nullptr) {
1509         MEDIA_ERR_LOG("Query expired bundle_name fails");
1510         return E_HAS_DB_ERROR;
1511     }
1512     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1513         std::string bundle_name = "";
1514         GetStringValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_BUNDLE_NAME, bundle_name);
1515         if (bundle_name == "com.huawei.ohos.screenshot") {
1516             MergeScreenShotAlbum(upgradeStore, resultSet);
1517         } else {
1518             MergeScreenRecordAlbum(upgradeStore, resultSet);
1519         }
1520     }
1521     MEDIA_INFO_LOG("End handle change name album data");
1522     return E_OK;
1523 }
1524 
CompensateLpathForLocalAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1525 int32_t MediaLibraryAlbumFusionUtils::CompensateLpathForLocalAlbum(
1526     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1527 {
1528     MEDIA_INFO_LOG("Begin compensate Lpath for local album");
1529     if (upgradeStore == nullptr) {
1530         MEDIA_ERR_LOG("invalid rdbstore or nullptr map");
1531         return E_INVALID_ARGUMENTS;
1532     }
1533     const std::string QUERY_COMPENSATE_ALBUM_INFO =
1534         "SELECT * FROM PhotoAlbum WHERE cloud_id IS NULL"
1535         " AND (priority IS NULL OR lpath IS NULL) AND dirty != 4 AND album_type IN (0, 2048)";
1536     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_COMPENSATE_ALBUM_INFO);
1537     if (resultSet == nullptr) {
1538         MEDIA_ERR_LOG("Query album info fails");
1539         return E_HAS_DB_ERROR;
1540     }
1541 
1542     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1543         int album_id = -1;
1544         int32_t album_type = -1;
1545         std::string album_name = "";
1546         std::string bundle_name = "";
1547         std::string lpath = "";
1548 
1549         GetIntValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_ID, album_id);
1550         GetIntValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_TYPE, album_type);
1551         GetStringValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_NAME, album_name);
1552         GetStringValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_BUNDLE_NAME, bundle_name);
1553         GetStringValueFromResultSet(resultSet, PhotoAlbumColumns::ALBUM_LPATH, lpath);
1554 
1555         if (lpath.empty()) {
1556             if (album_type == OHOS::Media::PhotoAlbumType::SOURCE) {
1557                 QuerySourceAlbumLPath(upgradeStore, lpath, bundle_name, album_name);
1558             } else {
1559                 lpath = "/Pictures/Users/" + album_name;
1560                 MEDIA_INFO_LOG("Album type is user type and lPath is %{public}s!!!", lpath.c_str());
1561             }
1562         }
1563 
1564         const std::string UPDATE_COMPENSATE_ALBUM_DATA =
1565             "UPDATE PhotoAlbum SET lpath = '" + lpath + "', "
1566             "priority = COALESCE ((SELECT priority FROM album_plugin WHERE lpath = '" + lpath + "'), 1) "
1567             "WHERE album_id = " + to_string(album_id);
1568         int32_t err = upgradeStore->ExecuteSql(UPDATE_COMPENSATE_ALBUM_DATA);
1569         if (err != NativeRdb::E_OK) {
1570             MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s", UPDATE_COMPENSATE_ALBUM_DATA.c_str());
1571             continue;
1572         }
1573     }
1574     MEDIA_INFO_LOG("End compensate Lpath for local album");
1575     return E_OK;
1576 }
1577 
SetParameterToStopSync()1578 void MediaLibraryAlbumFusionUtils::SetParameterToStopSync()
1579 {
1580     auto currentTime = to_string(MediaFileUtils::UTCTimeSeconds());
1581     MEDIA_INFO_LOG("Set parameter for album fusion currentTime:%{public}s", currentTime.c_str());
1582     bool retFlag = system::SetParameter(ALBUM_FUSION_FLAG, currentTime);
1583     if (!retFlag) {
1584         MEDIA_ERR_LOG("Failed to set parameter cloneFlag, retFlag:%{public}d", retFlag);
1585     }
1586 }
1587 
SetParameterToStartSync()1588 void MediaLibraryAlbumFusionUtils::SetParameterToStartSync()
1589 {
1590     MEDIA_INFO_LOG("Reset parameter for album fusion");
1591     bool retFlag = system::SetParameter(ALBUM_FUSION_FLAG, "0");
1592     if (!retFlag) {
1593         MEDIA_ERR_LOG("Failed to Set parameter for album fusion, retFlag:%{public}d", retFlag);
1594     }
1595 }
1596 
GetAlbumFuseUpgradeStatus()1597 int32_t MediaLibraryAlbumFusionUtils::GetAlbumFuseUpgradeStatus()
1598 {
1599     std::string albumFuseUpgradeStatus = system::GetParameter(ALBUM_FUSION_UPGRADE_STATUS_FLAG, "1");
1600     MEDIA_ERR_LOG("Current album upgrade status :%{public}s", albumFuseUpgradeStatus.c_str());
1601     if (albumFuseUpgradeStatus == "1") {
1602         return ALBUM_FUSION_UPGRADE_SUCCESS;
1603     } else {
1604         return ALBUM_FUSION_UPGRADE_FAIL;
1605     }
1606 }
1607 
SetAlbumFuseUpgradeStatus(int32_t upgradeStatus)1608 int32_t MediaLibraryAlbumFusionUtils::SetAlbumFuseUpgradeStatus(int32_t upgradeStatus)
1609 {
1610     if (upgradeStatus != ALBUM_FUSION_UPGRADE_SUCCESS && upgradeStatus != ALBUM_FUSION_UPGRADE_FAIL) {
1611         MEDIA_ERR_LOG("Invalid parameter for album fusion upgrade status :%{public}d", upgradeStatus);
1612         return E_INVALID_ARGUMENTS;
1613     }
1614     MEDIA_INFO_LOG("Set parameter for album fusion upgrade status :%{public}d", upgradeStatus);
1615     bool retFlag = system::SetParameter(ALBUM_FUSION_UPGRADE_STATUS_FLAG, to_string(upgradeStatus));
1616     if (!retFlag) {
1617         MEDIA_ERR_LOG("Failed to set parameter, retFlag:%{public}d", retFlag);
1618         return E_INVALID_MODE;
1619     }
1620     return E_OK;
1621 }
1622 
ToLower(const std::string & str)1623 static std::string ToLower(const std::string &str)
1624 {
1625     std::string lowerStr;
1626     std::transform(
1627         str.begin(), str.end(), std::back_inserter(lowerStr), [](unsigned char c) { return std::tolower(c); });
1628     return lowerStr;
1629 }
1630 
DeleteDuplicatePhoto(const std::shared_ptr<MediaLibraryRdbStore> store)1631 static int32_t DeleteDuplicatePhoto(const std::shared_ptr<MediaLibraryRdbStore> store)
1632 {
1633     const string sql = "UPDATE Photos SET dirty = 8 WHERE file_id IN ( " +
1634         SQL_GET_DUPLICATE_PHOTO + " )";
1635 
1636     int32_t err = store->ExecuteSql(sql);
1637     if (err != NativeRdb::E_OK) {
1638         MEDIA_ERR_LOG("DeleteDuplicatePhoto fail %{public}d", err);
1639     }
1640     return err;
1641 }
1642 
DuplicateDebugPrint(const vector<int32_t> & idArr)1643 void DuplicateDebugPrint(const vector<int32_t> &idArr)
1644 {
1645     constexpr int32_t maxPrintWidth = 50;
1646     string assetStr;
1647     for (auto assetId: idArr) {
1648         assetStr += to_string(assetId) + ",";
1649         if (assetStr.size() > maxPrintWidth) {
1650             MEDIA_DEBUG_LOG("delete dup photo %{public}s", assetStr.c_str());
1651             assetStr = "";
1652         }
1653     }
1654     if (assetStr.size() != 0) {
1655         MEDIA_DEBUG_LOG("delete dup photo %{public}s", assetStr.c_str());
1656     }
1657 }
1658 
DuplicateDebug(std::shared_ptr<NativeRdb::ResultSet> resultSet,vector<int32_t> & idArr)1659 void DuplicateDebug(std::shared_ptr<NativeRdb::ResultSet> resultSet, vector<int32_t> &idArr)
1660 {
1661     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1662         int32_t colIndex = -1;
1663         int32_t assetId = 0;
1664         resultSet->GetColumnIndex(MediaColumn::MEDIA_ID, colIndex);
1665         if (resultSet->GetInt(colIndex, assetId) != NativeRdb::E_OK) {
1666             MEDIA_ERR_LOG("db error");
1667             break;
1668         }
1669         idArr.push_back(assetId);
1670     }
1671 }
1672 
HandleDuplicatePhoto(const std::shared_ptr<MediaLibraryRdbStore> store)1673 static int32_t HandleDuplicatePhoto(const std::shared_ptr<MediaLibraryRdbStore> store)
1674 {
1675     int32_t row = 0;
1676     int32_t count = 0;
1677     // set max loop count to avoid trapped in loop if delete fail
1678     constexpr int32_t maxLoopCount = 1000;
1679     do {
1680         count++;
1681         shared_ptr<NativeRdb::ResultSet> resultSet = store->QuerySql(SQL_GET_DUPLICATE_PHOTO);
1682         if (resultSet == nullptr || resultSet->GetRowCount(row) != NativeRdb::E_OK) {
1683             MEDIA_INFO_LOG("rdb fail");
1684             return E_DB_FAIL;
1685         }
1686         MEDIA_INFO_LOG("duplicate photo %{public}d, need to delete", row);
1687         if (row == 0) {
1688             return E_OK;
1689         }
1690         vector<int32_t> idArr;
1691         DuplicateDebug(resultSet, idArr);
1692         auto err = DeleteDuplicatePhoto(store);
1693         if (err == NativeRdb::E_OK) {
1694             DuplicateDebugPrint(idArr);
1695         } else {
1696             MEDIA_ERR_LOG("duplicate photo %{public}d, delete fail %{public}d", row, err);
1697         }
1698     } while (row > 0 && count < maxLoopCount);
1699 
1700     return E_OK;
1701 }
1702 
HandleDuplicateAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1703 int32_t MediaLibraryAlbumFusionUtils::HandleDuplicateAlbum(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1704 {
1705     MEDIA_INFO_LOG("Media_Operation: Skip HandleDuplicateAlbum.");
1706     return E_OK;
1707 }
1708 
HandleNewCloudDirtyDataImp(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,shared_ptr<NativeRdb::ResultSet> & resultSet,std::vector<int32_t> & restOwnerAlbumIds,int32_t & assetId)1709 static void HandleNewCloudDirtyDataImp(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1710     shared_ptr<NativeRdb::ResultSet> &resultSet, std::vector<int32_t> &restOwnerAlbumIds, int32_t &assetId)
1711 {
1712     int64_t newAssetId = -1;
1713     if (isLocalAsset(resultSet)) {
1714         MEDIA_INFO_LOG("File is local asset %{public}d", assetId);
1715         // skip first one, already handled
1716         for (size_t i = 0; i < restOwnerAlbumIds.size(); i++) {
1717             int32_t err = MediaLibraryAlbumFusionUtils::CopyLocalSingleFile(upgradeStore,
1718                 restOwnerAlbumIds[i], resultSet, newAssetId);
1719             if (err != E_OK) {
1720                 MEDIA_WARN_LOG("Copy file fails, fileId is %{public}d", assetId);
1721                 continue;
1722             }
1723             MEDIA_INFO_LOG("Copy file success, fileId is %{public}d, albumId is %{public}d",
1724                 assetId, restOwnerAlbumIds[i]);
1725         }
1726     } else {
1727         MEDIA_INFO_LOG("File is cloud asset %{public}d", assetId);
1728         // skip first one, already handled
1729         for (size_t i = 0; i < restOwnerAlbumIds.size(); i++) {
1730             int32_t err = MediaLibraryAlbumFusionUtils::CopyCloudSingleFile(upgradeStore,
1731                 assetId, restOwnerAlbumIds[i], resultSet, newAssetId);
1732             if (err != E_OK) {
1733                 MEDIA_WARN_LOG("Copy cloud file fails, fileId is %{public}d", assetId);
1734                 continue;
1735             }
1736             MEDIA_INFO_LOG("Copy cloud file success, fileId is %{public}d, albumId is %{public}d",
1737                 assetId, restOwnerAlbumIds[i]);
1738         }
1739     }
1740 }
1741 
HandleNewCloudDirtyData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,std::multimap<int32_t,vector<int32_t>> & notMathedMap)1742 int32_t MediaLibraryAlbumFusionUtils::HandleNewCloudDirtyData(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore,
1743     std::multimap<int32_t, vector<int32_t>> &notMathedMap)
1744 {
1745     if (upgradeStore == nullptr) {
1746         MEDIA_ERR_LOG("invalid rdbstore or nullptr map");
1747         return E_INVALID_ARGUMENTS;
1748     }
1749     for (auto it = notMathedMap.begin(); it != notMathedMap.end(); ++it) {
1750         int32_t assetId = it->first;
1751         std::vector<int32_t> &restOwnerAlbumIds = it->second;
1752         const std::string QUERY_FILE_META_INFO =
1753             "SELECT * FROM Photos WHERE file_id = " + to_string(assetId);
1754         shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_FILE_META_INFO);
1755         if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1756             MEDIA_INFO_LOG("Query not matched data fails");
1757             return E_DB_FAIL;
1758         }
1759         HandleNewCloudDirtyDataImp(upgradeStore, resultSet, restOwnerAlbumIds, assetId);
1760     }
1761     return E_OK;
1762 }
1763 
TransferMisMatchScreenRecord(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1764 static int32_t TransferMisMatchScreenRecord(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1765 {
1766     MEDIA_INFO_LOG("Transfer miss matched screeRecord begin");
1767     const std::string QUERY_SCREEN_RECORD_ALBUM =
1768         "SELECT album_id FROM PhotoAlbum WHERE bundle_name ='com.huawei.hmos.screenrecorder' AND dirty <>4";
1769     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_SCREEN_RECORD_ALBUM);
1770     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1771         MEDIA_INFO_LOG("No screen record album");
1772         const std::string CREATE_SCREEN_RECORDS_ALBUM =
1773             "INSERT INTO " + PhotoAlbumColumns::TABLE +
1774             "(album_type, album_subtype, album_name,bundle_name, dirty, is_local, date_added, lpath, priority)"
1775             " Values ('2048', '2049', '屏幕录制', 'com.huawei.hmos.screenrecorder', '1', '1',"
1776             " strftime('%s000', 'now'), '/Pictures/Screenrecords', '1')";
1777         int32_t err = upgradeStore->ExecuteSql(CREATE_SCREEN_RECORDS_ALBUM);
1778         if (err != NativeRdb::E_OK) {
1779             MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s",
1780                 CREATE_SCREEN_RECORDS_ALBUM.c_str());
1781             return err;
1782         }
1783     }
1784     const std::string TRANSFER_MISS_MATCH_ASSET =
1785         "UPDATE Photos SET owner_album_id = "
1786         "(SELECT album_id FROM PhotoAlbum WHERE bundle_name ='com.huawei.hmos.screenrecorder' AND dirty <>4) "
1787         "WHERE owner_album_id = (SELECT album_id FROM PhotoAlbum WHERE "
1788         "bundle_name ='com.huawei.hmos.screenshot' AND dirty <>'4' limit 1) AND media_type =2";
1789     int32_t err = upgradeStore->ExecuteSql(TRANSFER_MISS_MATCH_ASSET);
1790         if (err != NativeRdb::E_OK) {
1791             MEDIA_ERR_LOG("Fatal error! Failed to exec: %{public}s",
1792                 TRANSFER_MISS_MATCH_ASSET.c_str());
1793             return err;
1794     }
1795     MEDIA_INFO_LOG("Transfer miss matched screenRecord end");
1796     return E_OK;
1797 }
1798 
HandleMisMatchScreenRecord(const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)1799 int32_t MediaLibraryAlbumFusionUtils::HandleMisMatchScreenRecord(
1800     const std::shared_ptr<MediaLibraryRdbStore> upgradeStore)
1801 {
1802     if (upgradeStore == nullptr) {
1803         MEDIA_ERR_LOG("invalid rdbstore");
1804         return E_INVALID_ARGUMENTS;
1805     }
1806     const std::string QUERY_MISS_MATCHED_RECORDS =
1807         "SELECT file_id FROM Photos WHERE owner_album_id = "
1808         "(SELECT album_id FROM PhotoAlbum WHERE bundle_name ='com.huawei.hmos.screenshot' AND dirty <>4) "
1809         " AND media_type =2";
1810     shared_ptr<NativeRdb::ResultSet> resultSet = upgradeStore->QuerySql(QUERY_MISS_MATCHED_RECORDS);
1811     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1812         MEDIA_INFO_LOG("No miss matched screen record");
1813         return E_OK;
1814     }
1815     return TransferMisMatchScreenRecord(upgradeStore);
1816 }
1817 
RefreshAllAlbums()1818 int32_t MediaLibraryAlbumFusionUtils::RefreshAllAlbums()
1819 {
1820     MEDIA_INFO_LOG("Froce refresh all albums start");
1821     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1822     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore);
1823     auto watch = MediaLibraryNotify::GetInstance();
1824     if (watch == nullptr) {
1825         MEDIA_ERR_LOG("Can not get MediaLibraryNotify Instance");
1826         return E_ERR;
1827     }
1828     watch->Notify(PhotoAlbumColumns::ALBUM_URI_PREFIX, NotifyType::NOTIFY_UPDATE);
1829     MEDIA_INFO_LOG("Froce refresh all albums end");
1830     return E_OK;
1831 }
1832 
CleanInvalidCloudAlbumAndData()1833 int32_t MediaLibraryAlbumFusionUtils::CleanInvalidCloudAlbumAndData()
1834 {
1835     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1836     if (rdbStore == nullptr) {
1837         MEDIA_ERR_LOG("Failed to get rdbstore, try again!");
1838         rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1839         if (rdbStore == nullptr) {
1840             MEDIA_ERR_LOG("Fatal error! Failed to get rdbstore, new cloud data is not processed!!");
1841             return E_DB_FAIL;
1842         }
1843     }
1844     if (GetAlbumFuseUpgradeStatus() != ALBUM_FUSION_UPGRADE_SUCCESS) {
1845         MEDIA_ERR_LOG("ALBUM_FUSE: First upgrade fails, perform upgrade again.");
1846         MediaLibraryRdbStore::ReconstructMediaLibraryStorageFormat(rdbStore);
1847         return E_OK;
1848     }
1849     std::unique_lock<std::mutex> cloudAlbumAndDataUniqueLock(
1850         MediaLibraryAlbumFusionUtils::cloudAlbumAndDataMutex_, std::defer_lock);
1851     if (!cloudAlbumAndDataUniqueLock.try_lock()) {
1852         MEDIA_WARN_LOG("ALBUM_FUSE: Failed to acquire lock, skipping task Clean.");
1853         return E_OK;
1854     }
1855     int64_t beginTime = MediaFileUtils::UTCTimeMilliSeconds();
1856     MEDIA_INFO_LOG("DATA_CLEAN:Clean invalid cloud album and dirty data start!");
1857     SetParameterToStopSync();
1858     int32_t totalNumber = QueryTotalNumberNeedToHandle(rdbStore, QUERY_NEW_NOT_MATCHED_COUNT_IN_PHOTOMAP);
1859     MEDIA_INFO_LOG("QueryTotalNumberNeedToHandle, totalNumber=%{public}d", totalNumber);
1860     SetRefreshAlbum(totalNumber > 0);
1861     std::multimap<int32_t, vector<int32_t>> notMatchedMap;
1862     for (int32_t offset = 0; offset < totalNumber; offset += ALBUM_FUSION_BATCH_COUNT) {
1863         MEDIA_INFO_LOG("DATA_CLEAN: handle batch clean, offset: %{public}d", offset);
1864         notMatchedMap.clear();
1865         int32_t err = QueryNoMatchedMap(rdbStore, notMatchedMap, false);
1866         if (err != NativeRdb::E_OK) {
1867             MEDIA_ERR_LOG("Fatal error! Failed to query not matched map data");
1868             break;
1869         }
1870         if (notMatchedMap.size() != 0) {
1871             MEDIA_INFO_LOG("There are %{public}d items need to migrate", (int)notMatchedMap.size());
1872             HandleNewCloudDirtyData(rdbStore, notMatchedMap);
1873         }
1874     }
1875     HandleDuplicateAlbum(rdbStore);
1876     HandleDuplicatePhoto(rdbStore);
1877     // Put no relationship asset into other album
1878     HandleNoOwnerData(rdbStore);
1879     // Clean duplicative album and rebuild expired album
1880     RebuildAlbumAndFillCloudValue(rdbStore);
1881     SetParameterToStartSync();
1882     if (isNeedRefreshAlbum.load() == true) {
1883         RefreshAllAlbums();
1884         isNeedRefreshAlbum = false;
1885     }
1886     PhotoSourcePathOperation().ResetPhotoSourcePath(rdbStore);
1887     MEDIA_INFO_LOG("DATA_CLEAN:Clean invalid cloud album and dirty data, cost %{public}ld",
1888         (long)(MediaFileUtils::UTCTimeMilliSeconds() - beginTime));
1889     return E_OK;
1890 }
1891 
QueryCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,const string & sql,const string & column)1892 static int QueryCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, const string& sql, const string& column)
1893 {
1894     if (rdbStore == nullptr) {
1895         MEDIA_INFO_LOG("fail to get rdbstore");
1896         return -1;
1897     }
1898     auto resultSet = rdbStore->QueryByStep(sql);
1899     if (resultSet == nullptr) {
1900         MEDIA_ERR_LOG("Query failed, failed when executing sql: %{public}s", sql.c_str());
1901         return -1;
1902     }
1903     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1904         MEDIA_ERR_LOG("Query result go to first row failed, sql: %{public}s", sql.c_str());
1905         return -1;
1906     }
1907     return GetInt32Val(column, resultSet);
1908 }
1909 
ReportAlbumFusionData(int64_t albumFusionTag,AlbumFusionState albumFusionState,const std::shared_ptr<MediaLibraryRdbStore> rdbStore)1910 void MediaLibraryAlbumFusionUtils::ReportAlbumFusionData(int64_t albumFusionTag, AlbumFusionState albumFusionState,
1911     const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
1912 {
1913     AlbumFusionDfxDataPoint dataPoint;
1914     dataPoint.albumFusionTag = albumFusionTag;
1915     dataPoint.reportTimeStamp = MediaFileUtils::UTCTimeMilliSeconds();
1916     dataPoint.albumFusionState = static_cast<int32_t>(albumFusionState);
1917     MEDIA_INFO_LOG("ALBUM_FUSE: Report album fusion data start, tag is %{public}" PRId64 ", fusion state is %{public}d",
1918         albumFusionTag, static_cast<int32_t>(albumFusionState));
1919 
1920     dataPoint.imageAssetCount = QueryCount(rdbStore,
1921         "SELECT count FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::IMAGE),
1922         "count");
1923     dataPoint.videoAssetCount = QueryCount(rdbStore,
1924         "SELECT count FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::VIDEO),
1925         "count");
1926     dataPoint.numberOfSourceAlbum = QueryCount(rdbStore,
1927         "SELECT count(*) FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::SOURCE_GENERIC),
1928         "count(*)");
1929     dataPoint.numberOfUserAlbum = QueryCount(rdbStore,
1930         "SELECT count(*) FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::USER_GENERIC),
1931         "count(*)");
1932     dataPoint.totalAssetsInSourceAlbums = QueryCount(rdbStore,
1933         "SELECT sum(count) FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::SOURCE_GENERIC),
1934         "sum(count)");
1935     dataPoint.totalAssetsInUserAlbums = QueryCount(rdbStore,
1936         "SELECT sum(count) FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::USER_GENERIC),
1937         "sum(count)");
1938     dataPoint.albumDetails = "";
1939     int32_t hiddenAssetCount = QueryCount(rdbStore,
1940         "SELECT count FROM PhotoAlbum WHERE album_subtype = " + to_string(PhotoAlbumSubType::HIDDEN),
1941         "count");
1942     int32_t dotHiddenAlbumAssetCount = QueryCount(rdbStore,
1943         "SELECT count FROM PhotoAlbum WHERE album_name = '.hiddenAlbum' AND dirty <> 4 AND album_subtype = " +
1944             to_string(PhotoAlbumSubType::SOURCE_GENERIC),
1945         "count");
1946     dataPoint.hiddenAssetInfo = "{hidden assets: " + to_string(hiddenAssetCount) + ", .hiddenAlbum assets: " +
1947         to_string(dotHiddenAlbumAssetCount) + "}";
1948 
1949     DfxReporter::ReportAlbumFusion(dataPoint);
1950     MEDIA_INFO_LOG("ALBUM_FUSE: Report album fusion data end, tag is %{public}" PRId64 ", fusion state is %{public}d",
1951         albumFusionTag, albumFusionState);
1952 }
1953 } // namespace OHOS::Media