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