1 /*
2 * Copyright (C) 2025 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 #include "medialibrary_ptp_operations.h"
16
17 #include <fcntl.h>
18
19 #include "dfx_utils.h"
20 #include "file_asset.h"
21 #include "media_file_utils.h"
22 #include "media_log.h"
23 #include "medialibrary_errno.h"
24 #include "medialibrary_notify.h"
25 #include "medialibrary_rdbstore.h"
26 #include "medialibrary_unistore_manager.h"
27 #include "photo_album_column.h"
28 #include "result_set_utils.h"
29 #include "userfile_manager_types.h"
30 #include "album_accurate_refresh.h"
31 #include "refresh_business_name.h"
32 using namespace std;
33 namespace OHOS::Media {
34 constexpr int64_t INVALID_SIZE = 0;
35 // LCOV_EXCL_START
FetchOneFileAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)36 shared_ptr<FileAsset> MediaLibraryPtpOperations::FetchOneFileAssetFromResultSet(
37 const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
38 {
39 int32_t currentRowIndex = 0;
40 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
41 CHECK_AND_RETURN_RET_LOG(
42 resultSet->GetRowIndex(currentRowIndex) == NativeRdb::E_OK, nullptr, "Cannot get row index of resultset");
43 CHECK_AND_RETURN_RET_LOG(currentRowIndex >= 0, nullptr, "Invalid row index");
44
45 auto fileAsset = make_shared<FileAsset>();
46 auto &map = fileAsset->GetMemberMap();
47 for (const auto &column : columns) {
48 int32_t columnIndex = 0;
49 CHECK_AND_RETURN_RET_LOG(resultSet->GetColumnIndex(column, columnIndex) == NativeRdb::E_OK,
50 nullptr, "Can not get column %{private}s index", column.c_str());
51 CHECK_AND_RETURN_RET_LOG(FILEASSET_MEMBER_MAP.find(column) != FILEASSET_MEMBER_MAP.end(), nullptr,
52 "Can not find column %{private}s from member map", column.c_str());
53 switch (FILEASSET_MEMBER_MAP.at(column)) {
54 case MEMBER_TYPE_INT32: {
55 int32_t value = 0;
56 CHECK_AND_RETURN_RET_LOG(resultSet->GetInt(columnIndex, value) == NativeRdb::E_OK, nullptr,
57 "Can not get int value from column %{private}s", column.c_str());
58 map[column] = value;
59 break;
60 }
61 case MEMBER_TYPE_INT64: {
62 int64_t value = 0;
63 CHECK_AND_RETURN_RET_LOG(resultSet->GetLong(columnIndex, value) == NativeRdb::E_OK, nullptr,
64 "Can not get long value from column %{private}s", column.c_str());
65 map[column] = value;
66 break;
67 }
68 case MEMBER_TYPE_STRING: {
69 string value;
70 CHECK_AND_RETURN_RET_LOG(resultSet->GetString(columnIndex, value) == NativeRdb::E_OK, nullptr,
71 "Can not get string value from column %{private}s", column.c_str());
72 map[column] = value;
73 break;
74 }
75 case MEMBER_TYPE_DOUBLE: {
76 double value;
77 CHECK_AND_RETURN_RET_LOG(resultSet->GetDouble(columnIndex, value) == NativeRdb::E_OK, nullptr,
78 "Can not get double value from column %{private}s", column.c_str());
79 map[column] = value;
80 break;
81 }
82 default:
83 break;
84 }
85 }
86 return fileAsset;
87 }
88
GetAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)89 shared_ptr<FileAsset> MediaLibraryPtpOperations::GetAssetFromResultSet(
90 const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
91 {
92 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
93 int32_t count = 0;
94 CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr,
95 "Cannot get row count of resultset");
96 CHECK_AND_RETURN_RET_LOG(count == 1, nullptr, "ResultSet count is %{public}d, not 1", count);
97 CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "Cannot go to first row");
98 return FetchOneFileAssetFromResultSet(resultSet, columns);
99 }
100
PushMovingPhotoExternalPath(const std::string & path,const std::string & logTarget,std::vector<std::string> & attachment)101 void MediaLibraryPtpOperations::PushMovingPhotoExternalPath(const std::string &path, const std::string &logTarget,
102 std::vector<std::string> &attachment)
103 {
104 if (path.empty()) {
105 MEDIA_WARN_LOG("%{private}s is invalid.", logTarget.c_str());
106 return;
107 }
108 attachment.push_back(path);
109 }
110
GetAssetSize(const std::string & extraPath)111 int64_t MediaLibraryPtpOperations::GetAssetSize(const std::string &extraPath)
112 {
113 string absExtraPath;
114 CHECK_AND_RETURN_RET_LOG(PathToRealPath(extraPath, absExtraPath), static_cast<int64_t>(E_ERR),
115 "file is not real path: %{private}s", extraPath.c_str());
116
117 UniqueFd fd(open(absExtraPath.c_str(), O_RDONLY));
118 CHECK_AND_RETURN_RET_LOG(fd.Get() != E_ERR, static_cast<int64_t>(E_ERR),
119 "failed to open extra file");
120
121 struct stat st;
122 CHECK_AND_RETURN_RET_LOG(fstat(fd.Get(), &st) == E_OK, static_cast<int64_t>(E_ERR),
123 "failed to get file size");
124 off_t fileSize = st.st_size;
125 return static_cast<int64_t>(fileSize);
126 }
127
GetMovingPhotoExternalInfo(ExternalInfo & exInfo,std::vector<std::string> & attachment)128 void MediaLibraryPtpOperations::GetMovingPhotoExternalInfo(ExternalInfo &exInfo, std::vector<std::string> &attachment)
129 {
130 if (!MovingPhotoFileUtils::IsMovingPhoto(exInfo.subType, exInfo.effectMode, exInfo.originalSubType)) {
131 return;
132 }
133 exInfo.videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(exInfo.path);
134 exInfo.extraPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(exInfo.path);
135 exInfo.photoImagePath = MovingPhotoFileUtils::GetSourceMovingPhotoImagePath(exInfo.path);
136 exInfo.photoVideoPath = MovingPhotoFileUtils::GetSourceMovingPhotoVideoPath(exInfo.path);
137 exInfo.cachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(exInfo.path);
138 PushMovingPhotoExternalPath(exInfo.videoPath, "videoPath", attachment);
139 PushMovingPhotoExternalPath(exInfo.extraPath, "extraPath", attachment);
140 PushMovingPhotoExternalPath(exInfo.photoImagePath, "photoImagePath", attachment);
141 PushMovingPhotoExternalPath(exInfo.photoVideoPath, "photoVideoPath", attachment);
142 PushMovingPhotoExternalPath(exInfo.cachePath, "cachePath", attachment);
143 MEDIA_INFO_LOG("videoPath is %{private}s, extraPath is %{private}s, photoImagePath is %{private}s, \
144 photoVideoPath is %{private}s, cachePath is %{private}s.", DfxUtils::GetSafePath(exInfo.videoPath).c_str(),
145 DfxUtils::GetSafePath(exInfo.extraPath).c_str(), DfxUtils::GetSafePath(exInfo.photoImagePath).c_str(),
146 DfxUtils::GetSafePath(exInfo.photoVideoPath).c_str(), DfxUtils::GetSafePath(exInfo.cachePath).c_str());
147 exInfo.sizeMp4 = GetAssetSize(exInfo.videoPath);
148 exInfo.sizeExtra = GetAssetSize(exInfo.extraPath);
149 if (exInfo.sizeMp4 <= INVALID_SIZE) {
150 MEDIA_WARN_LOG("failed to get mp4 size.");
151 } else {
152 exInfo.size += exInfo.sizeMp4;
153 }
154 if (exInfo.sizeExtra <= INVALID_SIZE) {
155 MEDIA_WARN_LOG("failed to get extra size.");
156 } else {
157 exInfo.size += exInfo.sizeExtra;
158 }
159 MEDIA_DEBUG_LOG("MovingPhoto size is %{public}" PRId64, exInfo.size);
160 }
161
GetEditPhotoExternalInfo(ExternalInfo & exInfo,vector<string> & attachment)162 void MediaLibraryPtpOperations::GetEditPhotoExternalInfo(ExternalInfo &exInfo, vector<string> &attachment)
163 {
164 CHECK_AND_RETURN_LOG(exInfo.editTime != 0, "editTime is zero");
165 exInfo.editDataPath = PhotoFileUtils::GetEditDataPath(exInfo.path);
166 exInfo.editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(exInfo.path);
167 exInfo.editDataSourcePath = PhotoFileUtils::GetEditDataSourcePath(exInfo.path);
168 PushMovingPhotoExternalPath(exInfo.editDataPath, "editDataPath", attachment);
169 PushMovingPhotoExternalPath(exInfo.editDataCameraPath, "editDataCameraPath", attachment);
170 PushMovingPhotoExternalPath(exInfo.editDataSourcePath, "editDataSourcePath", attachment);
171 MEDIA_DEBUG_LOG("editDataPath is %{private}s, editDataCameraPath is %{private}s, editDataSourcePath is %{private}s",
172 DfxUtils::GetSafePath(exInfo.editDataPath).c_str(), DfxUtils::GetSafePath(exInfo.editDataCameraPath).c_str(),
173 DfxUtils::GetSafePath(exInfo.editDataSourcePath).c_str());
174 }
175
GetCleanFileInfo(shared_ptr<FileAsset> & fileAssetPtr)176 FileManagement::CloudSync::CleanFileInfo MediaLibraryPtpOperations::GetCleanFileInfo(shared_ptr<FileAsset>&
177 fileAssetPtr)
178 {
179 CHECK_AND_RETURN_RET_LOG(fileAssetPtr != nullptr, {}, "GetCleanFileInfo fileAssetPtr is nullptr.");
180 FileManagement::CloudSync::CleanFileInfo cleanFileInfo;
181 ExternalInfo externalInfo;
182 externalInfo.size = fileAssetPtr->GetSize();
183 externalInfo.path = fileAssetPtr->GetPath();
184 if (externalInfo.size == INVALID_SIZE) {
185 externalInfo.size = GetAssetSize(externalInfo.path);
186 CHECK_AND_RETURN_RET_LOG(externalInfo.size > INVALID_SIZE, {}, "failed to get asset size.");
187 }
188 externalInfo.cloudId = fileAssetPtr->GetCloudId();
189 externalInfo.subType = fileAssetPtr->GetPhotoSubType();
190 externalInfo.effectMode = fileAssetPtr->GetMovingPhotoEffectMode();
191 externalInfo.originalSubType = fileAssetPtr->GetOriginalSubType();
192 GetMovingPhotoExternalInfo(externalInfo, cleanFileInfo.attachment);
193 externalInfo.dateModified = fileAssetPtr->GetDateModified();
194 externalInfo.displayName = fileAssetPtr->GetDisplayName();
195 externalInfo.editTime = fileAssetPtr->GetPhotoEditTime();
196 GetEditPhotoExternalInfo(externalInfo, cleanFileInfo.attachment);
197 cleanFileInfo.cloudId = externalInfo.cloudId;
198 cleanFileInfo.size = externalInfo.size;
199 cleanFileInfo.modifiedTime = externalInfo.dateModified;
200 cleanFileInfo.path = externalInfo.path;
201 cleanFileInfo.fileName = MediaFileUtils::GetFileName(externalInfo.path);
202 return cleanFileInfo;
203 }
204
BatchDeleteLocalAndCloud(const vector<FileManagement::CloudSync::CleanFileInfo> & fileInfos)205 bool MediaLibraryPtpOperations::BatchDeleteLocalAndCloud(const vector<FileManagement::CloudSync::CleanFileInfo>&
206 fileInfos)
207 {
208 CHECK_AND_RETURN_RET_LOG(!fileInfos.empty(), false, "Batch delete local and cloud fileInfo is empty.");
209 vector<string> failCloudId;
210 auto ret = FileManagement::CloudSync::CloudSyncManager::GetInstance().BatchCleanFile(fileInfos,
211 failCloudId);
212 if (ret != 0) {
213 MEDIA_ERR_LOG("Failed to delete local and cloud photos permanently.");
214 return false;
215 }
216 if (failCloudId.empty()) {
217 MEDIA_DEBUG_LOG("Delete local and cloud photos permanently success");
218 return true;
219 }
220 for (const auto& element : failCloudId) {
221 MEDIA_ERR_LOG("Failed to delete, cloudId is %{public}s.", element.c_str());
222 }
223 return false;
224 }
225
DeleteLocalAndCloudPhotos(vector<shared_ptr<FileAsset>> & subFileAsset)226 int32_t MediaLibraryPtpOperations::DeleteLocalAndCloudPhotos(vector<shared_ptr<FileAsset>> &subFileAsset)
227 {
228 MEDIA_INFO_LOG("DeleteLocalAndCloudPhotos start.");
229 vector<FileManagement::CloudSync::CleanFileInfo> fileInfos;
230 if (subFileAsset.empty()) {
231 MEDIA_INFO_LOG("DeleteLocalAndCloudPhotos subFileAsset is empty.");
232 return E_OK;
233 }
234 for (auto& fileAssetPtr : subFileAsset) {
235 if (fileAssetPtr == nullptr) {
236 continue;
237 }
238 fileInfos.push_back(GetCleanFileInfo(fileAssetPtr));
239 }
240 if (!BatchDeleteLocalAndCloud(fileInfos)) {
241 MEDIA_ERR_LOG("BatchDeleteLocalAndCloud delete media assert fail.");
242 return E_HAS_DB_ERROR;
243 }
244 return E_OK;
245 }
246
GetBurstPhotosInfo(const std::string & burstKey,bool & isLastBurstPhoto,vector<int32_t> & burstFileIds)247 int32_t MediaLibraryPtpOperations::GetBurstPhotosInfo(const std::string &burstKey, bool &isLastBurstPhoto,
248 vector<int32_t> &burstFileIds)
249 {
250 burstFileIds.clear();
251 NativeRdb::RdbPredicates queryPredicates(PhotoColumn::PHOTOS_TABLE);
252 vector<string> columns = { MediaColumn::MEDIA_ID };
253 queryPredicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL, static_cast<int32_t>(BurstCoverLevelType::MEMBER));
254 queryPredicates.EqualTo(PhotoColumn::PHOTO_BURST_KEY, burstKey);
255 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
256 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "rdbStore is null");
257 auto resultSet = rdbStore->Query(queryPredicates, columns);
258 int32_t count = 0;
259 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "resultSet is nullptr");
260 CHECK_AND_RETURN_RET_LOG(
261 resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR, "Cannot get row count of resultset");
262 isLastBurstPhoto = count == 1;
263 CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "have no photo asset");
264 do {
265 burstFileIds.push_back(GetInt32Val(MediaColumn::MEDIA_ID, resultSet));
266 } while (resultSet->GoToNextRow() == NativeRdb::E_OK);
267 resultSet->Close();
268 return NativeRdb::E_OK;
269 }
270
DeletePtpPhoto(NativeRdb::RdbPredicates & rdbPredicate)271 int32_t MediaLibraryPtpOperations::DeletePtpPhoto(NativeRdb::RdbPredicates &rdbPredicate)
272 {
273 int32_t ret = 0;
274 std::vector<std::shared_ptr<FileAsset>> fileAssetVector;
275 std::shared_ptr<FileAsset> fileAsset = QueryPhotoInfo(rdbPredicate);
276 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "fileAsset is nullptr");
277 int32_t position = fileAsset->GetPosition();
278 if (position == static_cast<int32_t>(PhotoPositionType::CLOUD) ||
279 position == static_cast<int32_t>(PhotoPositionType::LOCAL_AND_CLOUD)) {
280 fileAssetVector.push_back(fileAsset);
281 return DeleteLocalAndCloudPhotos(fileAssetVector);
282 }
283 int32_t subType = fileAsset->GetPhotoSubType();
284 int32_t burstCoverLevel = fileAsset->GetBurstCoverLevel();
285 string burstKey = fileAsset->GetBurstKey();
286 bool isBurstCover = false;
287 bool isLastBurstPhoto = false;
288 vector<int32_t> burstFileIds;
289 auto assetRefresh = std::make_shared<AccurateRefresh::AssetAccurateRefresh>(
290 AccurateRefresh::DELETE_PERMANENTLY_BUSSINESS_NAME);
291 if (subType == static_cast<int32_t>(PhotoSubType::BURST)) {
292 isBurstCover = burstCoverLevel == static_cast<int32_t>(BurstCoverLevelType::COVER);
293 ret = GetBurstPhotosInfo(burstKey, isLastBurstPhoto, burstFileIds);
294 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR, "GetBurstPhotosInfo fail.");
295 bool needClearBurst = isLastBurstPhoto || isBurstCover;
296 ret = UpdateBurstPhotoInfo(burstKey, needClearBurst, rdbPredicate, assetRefresh);
297 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR, "UpdateBurstPhotoInfo fail.");
298 }
299 if (isBurstCover) {
300 auto watch = MediaLibraryNotify::GetInstance();
301 CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
302 for (const auto &fileId : burstFileIds) {
303 watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(fileId), NotifyType::NOTIFY_ADD);
304 watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(fileId), NotifyType::NOTIFY_THUMB_ADD);
305 }
306 }
307 return MediaLibraryAssetOperations::DeletePermanently(rdbPredicate, true, assetRefresh);
308 }
309
QueryPhotoInfo(NativeRdb::RdbPredicates & rdbPredicate)310 std::shared_ptr<FileAsset> MediaLibraryPtpOperations::QueryPhotoInfo(NativeRdb::RdbPredicates &rdbPredicate)
311 {
312 vector<string> columns = {
313 PhotoColumn::PHOTO_CLOUD_ID,
314 MediaColumn::MEDIA_SIZE,
315 MediaColumn::MEDIA_DATE_MODIFIED,
316 MediaColumn::MEDIA_FILE_PATH,
317 MediaColumn::MEDIA_NAME,
318 MediaColumn::MEDIA_ID,
319 PhotoColumn::PHOTO_POSITION,
320 PhotoColumn::PHOTO_BURST_KEY,
321 MediaColumn::MEDIA_TYPE,
322 PhotoColumn::PHOTO_SUBTYPE,
323 PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
324 PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
325 PhotoColumn::PHOTO_EDIT_TIME,
326 PhotoColumn::PHOTO_OWNER_ALBUM_ID,
327 PhotoColumn::PHOTO_BURST_COVER_LEVEL,
328 };
329 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
330 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, nullptr, "rdbStore is null");
331 auto resultSet = rdbStore->Query(rdbPredicate, columns);
332 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "QueryPhotoInfo fail");
333 CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "have no photos");
334 return GetAssetFromResultSet(resultSet, columns);
335 }
336
UpdateBurstPhotoInfo(const std::string & burstKey,const bool isCover,NativeRdb::RdbPredicates & rdbPredicate,std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)337 int32_t MediaLibraryPtpOperations::UpdateBurstPhotoInfo(const std::string &burstKey, const bool isCover,
338 NativeRdb::RdbPredicates &rdbPredicate, std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
339 {
340 CHECK_AND_RETURN_RET_LOG(assetRefresh != nullptr, E_HAS_DB_ERROR, "assetRefresh is null");
341 vector<string> whereArgs;
342 string whereClause;
343 int32_t changeRows;
344 int32_t updateCount = 0;
345 NativeRdb::ValuesBucket values;
346 values.PutInt(PhotoColumn::PHOTO_BURST_COVER_LEVEL, static_cast<int32_t>(BurstCoverLevelType::COVER));
347 values.PutString(PhotoColumn::PHOTO_BURST_KEY, "");
348 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
349 if (isCover) {
350 whereClause = PhotoColumn::PHOTO_BURST_KEY + " = ?";
351 whereArgs = {burstKey};
352 changeRows = assetRefresh->Update(updateCount, PhotoColumn::PHOTOS_TABLE, values, whereClause, whereArgs);
353 } else {
354 changeRows = assetRefresh->Update(updateCount, values, rdbPredicate);
355 }
356 MEDIA_INFO_LOG("UpdateBurstPhotoInfo end updateRows:%{public}d", updateCount);
357 CHECK_AND_RETURN_RET_LOG(changeRows == NativeRdb::E_OK && updateCount >= 0, E_HAS_DB_ERROR,
358 "Update failed. changeRows:%{public}d, updateRows:%{public}d", changeRows, updateCount);
359 return E_OK;
360 }
361
DeletePtpAlbum(NativeRdb::RdbPredicates & predicates)362 int32_t MediaLibraryPtpOperations::DeletePtpAlbum(NativeRdb::RdbPredicates &predicates)
363 {
364 std::vector<string> queryAlbumColumns = {PhotoAlbumColumns::ALBUM_ID};
365 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
366 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "rdbStore is nullptr");
367 auto albumResultSet = rdbStore->Query(predicates, queryAlbumColumns);
368 CHECK_AND_RETURN_RET_LOG(albumResultSet != nullptr, E_ERR, "albumResultSet is nullptr");
369 CHECK_AND_RETURN_RET_LOG(albumResultSet->GoToFirstRow() == NativeRdb::E_OK, E_ERR, "get albumResultSet failed");
370 int32_t albumId = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, albumResultSet);
371 albumResultSet->Close();
372 NativeRdb::RdbPredicates queryPredicates(PhotoColumn::PHOTOS_TABLE);
373 queryPredicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
374 NativeRdb::RdbPredicates deletePhotoPredicates(PhotoColumn::PHOTOS_TABLE);
375 deletePhotoPredicates.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
376 std::vector<std::string> photosCloumns = {PhotoColumn::PHOTO_POSITION};
377 auto photosResultSet = rdbStore->Query(deletePhotoPredicates, photosCloumns);
378 CHECK_AND_RETURN_RET_LOG(photosResultSet != nullptr, E_ERR, "photosResultSet is nullptr");
379 CHECK_AND_PRINT_LOG(photosResultSet->GoToFirstRow() == NativeRdb::E_OK, "photosResultSet do not have photo asset");
380 while (photosResultSet->GoToNextRow() == NativeRdb::E_OK) {
381 int32_t position = GetInt32Val(PhotoColumn::PHOTO_POSITION, photosResultSet);
382 if (position == static_cast<int32_t>(PhotoPositionType::CLOUD) ||
383 position == static_cast<int32_t>(PhotoPositionType::LOCAL_AND_CLOUD)) {
384 MediaLibraryAssetOperations::DeletePermanently(deletePhotoPredicates, true);
385 return E_OK;
386 }
387 }
388 MediaLibraryAssetOperations::DeletePermanently(deletePhotoPredicates, true);
389 AccurateRefresh::AlbumAccurateRefresh albumRefresh(AccurateRefresh::DELETE_PTP_ALBUM_BUSSINESS_NAME);
390 int deleteRow = -1;
391 albumRefresh.LogicalDeleteReplaceByUpdate(predicates, deleteRow);
392 CHECK_AND_RETURN_RET_LOG(deleteRow > 0, E_ERR, "delete album fail");
393 albumRefresh.Notify();
394 auto watch = MediaLibraryNotify::GetInstance();
395 CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
396 watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoAlbumColumns::ALBUM_URI_PREFIX,
397 to_string(albumId)), NotifyType::NOTIFY_REMOVE);
398 return E_OK;
399 }
400 // LCOV_EXCL_STOP
401 } // namespace OHOS::Media