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>> ¬MathedMap, 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 ©Info)
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 ©Info)
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>> ¬MathedMap)
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>> ¬MathedMap)
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