diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn b/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn index d79822eb003223a8718c393e68dd627a6b66be8f..98cc38e81e90b63fcdf7a9ab720bd295a6cb4528 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn @@ -363,6 +363,7 @@ ohos_shared_library("medialibrary_data_extension") { "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/controller/processor/cloud_media_download_controller_processor.cpp", "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/dao/cloud_media_album_dao.cpp", "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/dao/cloud_media_common_dao.cpp", + "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/dao/cloud_media_photo_ext_dao.cpp", "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/dao/cloud_media_data_dao.cpp", "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/dao/cloud_media_photos_dao.cpp", "${MEDIALIB_CLOUD_SYNC_SERVICE_PATH}/src/dao/cloud_media_download_dao.cpp", @@ -642,6 +643,7 @@ ohos_shared_library("medialibrary_data_extension") { "src/operation/photo_day_month_year_operation.cpp", "src/operation/photo_displayname_operation.cpp", "src/operation/photo_file_operation.cpp", + "src/operation/photo_edit_size_operation.cpp", "src/operation/photo_mimetype_operation.cpp", "src/operation/photo_owner_album_id_operation.cpp", "src/operation/photo_source_path_operation.cpp", diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_data_manager.h b/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_data_manager.h index 2fb6c36ffb3d573486a6463d6a47d8e1c5c76d43..67e3bc7262af84b656303e546131a6190a3a0f92 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_data_manager.h +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_data_manager.h @@ -120,7 +120,6 @@ public: EXPORT void UploadDBFileInner(int64_t totalFileSize); EXPORT int32_t UpdateDirtyForCloudClone(int32_t version); EXPORT int32_t ClearDirtyHdcData(); - EXPORT int32_t UpdateMediaSizeFromStorage(); EXPORT int HandleAnalysisFaceUpdate(MediaLibraryCommand& cmd, NativeRdb::ValuesBucket &value, const DataShare::DataSharePredicates &predicates); private: diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/include/operation/photo_edit_size_operation.h b/frameworks/innerkitsimpl/medialibrary_data_extension/include/operation/photo_edit_size_operation.h new file mode 100644 index 0000000000000000000000000000000000000000..20ee889eb7cc87c6d759e98ebd399cc087613f7d --- /dev/null +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/include/operation/photo_edit_size_operation.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEDIA_PHOTO_EDIT_SIZE_OPERATION_H +#define OHOS_MEDIA_PHOTO_EDIT_SIZE_OPERATION_H + +#include + +#include "medialibrary_rdbstore.h" + +namespace OHOS::Media { +#define EXPORT __attribute__ ((visibility ("default"))) +class PhotoEditSizeOperation { +public: + EXPORT static int32_t CalCloudSyncSingleEditDataSize(const std::string &fileId); + EXPORT static int32_t CalSingleEditDataSize(const std::string &fileId); + EXPORT static int32_t GetFileIdsAndPathS(const std::shared_ptr rdbStore, + std::vector &fileIds, std::vector &filePaths, std::string startFileId, + bool &hasMore, int32_t limitCount); + EXPORT static int32_t ConvertPhotoCloudPathToLocalData(std::string retrievedPath, + std::string &filePath); + EXPORT static int32_t GetFilePathById(const std::shared_ptr rdbStore, + const std::string &fileId, std::string &filePath); + EXPORT static int32_t GetFileIdByCloudPath(const std::shared_ptr rdbStore, + std::string &fileId, const std::string &filePath); + EXPORT static int32_t UpdateMediaSizeFromStorage(); + EXPORT static int32_t UpdateSingleEditDataSize(std::shared_ptr rdbStore, + const std::string &photoId, const std::string &editDataDir); +}; +} // namespace OHOS::Media +#endif // FRAMEWORKS_INNERKITSIMPL_MEDIA_LIBRARY_INCLUDE_PHOTO_EDIT_SIZE_H_ \ No newline at end of file diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_data_manager.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_data_manager.cpp index f327ea3d6e52e091563a298ea5b6c2c809f00b89..9cbd540173c9c5609f81b15e880c03a73c0ef118 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_data_manager.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_data_manager.cpp @@ -3022,98 +3022,6 @@ int32_t MediaLibraryDataManager::ClearDirtyHdcData() return E_OK; } -static void Update500EditDataSize(const shared_ptr rdbStore, std::string startFileId, - bool &hasMore) -{ - std::vector filePaths; - std::vector fileIds; - int32_t ret = MediaLibraryPhotoOperations::Get500FileIdsAndPathS(rdbStore, fileIds, filePaths, - startFileId, hasMore); - if (ret != E_OK) { - MEDIA_ERR_LOG("Failed to get filePaths and IDs, error code: %{public}d", ret); - return; - } - - if (filePaths.empty() || fileIds.empty()) { - hasMore = false; - MEDIA_INFO_LOG("No files need to update edit data size"); - return; - } - - MEDIA_INFO_LOG("Start to update edit data size for %{public}zu files", fileIds.size()); - int32_t successCount = 0; - int32_t failedCount = 0; - - for (size_t i = 0; i < fileIds.size(); ++i) { - const auto &fileId = fileIds[i]; - const auto &filePath = filePaths[i]; - - std::string editDataFilePath; - ret = MediaLibraryPhotoOperations::ConvertPhotoCloudPathToLocalData(filePath, editDataFilePath); - if (ret != E_OK) { - MEDIA_WARN_LOG("Skip invalid file ID: %{public}s (error code: %{public}d)", - fileId.c_str(), ret); - failedCount++; - continue; - } - - ret = MediaLibraryRdbStore::UpdateEditDataSize(rdbStore, fileId, editDataFilePath); - if (ret == E_OK) { - successCount++; - } else { - MEDIA_ERR_LOG("Update failed for ID: %{public}s, Path: %{public}s (error code: %{public}d)", - fileId.c_str(), editDataFilePath.c_str(), ret); - failedCount++; - } - } - - MEDIA_INFO_LOG("Edit data size update completed: success=%{public}d, failed=%{public}d", - successCount, failedCount); - if (failedCount > 0) { - MEDIA_WARN_LOG("%{public}d files failed to update, check above logs for details", failedCount); - } -} - -int32_t MediaLibraryDataManager::UpdateMediaSizeFromStorage() -{ - if (!MedialibrarySubscriber::IsCurrentStatusOn()) { - MEDIA_INFO_LOG("Current status is off, skip disk cleanup"); - return E_OK; - } - - auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); - if (!rdbStore) { - MEDIA_ERR_LOG("RdbStore is null"); - return E_HAS_DB_ERROR; - } - - int32_t errCode; - shared_ptr prefs = - NativePreferences::PreferencesHelper::GetPreferences(TASK_PROGRESS_XML, errCode); - if (prefs == nullptr) { - MEDIA_ERR_LOG("Get preferences error: %{public}d", errCode); - return errCode; - } - - int32_t startFileId = prefs->GetInt(UPDATE_EDITDATA_SIZE_COUNT, 0); - bool hasMore = true; - while (hasMore) { - if (!MedialibrarySubscriber::IsCurrentStatusOn()) { - MEDIA_INFO_LOG("Current status is off, skip disk cleanup"); - return E_OK; - } - prefs->PutInt(UPDATE_EDITDATA_SIZE_COUNT, startFileId); - prefs->FlushSync(); - Update500EditDataSize(rdbStore, std::to_string(startFileId), hasMore); - // 一次500张图片 - startFileId += 500; - } - - prefs->PutInt(NO_UPDATE_EDITDATA_SIZE, 1); - prefs->FlushSync(); - return E_OK; -} - static int32_t DoUpdateBurstCoverLevelOperation(const shared_ptr rdbStore, const std::vector &fileIdVec) { diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_photo_operations.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_photo_operations.cpp index 577a33d98793dfdd96f0584887aab39c56ee907f..48e50b9111c62823fbc2b6e9d5c087168b79b680 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_photo_operations.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_photo_operations.cpp @@ -92,6 +92,7 @@ #include "moving_photo_file_utils.h" #include "hi_audit.h" #include "video_composition_callback_imp.h" +#include "photo_edit_size_operation.h" #include "medialibrary_data_manager.h" #include "shooting_mode_column.h" #include "refresh_business_name.h" @@ -1317,148 +1318,6 @@ static int32_t UpdateIsTempAndDirty(MediaLibraryCommand &cmd, const string &file return updateRows; } -int32_t MediaLibraryPhotoOperations::CalSingleEditDataSize(const std::string &fileId) -{ - auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); - if (rdbStore == nullptr) { - MEDIA_ERR_LOG("rdbStore is nullptr"); - return E_DB_FAIL; - } - - std::string filePath; - int ret = MediaLibraryPhotoOperations::GetFilePathById(rdbStore, fileId, filePath); - if (ret != E_OK) { - MEDIA_WARN_LOG("Skip invalid file ID: %{public}s (error code: %{public}d)", - fileId.c_str(), ret); - return ret; - } - - return MediaLibraryRdbStore::UpdateEditDataSize(rdbStore, fileId, filePath); -} - -int32_t MediaLibraryPhotoOperations::Get500FileIdsAndPathS(const std::shared_ptr rdbStore, - std::vector &fileIds, std::vector &filePaths, std::string startFileId, bool &hasMore) -{ - fileIds.clear(); - filePaths.clear(); - - MediaLibraryCommand queryCmd(OperationObject::UFM_PHOTO, OperationType::QUERY); - queryCmd.GetAbsRdbPredicates() - ->IsNotNull(MediaColumn::MEDIA_ID) - ->And() - ->IsNotNull(MediaColumn::MEDIA_FILE_PATH); - - if ((!startFileId.empty()) && MediaLibraryDataManagerUtils::IsNumber(startFileId)) { - queryCmd.GetAbsRdbPredicates()->Offset(std::stoi(startFileId)); - } - // 一次查取500个 - queryCmd.GetAbsRdbPredicates()->Limit(500); - - std::vector columns = {MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH}; - - auto result = rdbStore->Query(queryCmd, columns); - if (!result || result->GoToFirstRow() != NativeRdb::E_OK) { - hasMore = false; - MEDIA_ERR_LOG("Query files failed"); - return E_GET_PRAMS_FAIL; - } - - std::string fileId; - std::string filePath; - int count = 0; - do { - fileId = GetStringVal(MediaColumn::MEDIA_ID, result); - filePath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, result); - if (!fileId.empty() && !filePath.empty()) { - fileIds.push_back(fileId); - filePaths.push_back(filePath); - count++; - } - } while (result->GoToNextRow() == NativeRdb::E_OK); - - // 没有取到500个,认为已经取完了所有的数据 - if (count < 500) { - hasMore = false; - } - - return E_OK; -} - -static int32_t ConvertPhotoPathToEditDataDirPath(const std::string &sourcePath, std::string &editDataDir) -{ - if (sourcePath.empty()) { - return E_INVALID_PATH; - } - - editDataDir = MediaLibraryAssetOperations::GetEditDataDirPath(sourcePath); - if (editDataDir.empty()) { - MEDIA_ERR_LOG("Failed to convert path: %{public}s", sourcePath.c_str()); - return E_INVALID_PATH; - } - return E_OK; -} - -static int32_t GetCloudFilePath(const shared_ptr rdbStore, const std::string &fileId, - std::string &filePath) -{ - std::string sql = "SELECT " + MediaColumn::MEDIA_FILE_PATH + - " FROM " + PhotoColumn::PHOTOS_TABLE + - " WHERE " + MediaColumn::MEDIA_ID + " = ?"; - - std::vector params = {fileId}; - auto result = rdbStore->QuerySql(sql, params); - if (!result) { - MEDIA_ERR_LOG("Query failed for fileId: %{public}s", fileId.c_str()); - return E_HAS_DB_ERROR; - } - - if (result->GoToFirstRow() != NativeRdb::E_OK) { - MEDIA_WARN_LOG("File not found for ID: %{public}s", fileId.c_str()); - return E_INVALID_FILEID; - } - - if (result->GetString(0, filePath) != NativeRdb::E_OK || filePath.empty()) { - MEDIA_ERR_LOG("Failed to retrieve file path for ID: %{public}s", fileId.c_str()); - return E_INVALID_FILEID; - } - return E_OK; -} - -int32_t MediaLibraryPhotoOperations::ConvertPhotoCloudPathToLocalData(std::string retrievedPath, std::string &filePath) -{ - static const std::string OLD_PREFIX = "/storage/cloud/"; - static const std::string NEW_PREFIX = "/storage/media/local/"; - if (retrievedPath.compare(0, OLD_PREFIX.length(), OLD_PREFIX) == 0) { - std::string editDataDir; - int32_t ret = ConvertPhotoPathToEditDataDirPath(retrievedPath, editDataDir); - if (ret != E_OK) { - return ret; - } - filePath = NEW_PREFIX + editDataDir.substr(OLD_PREFIX.length()); - MEDIA_INFO_LOG("Converted to local path: %{private}s", filePath.c_str()); - } else { - filePath = std::move(retrievedPath); - } - return E_OK; -} - -int32_t MediaLibraryPhotoOperations::GetFilePathById(const shared_ptr rdbStore, - const std::string &fileId, std::string &filePath) -{ - std::string retrievedPath; - if (GetCloudFilePath(rdbStore, fileId, retrievedPath) != E_OK) { - MEDIA_ERR_LOG("Failed to retrieve file path for ID: %{public}s", fileId.c_str()); - return E_INVALID_FILEID; - } - - if (ConvertPhotoCloudPathToLocalData(retrievedPath, filePath) != E_OK) { - MEDIA_ERR_LOG("Failed to Convert cloue path: %{public}s to local path", retrievedPath.c_str()); - return E_INVALID_FILEID; - } - - return E_OK; -} - int32_t MediaLibraryPhotoOperations::SaveCameraPhoto(MediaLibraryCommand &cmd) { MediaLibraryTracer tracer; @@ -3153,7 +3012,7 @@ void MediaLibraryPhotoOperations::StoreThumbnailAndEditSize(const string& photoI uint64_t editDataSize = 0; string editDataDir; - if (MediaLibraryPhotoOperations::ConvertPhotoCloudPathToLocalData(photoPath, editDataDir) != E_OK) { + if (PhotoEditSizeOperation::ConvertPhotoCloudPathToLocalData(photoPath, editDataDir) != E_OK) { MEDIA_ERR_LOG("Failed to Convert cloue path: %{public}s to local path", photoPath.c_str()); return; } diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp index dedadbbe0890bc583a02e16c0813a4b635b04d65..35518f2df6b49bf585b499371ba6cda359e7cdcf 100755 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp @@ -402,24 +402,6 @@ void MediaLibraryRdbStore::UpdateDateTakenIndex(const shared_ptr rdbStore, - const std::string &photoId, const std::string &editDataDir) -{ - size_t size = 0; - MediaFileUtils::StatDirSize(editDataDir, size); - std::string sql = "UPDATE " + PhotoExtColumn::PHOTOS_EXT_TABLE + " " - "SET " + PhotoExtColumn::EDITDATA_SIZE + " = " + std::to_string(size) + " " - "WHERE " + PhotoExtColumn::PHOTO_ID + " = '" + photoId + "'"; - - int32_t ret = rdbStore->ExecuteSql(sql); - if (ret != NativeRdb::E_OK) { - MEDIA_ERR_LOG("Execute SQL failed: %{public}d", ret); - return E_DB_FAIL; - } - return E_OK; -} - void MediaLibraryRdbStore::UpdateDateTakenAndDetalTime(const shared_ptr store) { MEDIA_INFO_LOG("UpdateDateTakenAndDetalTime start"); diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_subscriber.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_subscriber.cpp index 010da2d8c5d4e43d3e9535283b4c3bd77b8a0452..8e6b6a08fc50f1843c8637ee7a48a8760e124035 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_subscriber.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_subscriber.cpp @@ -87,6 +87,7 @@ #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT #include "enhancement_manager.h" #include "cloud_enhancement_checker.h" +#include "photo_edit_size_operation.h" #endif using namespace OHOS::AAFwk; @@ -581,10 +582,7 @@ static int32_t DoUpdateBurstFromGallery() static void QueryUpdateSize(AsyncTaskData *data) { - auto dataManager = MediaLibraryDataManager::GetInstance(); - CHECK_AND_RETURN_LOG(dataManager != nullptr, "dataManager is nullptr"); - - int32_t result = dataManager->UpdateMediaSizeFromStorage(); + int32_t result = PhotoEditSizeOperation::UpdateMediaSizeFromStorage(); CHECK_AND_PRINT_LOG(result == E_OK, "UpdateMediaSizeFromStorage failed"); } @@ -607,8 +605,7 @@ static int32_t UpdateAllEditDataSize() shared_ptr updateSizeTask = make_shared(QueryUpdateSize, nullptr); - CHECK_AND_RETURN_RET_LOG(updateSizeTask != nullptr, E_FAIL, - "Failed to create async task for updateBurstTask!"); + CHECK_AND_RETURN_RET_LOG(updateSizeTask != nullptr, E_FAIL, "Failed to create async task for updateBurstTask!"); asyncWorker->AddTask(updateSizeTask, false); return E_SUCCESS; } diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_custom_restore_operation.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_custom_restore_operation.cpp index 518d897cc2f89bd4783327c1507900f3279d2f8d..050be01e2dbe9d4a09cb8fc132e8f473877a6bfa 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_custom_restore_operation.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_custom_restore_operation.cpp @@ -45,6 +45,7 @@ #include "scanner_utils.h" #include "shooting_mode_column.h" #include "userfile_manager_types.h" +#include "photo_edit_size_operation.h" #include "refresh_business_name.h" using namespace std; @@ -887,6 +888,36 @@ static void UpdateCoverPosition(const string &filePath, int64_t coverPosition) " ret = %{public}d", errCode); } +static void UpdateLivePhoto(const string &cloudPath) +{ + auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (rdbStore == nullptr) { + MEDIA_ERR_LOG("rdbStore is nullptr"); + return; + } + + string fileId; + int32_t ret = PhotoEditSizeOperation::GetFileIdByCloudPath(rdbStore, fileId, cloudPath); + if (ret != E_OK) { + MEDIA_ERR_LOG("Skip invalid file path: %{public}s (error code: %{public}d)", + cloudPath.c_str(), ret); + return; + } + + std::string filePath; + if (PhotoEditSizeOperation::ConvertPhotoCloudPathToLocalData(cloudPath, filePath) != E_OK) { + MEDIA_ERR_LOG("Failed to Convert cloud path: %{public}s to local path", cloudPath.c_str()); + return; + } + + ret = PhotoEditSizeOperation::UpdateSingleEditDataSize(rdbStore, fileId, filePath); + if (ret != E_OK) { + MEDIA_ERR_LOG("UpdateSingleEditDataSize failed, fielId: %{public}s, fielPath: %{public}s,\ + (error code: %{public}d)", fileId.c_str(), cloudPath.c_str(), ret); + return; + } +} + int32_t PhotoCustomRestoreOperation::RenameFiles(const vector &restoreFiles) { int32_t renameNum = 0; @@ -900,6 +931,7 @@ int32_t PhotoCustomRestoreOperation::RenameFiles(const vector &restore } else { renameNum++; } + UpdateLivePhoto(fileInfo.filePath); continue; } if (!MediaFileUtils::MoveFile(fileInfo.originFilePath, fileInfo.filePath, true)) { diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_edit_size_operation.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_edit_size_operation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ff4c649fd1f922eed6aa0ed54ba242f1aa4a98d --- /dev/null +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/operation/photo_edit_size_operation.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "photo_edit_size_operation.h" + +#include "media_log.h" +#include "medialibrary_errno.h" +#include "medialibrary_unistore_manager.h" +#include "medialibrary_asset_operations.h" +#include "medialibrary_subscriber.h" +#include "preferences.h" +#include "preferences_helper.h" +#include "rdb_predicates.h" +#include "result_set_utils.h" +#include "media_file_utils.h" +#include "medialibrary_asset_operations.h" +#include "medialibrary_data_manager_utils.h" + +using namespace std; +namespace OHOS::Media { + +static const std::string TASK_PROGRESS_XML = "/data/storage/el2/base/preferences/task_progress.xml"; +static const std::string UPDATE_EDITDATA_SIZE_COUNT = "update_editdata_size_count"; +static const std::string NO_UPDATE_EDITDATA_SIZE = "no_update_editdata_size"; + +int32_t PhotoEditSizeOperation::CalCloudSyncSingleEditDataSize(const std::string &fileId) +{ + auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (rdbStore == nullptr) { + MEDIA_ERR_LOG("rdbStore is nullptr"); + return E_DB_FAIL; + } + + std::string filePath; + int ret = PhotoEditSizeOperation::GetFilePathById(rdbStore, fileId, filePath); + if (ret != E_OK) { + MEDIA_WARN_LOG("Skip invalid file ID: %{public}s (error code: %{public}d)", + fileId.c_str(), ret); + } + + return PhotoEditSizeOperation::UpdateSingleEditDataSize(rdbStore, fileId, filePath); +} + +int32_t PhotoEditSizeOperation::CalSingleEditDataSize(const std::string &fileId) +{ + auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (rdbStore == nullptr) { + MEDIA_ERR_LOG("rdbStore is nullptr"); + return E_DB_FAIL; + } + + std::string filePath; + int ret = PhotoEditSizeOperation::GetFilePathById(rdbStore, fileId, filePath); + if (ret != E_OK) { + MEDIA_WARN_LOG("Skip invalid file ID: %{public}s (error code: %{public}d)", + fileId.c_str(), ret); + return ret; + } + + return PhotoEditSizeOperation::UpdateSingleEditDataSize(rdbStore, fileId, filePath); +} + +static int32_t GetCloudFilePath(const shared_ptr rdbStore, const std::string &fileId, + std::string &filePath) +{ + if (!rdbStore) { + MEDIA_ERR_LOG("GetRdbStore failed"); + return E_HAS_DB_ERROR; + } + + std::string sql = "SELECT " + MediaColumn::MEDIA_FILE_PATH + + " FROM " + PhotoColumn::PHOTOS_TABLE + + " WHERE " + MediaColumn::MEDIA_ID + " = ?"; + + std::vector params = {fileId}; + auto result = rdbStore->QuerySql(sql, params); + if (!result) { + MEDIA_ERR_LOG("Query failed for fileId: %{public}s", fileId.c_str()); + return E_HAS_DB_ERROR; + } + + if (result->GoToFirstRow() != NativeRdb::E_OK) { + MEDIA_WARN_LOG("File not found for ID: %{public}s", fileId.c_str()); + return E_INVALID_FILEID; + } + + if (result->GetString(0, filePath) != NativeRdb::E_OK || filePath.empty()) { + MEDIA_ERR_LOG("Failed to retrieve file path for ID: %{public}s", fileId.c_str()); + return E_INVALID_FILEID; + } + return E_OK; +} + +int32_t PhotoEditSizeOperation::GetFileIdByCloudPath(const shared_ptr rdbStore, + std::string &fileId, const std::string &filePath) +{ + if (!rdbStore) { + MEDIA_ERR_LOG("GetRdbStore failed"); + return E_HAS_DB_ERROR; + } + std::string sql = "SELECT " + MediaColumn::MEDIA_ID+ + " FROM " + PhotoColumn::PHOTOS_TABLE + + " WHERE " + MediaColumn::MEDIA_FILE_PATH + " = ?"; + + std::vector params = {filePath}; + auto result = rdbStore->QuerySql(sql, params); + if (!result) { + MEDIA_ERR_LOG("Query failed for fileId: %{public}s", filePath.c_str()); + return E_HAS_DB_ERROR; + } + + if (result->GoToFirstRow() != NativeRdb::E_OK) { + MEDIA_WARN_LOG("File not found for filePath: %{public}s", filePath.c_str()); + return E_INVALID_FILEID; + } + + if (result->GetString(0, fileId) != NativeRdb::E_OK || fileId.empty()) { + MEDIA_ERR_LOG("Failed to retrieve file path for file path: %{public}s", filePath.c_str()); + return E_INVALID_FILEID; + } + return E_OK; +} + +int32_t PhotoEditSizeOperation::GetFilePathById(const shared_ptr rdbStore, + const std::string &fileId, std::string &filePath) +{ + std::string retrievedPath; + if (GetCloudFilePath(rdbStore, fileId, retrievedPath) != E_OK) { + MEDIA_ERR_LOG("Failed to retrieve file path for ID: %{public}s", fileId.c_str()); + return E_INVALID_FILEID; + } + + if (ConvertPhotoCloudPathToLocalData(retrievedPath, filePath) != E_OK) { + MEDIA_ERR_LOG("Failed to Convert cloue path: %{public}s to local path", retrievedPath.c_str()); + return E_INVALID_FILEID; + } + + return E_OK; +} + +static int32_t ConvertPhotoPathToEditDataDirPath(const std::string &sourcePath, std::string &editDataDir) +{ + if (sourcePath.empty()) { + return E_INVALID_PATH; + } + + editDataDir = MediaLibraryAssetOperations::GetEditDataDirPath(sourcePath); + if (editDataDir.empty()) { + MEDIA_ERR_LOG("Failed to convert path: %{public}s", sourcePath.c_str()); + return E_INVALID_PATH; + } + return E_OK; +} + +int32_t PhotoEditSizeOperation::ConvertPhotoCloudPathToLocalData(std::string retrievedPath, std::string &filePath) +{ + static const std::string OLD_PREFIX = "/storage/cloud/"; + static const std::string NEW_PREFIX = "/storage/media/local/"; + if (retrievedPath.compare(0, OLD_PREFIX.length(), OLD_PREFIX) == 0) { + std::string editDataDir; + int32_t ret = ConvertPhotoPathToEditDataDirPath(retrievedPath, editDataDir); + if (ret != E_OK) { + return ret; + } + filePath = NEW_PREFIX + editDataDir.substr(OLD_PREFIX.length()); + MEDIA_INFO_LOG("Converted to local path: %{private}s", filePath.c_str()); + } else { + filePath = std::move(retrievedPath); + } + return E_OK; +} + +static void UpdateLimitEditDataSize(const shared_ptr rdbStore, std::string startFileId, + bool &hasMore, int32_t limitCount) +{ + std::vector filePaths; + std::vector fileIds; + int32_t ret = PhotoEditSizeOperation::GetFileIdsAndPathS(rdbStore, fileIds, filePaths, startFileId, + hasMore, limitCount); + if (ret != E_OK) { + MEDIA_ERR_LOG("Failed to get filePaths and Ids, error code: %{public}d", ret); + return; + } + + if (filePaths.empty() || fileIds.empty()) { + hasMore = false; + MEDIA_ERR_LOG("No files need to update edit data size"); + return; + } + + MEDIA_INFO_LOG("Start to update edit data size for %{public}zu files", fileIds.size()); + int32_t successCount = 0; + int32_t failedCount = 0; + + for (size_t i = 0; i < fileIds.size(); ++i) { + const auto &fileId = fileIds[i]; + const auto &filePath = filePaths[i]; + + std::string editDataFilePath; + ret = PhotoEditSizeOperation::ConvertPhotoCloudPathToLocalData(filePath, editDataFilePath); + if (ret != E_OK) { + MEDIA_WARN_LOG("Skip invalid file ID: %{public}s (error code: %{public}d)", + fileId.c_str(), ret); + failedCount++; + continue; + } + + ret = PhotoEditSizeOperation::UpdateSingleEditDataSize(rdbStore, fileId, editDataFilePath); + if (ret == E_OK) { + successCount++; + } else { + MEDIA_ERR_LOG("Update failed for ID: %{public}s, Path: %{public}s (error code: %{public}d)", + fileId.c_str(), editDataFilePath.c_str(), ret); + failedCount++; + } + } + + MEDIA_INFO_LOG("Edit data size update completed: success=%{public}d, failed=%{public}d", + successCount, failedCount); + if (failedCount > 0) { + MEDIA_WARN_LOG("%{public}d files failed to update, check above logs for details", failedCount); + } +} + +int32_t PhotoEditSizeOperation::UpdateMediaSizeFromStorage() +{ + if (!MedialibrarySubscriber::IsCurrentStatusOn()) { + MEDIA_INFO_LOG("Current status is off, skip disk cleanup"); + return E_OK; + } + + auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (!rdbStore) { + MEDIA_ERR_LOG("RdbStore is null"); + return E_HAS_DB_ERROR; + } + + int32_t errCode; + shared_ptr prefs = + NativePreferences::PreferencesHelper::GetPreferences(TASK_PROGRESS_XML, errCode); + if (prefs == nullptr) { + MEDIA_ERR_LOG("Get preferences error: %{public}d", errCode); + return errCode; + } + + int32_t startFileId = prefs->GetInt(UPDATE_EDITDATA_SIZE_COUNT, 0); + bool hasMore = true; + // 一次500张图片 + int32_t limitCount = 500; + while (hasMore) { + if (!MedialibrarySubscriber::IsCurrentStatusOn()) { + MEDIA_INFO_LOG("Current status is off, skip disk cleanup"); + return E_OK; + } + prefs->PutInt(UPDATE_EDITDATA_SIZE_COUNT, startFileId); + prefs->FlushSync(); + UpdateLimitEditDataSize(rdbStore, std::to_string(startFileId), hasMore, limitCount); + startFileId += limitCount; + } + + prefs->PutInt(NO_UPDATE_EDITDATA_SIZE, 1); + prefs->FlushSync(); + return E_OK; +} + +int32_t PhotoEditSizeOperation::GetFileIdsAndPathS(const std::shared_ptr rdbStore, + std::vector &fileIds, std::vector &filePaths, std::string startFileId, + bool &hasMore, int32_t limitCount) +{ + fileIds.clear(); + filePaths.clear(); + + NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE); + predicates + .IsNotNull(MediaColumn::MEDIA_ID) + ->And() + ->IsNotNull(MediaColumn::MEDIA_FILE_PATH); + + if ((!startFileId.empty()) && MediaLibraryDataManagerUtils::IsNumber(startFileId)) { + predicates.Offset(std::stoi(startFileId)); + } + predicates.Limit(limitCount); + + std::vector columns = {MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH}; + + auto result = rdbStore->Query(predicates, columns); + if (!result || result->GoToFirstRow() != NativeRdb::E_OK) { + hasMore = false; + MEDIA_ERR_LOG("Query files failed"); + return E_GET_PRAMS_FAIL; + } + + std::string fileId; + std::string filePath; + int count = 0; + do { + fileId = GetStringVal(MediaColumn::MEDIA_ID, result); + filePath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, result); + if (!fileId.empty() && !filePath.empty()) { + fileIds.push_back(fileId); + filePaths.push_back(filePath); + count++; + } + } while (result->GoToNextRow() == NativeRdb::E_OK); + + if (count < limitCount) { + hasMore = false; + } + + return E_OK; +} + +// 更新单条编辑数据大小 +int32_t PhotoEditSizeOperation::UpdateSingleEditDataSize(std::shared_ptr rdbStore, + const std::string &photoId, const std::string &editDataDir) +{ + size_t size = 0; + MediaFileUtils::StatDirSize(editDataDir, size); + std::string sql = "INSERT INTO " + PhotoExtColumn::PHOTOS_EXT_TABLE + " (" + + PhotoExtColumn::PHOTO_ID + ", " + PhotoExtColumn::EDITDATA_SIZE + + ") VALUES (" + photoId + ", " + std::to_string(size) + ")" + + " ON CONFLICT(" + PhotoExtColumn::PHOTO_ID + ")" + " DO UPDATE SET " + + PhotoExtColumn::EDITDATA_SIZE + " = " + std::to_string(size); + + int32_t ret = rdbStore->ExecuteSql(sql); + if (ret != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Execute SQL failed: %{public}d", ret); + return E_DB_FAIL; + } + return E_OK; +} +} // namespace OHOS::Media diff --git a/frameworks/innerkitsimpl/test/unittest/medialibrary_photo_operations_test/src/medialibrary_photo_edit_test.cpp b/frameworks/innerkitsimpl/test/unittest/medialibrary_photo_operations_test/src/medialibrary_photo_edit_test.cpp index def634fe1b25943d71ac8684cb310673ed35953a..66f5124fe77652806d8aa7087ed93c374e0b013e 100644 --- a/frameworks/innerkitsimpl/test/unittest/medialibrary_photo_operations_test/src/medialibrary_photo_edit_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/medialibrary_photo_operations_test/src/medialibrary_photo_edit_test.cpp @@ -47,10 +47,13 @@ #include "medialibrary_type_const.h" #include "medialibrary_unistore_manager.h" #include "medialibrary_unittest_utils.h" +#include "media_file_ext_ability.h" +#include "media_file_extention_utils.h" #include "result_set_utils.h" #include "uri.h" #include "userfile_manager_types.h" #include "values_bucket.h" +#include "photo_edit_size_operation.h" namespace OHOS { namespace Media { @@ -544,5 +547,52 @@ HWTEST_F(MediaLibraryPhotoEditTest, deferred_photos_test_006, TestSize.Level1) MEDIA_INFO_LOG("end deferred_photos_test_006"); } +// 更新单个图片的editdata_size +HWTEST_F(MediaLibraryPhotoEditTest, cal_editdata_size_test_001, TestSize.Level1) +{ + MEDIA_INFO_LOG("start cal_editdata_size_test_001"); + ASSERT_TRUE(IsWaterMarkExists()); + + // 一阶段拍照无水印 + TakePhotoResult result = TakePhotoMock(true); + // 保存编辑后图片和编辑数据 + EditPhoto(result, true, true); + // 二阶段落盘 + bool isEdited = IsEdited(result.fileId); + EXPECT_EQ(isEdited, true); + WriteDefferedPhoto(isEdited, result.path); + // 假设 fileId 是 int32_t 类型 + std::string fileIdStr = std::to_string(result.fileId); + int32_t ret = PhotoEditSizeOperation::CalSingleEditDataSize(fileIdStr.c_str(), result.path); + EXPECT_EQ(ret, 0); + // 回退 + Revert(result, true); + MEDIA_INFO_LOG("end cal_editdata_size_test_001"); +} + +// 更新多个图片的editdata_size +HWTEST_F(MediaLibraryPhotoEditTest, cal_editdata_size_test_002, TestSize.Level1) +{ + MEDIA_INFO_LOG("start cal_editdata_size_test_002"); + ASSERT_TRUE(IsWaterMarkExists()); + + const int LOOP_COUNT = 531; + TakePhotoResult result; + bool isEdited; + for (int i = 0; i < LOOP_COUNT; ++i) { + // 1.获取新的拍照模拟结果 + result = TakePhotoMock(true); + // 2.编辑照片并保存数据 + EditPhoto(result, true, true); + // 3.检查是否已编辑 + isEdited = IsEdited(result.fileId); + EXPECT_EQ(isEdited, true); + // 4.执行二阶段落盘 + WriteDefferedPhoto(isEdited, result.path); + } + PhotoEditSizeOperation::UpdateMediaSizeFromStorage(); + MEDIA_INFO_LOG("end cal_editdata_size_test_002"); +} + } } \ No newline at end of file diff --git a/services/media_cloud_sync_service/include/dao/cloud_media_photo_ext_dao.h b/services/media_cloud_sync_service/include/dao/cloud_media_photo_ext_dao.h new file mode 100644 index 0000000000000000000000000000000000000000..d8a888ac60edbb42a1a87427b1e3ab6ac5408630 --- /dev/null +++ b/services/media_cloud_sync_service/include/dao/cloud_media_photo_ext_dao.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEDIA_CLOUD_SYNC_CLOUD_MEDIA_PHOTO_EXT_DAO_H +#define OHOS_MEDIA_CLOUD_SYNC_CLOUD_MEDIA_PHOTO_EXT_DAO_H + +#include +#include + +#include "media_column.h" +#include "rdb_store.h" + +namespace OHOS::Media::CloudSync { + +class EXPORT CloudMediaPhotoExtDao { + +public: + static bool DeletePhotoExtTable(const std::string& photoId); +}; +} // namespace OHOS::Media::CloudSync +#endif // OHOS_MEDIA_CLOUD_SYNC_CLOUD_MEDIA_PHOTO_EXT_DAO_H \ No newline at end of file diff --git a/services/media_cloud_sync_service/src/dao/cloud_media_photo_ext_dao.cpp b/services/media_cloud_sync_service/src/dao/cloud_media_photo_ext_dao.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b706245d7c24f959198770343bb7860881a6d2a8 --- /dev/null +++ b/services/media_cloud_sync_service/src/dao/cloud_media_photo_ext_dao.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MLOG_TAG "Media_Cloud_Dao" + +#include "cloud_media_photo_ext_dao.h" + +#include +#include +#include "media_log.h" +#include "media_column.h" +#include "medialibrary_unistore_manager.h" + + +namespace OHOS::Media::CloudSync { +bool CloudMediaPhotoExtDao::DeletePhotoExtTable(const std::string& photoId) +{ + auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, + "Medialibrary rdbStore is nullptr!"); + + std::string sql = "DELETE FROM" + PhotoExtColumn::PHOTOS_EXT_TABLE + + " WHERE " + PhotoExtColumn::PHOTO_ID + " = " + photoId + ";"; + int32_t ret = rdbStore->ExecuteSql(sql); + CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, false, + "Failed to execute sql, photoId is %{public}s, error code is %{public}d", photoId.c_str(), ret); + return true; +} +} // namespace OHOS::Media::CloudSync \ No newline at end of file diff --git a/services/media_cloud_sync_service/src/service/cloud_media_download_service.cpp b/services/media_cloud_sync_service/src/service/cloud_media_download_service.cpp index 8ff2e6cf7c58e136722e03438f0ea105d680e94d..18cb00e014fd423ee8ec03c9ab11a8d31d490a74 100644 --- a/services/media_cloud_sync_service/src/service/cloud_media_download_service.cpp +++ b/services/media_cloud_sync_service/src/service/cloud_media_download_service.cpp @@ -35,6 +35,7 @@ #include "cloud_media_scan_service.h" #include "dfx_const.h" #include "media_gallery_sync_notify.h" +#include "photo_edit_size_operation.h" namespace OHOS::Media::CloudSync { using ChangeType = AAFwk::ChangeInfo::ChangeType; @@ -444,6 +445,12 @@ void CloudMediaDownloadService::HandlePhoto(const ORM::PhotosPo &photo, OnDownlo } else if (assetData.dateModified > 0 && (assetData.needSliceContent || assetData.needSliceRaw)) { this->ResetAssetModifyTime(assetData); } + int32_t fileId = photo.fileId.value_or(0); + ret = PhotoEditSizeOperation::CalCloudSyncSingleEditDataSize(std::to_string(fileId)); + if (ret != E_OK) { + MEDIA_ERR_LOG("CalCloudSyncSingleEditDataSize failed for ID: %{public}d (ret code: %{public}d)", + fileId, ret); + } ret = FixDownloadAssetExifRotate(photo, assetData); if (ret != E_OK) { diff --git a/services/media_cloud_sync_service/src/service/cloud_media_photos_service.cpp b/services/media_cloud_sync_service/src/service/cloud_media_photos_service.cpp index ccb37a65300b8d8b6e0bdda485db6d890690c8b5..013351faec7726d2b92db120a6bc4a222daa6815 100644 --- a/services/media_cloud_sync_service/src/service/cloud_media_photos_service.cpp +++ b/services/media_cloud_sync_service/src/service/cloud_media_photos_service.cpp @@ -41,6 +41,7 @@ #include "cloud_media_sync_const.h" #include "cloud_media_operation_code.h" #include "cloud_media_dfx_service.h" +#include "cloud_media_photo_ext_dao.h" using ChangeType = OHOS::AAFwk::ChangeInfo::ChangeType; namespace OHOS::Media::CloudSync { @@ -500,6 +501,10 @@ int32_t CloudMediaPhotosService::HandleRecord(const std::vector &cl ret = PullDelete(pullData, refreshAlbums, photoRefresh); changeType = ChangeType::DELETE; stats[StatsIndex::DELETE_RECORDS_COUNT]++; + std::string fileId = std::to_string(pullData.localFileId); + if (!CloudMediaPhotoExtDao::DeletePhotoExtTable(fileId.c_str())) { + MEDIA_ERR_LOG("DeletePhotoExtTable fileId failed: %{public}s", fileId.c_str()); + } } else { ret = PullUpdate(pullData, refreshAlbums, fdirtyData, stats, photoRefresh); changeType = ChangeType::UPDATE;