• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "medialibrary_album_fusion_utils.h"
17 
18 #include <cerrno>
19 #include <functional>
20 #include <iomanip>
21 #include <sstream>
22 #include <string>
23 #include <unordered_map>
24 
25 #include "dfx_reporter.h"
26 #include "medialibrary_type_const.h"
27 #include "medialibrary_formmap_operations.h"
28 #include "medialibrary_notify.h"
29 #include "medialibrary_rdbstore.h"
30 #include "metadata.h"
31 #include "media_file_utils.h"
32 #include "medialibrary_album_compatibility_fusion_sql.h"
33 #include "medialibrary_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>> &notMathedMap, 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 &copyInfo,
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 &copyInfo)
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 &copyInfo)
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>> &notMathedMap)
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>> &notMathedMap)
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