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