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