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