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