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
16 #define MLOG_TAG "AccurateRefresh::AlbumAccurateRefresh"
17 #include <cstdint>
18
19 #ifndef MEDIA_REFRESH_TEST
20 #include "cloud_sync_helper.h"
21 #endif
22
23 #include "medialibrary_errno.h"
24 #include "album_accurate_refresh.h"
25 #include "medialibrary_notify_new.h"
26 #include "accurate_debug_log.h"
27 #include "medialibrary_tracer.h"
28 #include "dfx_refresh_hander.h"
29 #include "result_set_utils.h"
30 #include "medialibrary_type_const.h"
31 #include "medialibrary_unistore_manager.h"
32
33 using namespace std;
34 using namespace OHOS::NativeRdb;
35
36 namespace OHOS {
37 namespace Media::AccurateRefresh {
38
AlbumAccurateRefresh(const std::string & targetBusiness,std::shared_ptr<TransactionOperations> trans)39 AlbumAccurateRefresh::AlbumAccurateRefresh(const std::string &targetBusiness,
40 std::shared_ptr<TransactionOperations> trans) : AccurateRefreshBase(targetBusiness, trans)
41 {
42 dataManager_.SetTransaction(trans);
43 }
44
AlbumAccurateRefresh(std::shared_ptr<TransactionOperations> trans)45 AlbumAccurateRefresh::AlbumAccurateRefresh(std::shared_ptr<TransactionOperations> trans) : AccurateRefreshBase(trans)
46 {
47 dataManager_.SetTransaction(trans);
48 }
49
Init()50 int32_t AlbumAccurateRefresh::Init()
51 {
52 return ACCURATE_REFRESH_RET_OK;
53 }
54
Init(const AbsRdbPredicates & predicates)55 int32_t AlbumAccurateRefresh::Init(const AbsRdbPredicates &predicates)
56 {
57 if (!IsValidTable(predicates.GetTableName())) {
58 return ACCURATE_REFRESH_RDB_INVALITD_TABLE;
59 }
60
61 return dataManager_.Init(predicates);
62 }
63
Init(const string & sql,const vector<ValueObject> bindArgs)64 int32_t AlbumAccurateRefresh::Init(const string &sql, const vector<ValueObject> bindArgs)
65 {
66 return dataManager_.Init(sql, bindArgs);
67 }
68
Init(const std::vector<int32_t> & albumIds)69 int32_t AlbumAccurateRefresh::Init(const std::vector<int32_t> &albumIds)
70 {
71 return dataManager_.InitAlbumInfos(albumIds);
72 }
73
Notify(std::shared_ptr<DfxRefreshManager> dfxRefreshManager)74 int32_t AlbumAccurateRefresh::Notify(std::shared_ptr<DfxRefreshManager> dfxRefreshManager)
75 {
76 if (dataManager_.CheckIsForRecheck()) {
77 return NotifyForReCheck();
78 }
79 return Notify(dataManager_.GetChangeDatas(), dfxRefreshManager);
80 }
81
Notify(vector<AlbumChangeData> albumChangeDatas,std::shared_ptr<DfxRefreshManager> dfxRefreshManager)82 int32_t AlbumAccurateRefresh::Notify(vector<AlbumChangeData> albumChangeDatas,
83 std::shared_ptr<DfxRefreshManager> dfxRefreshManager)
84 {
85 if (albumChangeDatas.empty()) {
86 MEDIA_WARN_LOG("albumChangeDatas empty.");
87 return ACCURATE_REFRESH_INPUT_PARA_ERR;
88 }
89 notifyExe_.Notify(albumChangeDatas);
90 if (dfxRefreshManager != nullptr) {
91 dfxRefreshManager->SetEndTime();
92 } else if (dfxRefreshManager_ != nullptr) {
93 dfxRefreshManager_->SetEndTime();
94 }
95
96 return ACCURATE_REFRESH_RET_OK;
97 }
98
NotifyAddAlbums(const vector<string> & albumIdsStr)99 int32_t AlbumAccurateRefresh::NotifyAddAlbums(const vector<string> &albumIdsStr)
100 {
101 return Notify(dataManager_.GetAlbumDatasFromAddAlbum(albumIdsStr));
102 }
103
UpdateModifiedDatasInner(const std::vector<int> & albumIds,RdbOperation operation,PendingInfo pendingInfo)104 int32_t AlbumAccurateRefresh::UpdateModifiedDatasInner(const std::vector<int> &albumIds, RdbOperation operation,
105 PendingInfo pendingInfo)
106 {
107 auto modifiedAlbumIds = albumIds;
108 if (modifiedAlbumIds.empty()) {
109 MEDIA_WARN_LOG("modifiedAlbumIds empty.");
110 return ACCURATE_REFRESH_INPUT_PARA_ERR;
111 }
112 DfxRefreshHander::SetAlbumIdHander(albumIds, dfxRefreshManager_);
113 int32_t err = dataManager_.UpdateModifiedDatasInner(modifiedAlbumIds, operation, pendingInfo);
114 CHECK_AND_RETURN_RET_WARN_LOG(err == ACCURATE_REFRESH_RET_OK, err,
115 "UpdateModifiedDatasInner failed, err:%{public}d", err);
116 err = dataManager_.PostProcessModifiedDatas(modifiedAlbumIds);
117 CHECK_AND_RETURN_RET_WARN_LOG(err == ACCURATE_REFRESH_RET_OK, err,
118 "PostProcessModifiedDatas failed, err:%{public}d", err);
119 return ACCURATE_REFRESH_RET_OK;
120 }
121
UpdateModifiedDatas()122 int32_t AlbumAccurateRefresh::UpdateModifiedDatas()
123 {
124 return dataManager_.UpdateModifiedDatas();
125 }
126
GetInitAlbumInfos()127 unordered_map<int32_t, AlbumChangeInfo> AlbumAccurateRefresh::GetInitAlbumInfos()
128 {
129 return dataManager_.GetInitAlbumInfos();
130 }
131
GetReturningKeyName()132 string AlbumAccurateRefresh::GetReturningKeyName()
133 {
134 return PhotoAlbumColumns::ALBUM_ID;
135 }
136
LogicalDeleteReplaceByUpdate(MediaLibraryCommand & cmd,int32_t & deletedRows)137 int32_t AlbumAccurateRefresh::LogicalDeleteReplaceByUpdate(MediaLibraryCommand &cmd, int32_t &deletedRows)
138 {
139 if (!IsValidTable(cmd.GetTableName())) {
140 return ACCURATE_REFRESH_RDB_INVALITD_TABLE;
141 }
142 return DeleteCommon([&](ValuesBucket &values) {
143 return Update(deletedRows, values, *(cmd.GetAbsRdbPredicates()), RDB_OPERATION_REMOVE);
144 });
145 }
146
LogicalDeleteReplaceByUpdate(const AbsRdbPredicates & predicates,int & deletedRows)147 int32_t AlbumAccurateRefresh::LogicalDeleteReplaceByUpdate(const AbsRdbPredicates &predicates, int &deletedRows)
148 {
149 DfxRefreshHander::SetOperationStartTimeHander(dfxRefreshManager_);
150 if (!IsValidTable(predicates.GetTableName())) {
151 return ACCURATE_REFRESH_RDB_INVALITD_TABLE;
152 }
153 int32_t ret = DeleteCommon([&](ValuesBucket& values) {
154 return Update(deletedRows, values, predicates, RDB_OPERATION_REMOVE);
155 });
156 DfxRefreshHander::SetOptEndTimeHander(predicates, dfxRefreshManager_);
157 return ret;
158 }
159
DeleteCommon(function<int32_t (ValuesBucket &)> updateExe)160 int32_t AlbumAccurateRefresh::DeleteCommon(function<int32_t(ValuesBucket&)> updateExe)
161 {
162 MEDIA_INFO_LOG("DeleteCommon enter");
163 MediaLibraryTracer tracer;
164 tracer.Start("AlbumAccurateRefresh::DeleteCommon");
165 ValuesBucket valuesBucket;
166 valuesBucket.PutInt(PhotoAlbumColumns::ALBUM_DIRTY, static_cast<int32_t>(DirtyType::TYPE_DELETED));
167 auto ret = updateExe(valuesBucket);
168 if (ret != NativeRdb::E_OK) {
169 MEDIA_ERR_LOG("rdbStore_->Delete failed, ret = %{public}d", ret);
170 return E_HAS_DB_ERROR;
171 }
172
173 #ifndef MEDIA_REFRESH_TEST
174 if (!trans_) {
175 CloudSyncHelper::GetInstance()->StartSync(); // 事务场景不需要执行
176 ACCURATE_DEBUG("Delete update done, start sync.");
177 }
178 #endif
179
180 return ACCURATE_REFRESH_RET_OK;
181 }
182
IsValidTable(std::string tableName)183 bool AlbumAccurateRefresh::IsValidTable(std::string tableName)
184 {
185 return PhotoAlbumColumns::TABLE == tableName;
186 }
187
NotifyForReCheck()188 int32_t AlbumAccurateRefresh::NotifyForReCheck()
189 {
190 Notification::NotifyInfoInner notifyInfo;
191 notifyInfo.tableType = Notification::NotifyTableType::PHOTO_ALBUM;
192 notifyInfo.operationType = Notification::ALBUM_OPERATION_RECHECK;
193 Notification::MediaLibraryNotifyNew::AddItem(notifyInfo);
194 ACCURATE_DEBUG("album recheck");
195 return ACCURATE_REFRESH_RET_OK;
196 }
197
IsCoverContentChange(string & fileId)198 bool AlbumAccurateRefresh::IsCoverContentChange(string &fileId)
199 {
200 CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsValidInteger(fileId), false, "invalid input param");
201 CHECK_AND_RETURN_RET_LOG(stoi(fileId) > 0, false, "fileId is invalid");
202 MEDIA_INFO_LOG("IsCoverContentChange in, fileId: %{public}s", fileId.c_str());
203
204 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
205 RdbPredicates predicates(PhotoAlbumColumns::TABLE);
206 vector<string> columns = {PhotoAlbumColumns::ALBUM_ID, PhotoAlbumColumns::ALBUM_COVER_URI,
207 PhotoAlbumColumns::HIDDEN_COVER};
208 shared_ptr<ResultSet> resultSet = rdbStore->Query(predicates, columns);
209 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "resultSet is null!");
210 int32_t rowCount = 0;
211 resultSet->GetRowCount(rowCount);
212 CHECK_AND_RETURN_RET_LOG(rowCount > 0, false, "result rowCount is: %{public}d", rowCount);
213
214 vector<int32_t> albumIds;
215 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
216 int32_t albumId = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_ID,
217 resultSet, TYPE_INT32));
218 string coverUri = get<string>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_COVER_URI,
219 resultSet, TYPE_STRING));
220 string hiddenCover = get<string>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::HIDDEN_COVER,
221 resultSet, TYPE_STRING));
222 if ((coverUri != "" && MediaFileUtils::GetIdFromUri(coverUri) == fileId)
223 || (hiddenCover != "" && MediaFileUtils::GetIdFromUri(hiddenCover) == fileId)) {
224 albumIds.push_back(albumId);
225 }
226 }
227 resultSet->Close();
228
229 if (!albumIds.empty()) {
230 NotifyAlbumsCoverChange(fileId, albumIds);
231 return true;
232 }
233 return false;
234 }
235
NotifyAlbumsCoverChange(string & fileId,vector<int32_t> & albumIds)236 void AlbumAccurateRefresh::NotifyAlbumsCoverChange(string &fileId, vector<int32_t> &albumIds)
237 {
238 CHECK_AND_RETURN_LOG(MediaFileUtils::IsValidInteger(fileId), "invalid input param");
239 CHECK_AND_RETURN_LOG(stoi(fileId) > 0, "fileId is invalid");
240 CHECK_AND_RETURN_LOG(!albumIds.empty(), "no album cover has changed");
241 Init(albumIds);
242 UpdateModifiedDatasInner(albumIds, RDB_OPERATION_UPDATE);
243 vector<AlbumChangeData> albumChangeDatas = dataManager_.GetChangeDatas();
244 for (auto &albumChangeData : albumChangeDatas) {
245 if (MediaFileUtils::GetIdFromUri(albumChangeData.infoAfterChange_.coverUri_) == fileId) {
246 albumChangeData.infoAfterChange_.isCoverChange_ = true;
247 continue;
248 }
249 if (MediaFileUtils::GetIdFromUri(albumChangeData.infoAfterChange_.hiddenCoverUri_) == fileId) {
250 albumChangeData.infoAfterChange_.isHiddenCoverChange_ = true;
251 continue;
252 }
253 }
254 Notify(albumChangeDatas);
255 }
256
257 } // namespace Media
258 } // namespace OHOS