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::AssetChangeNotifyExecution"
17 #include "asset_change_notify_execution.h"
18
19 #include "trash_asset_helper.h"
20 #include "hidden_asset_helper.h"
21 #include "accurate_debug_log.h"
22 #include "medialibrary_notify_new.h"
23
24 namespace OHOS {
25 namespace Media::AccurateRefresh {
26 using namespace std;
27 using namespace OHOS::Media::Notification;
28
29 const std::vector<std::pair<std::function<bool(std::pair<AssetType, AssetType>)>, Notification::AssetRefreshOperation>>
30 NORMAL_ASSET_OPERATION_CALS = {
31 {
__anonb9eb83960102() 32 [](std::pair<AssetType, AssetType> info) -> bool {
33 return info.first != ASSET_NORMAL && info.second == ASSET_NORMAL;
34 },
35 Notification::ASSET_OPERATION_UPDATE_ADD_NORMAL
36 },
37 {
__anonb9eb83960202() 38 [](std::pair<AssetType, AssetType> info) -> bool {
39 return info.first == ASSET_NORMAL && info.second != ASSET_NORMAL;
40 },
41 Notification::ASSET_OPERATION_UPDATE_REMOVE_NORMAL
42 },
43 {
__anonb9eb83960302() 44 [](std::pair<AssetType, AssetType> info) -> bool {
45 return info.first == ASSET_NORMAL && info.second == ASSET_NORMAL;
46 },
47 Notification::ASSET_OPERATION_UPDATE_NORMAL
48 },
49 };
50 const std::vector<std::pair<std::function<bool(std::pair<AssetType, AssetType>)>, Notification::AssetRefreshOperation>>
51 HIDDEN_ASSET_OPERATION_CALS = {
52 {
__anonb9eb83960402() 53 [](std::pair<AssetType, AssetType> info) -> bool {
54 return info.first != ASSET_HIDDEN && info.second == ASSET_HIDDEN;
55 },
56 Notification::ASSET_OPERATION_UPDATE_ADD_HIDDEN
57 },
58 {
__anonb9eb83960502() 59 [](std::pair<AssetType, AssetType> info) -> bool {
60 return info.first == ASSET_HIDDEN && info.second != ASSET_HIDDEN;
61 },
62 Notification::ASSET_OPERATION_UPDATE_REMOVE_HIDDEN
63 },
64 {
__anonb9eb83960602() 65 [](std::pair<AssetType, AssetType> info) -> bool {
66 return info.first == ASSET_HIDDEN && info.second == ASSET_HIDDEN;
67 },
68 Notification::ASSET_OPERATION_UPDATE_HIDDEN
69 },
70 };
71 const std::vector<std::pair<std::function<bool(std::pair<AssetType, AssetType>)>, Notification::AssetRefreshOperation>>
72 TRASH_ASSET_OPERATION_CALS = {
73 {
__anonb9eb83960702() 74 [](std::pair<AssetType, AssetType> info) -> bool {
75 return (info.first & ASSET_TRASH) != ASSET_TRASH && (info.second & ASSET_TRASH) == ASSET_TRASH;
76 },
77 Notification::ASSET_OPERATION_UPDATE_ADD_TRASH
78 },
79 {
__anonb9eb83960802() 80 [](std::pair<AssetType, AssetType> info) -> bool {
81 return (info.first & ASSET_TRASH) == ASSET_TRASH && (info.second & ASSET_TRASH) != ASSET_TRASH;
82 },
83 Notification::ASSET_OPERATION_UPDATE_REMOVE_TRASH
84 },
85 {
__anonb9eb83960902() 86 [](std::pair<AssetType, AssetType> info) -> bool {
87 return (info.first & ASSET_TRASH) == ASSET_TRASH && (info.second & ASSET_TRASH) == ASSET_TRASH;
88 },
89 Notification::ASSET_OPERATION_UPDATE_TRASH
90 },
91 };
92
Notify(const vector<PhotoAssetChangeData> & changeDatas)93 void AssetChangeNotifyExecution::Notify(const vector<PhotoAssetChangeData> &changeDatas)
94 {
95 // 轮询所有的changeDatas
96 for (auto &changeData : changeDatas) {
97 auto &infoBefore = changeData.infoBeforeChange_;
98 auto &infoAfter = changeData.infoAfterChange_;
99 auto rdbOperation = changeData.operation_;
100 if (rdbOperation == RDB_OPERATION_ADD) {
101 AssetRefreshOperation operationType = GetAddOperation(infoAfter);
102 if (operationType != ASSET_OPERATION_UNDEFINED) {
103 InsertNotifyInfo(operationType, changeData);
104 } else {
105 MEDIA_WARN_LOG("invalid after asset info:%{public}s", infoAfter.ToString().c_str());
106 }
107 } else if (rdbOperation == RDB_OPERATION_REMOVE) {
108 AssetRefreshOperation operationType = GetRemoveOperation(infoBefore);
109 if (operationType != ASSET_OPERATION_UNDEFINED) {
110 InsertNotifyInfo(operationType, changeData);
111 } else {
112 MEDIA_WARN_LOG("invalid before asset info:%{public}s", infoBefore.ToString().c_str());
113 }
114 } else if (rdbOperation == RDB_OPERATION_UPDATE) {
115 InsertNormalAssetOperation(changeData);
116 InsertTrashAssetOperation(changeData);
117 InsertHiddenlAssetOperation(changeData);
118 }
119 }
120
121 for (auto &item : notifyInfos_) {
122 NotifyInfoInner notifyInfo;
123 notifyInfo.tableType = NotifyTableType::PHOTOS;
124 notifyInfo.operationType = item.first;
125 NotifyLevel level;
126 notifyInfo.notifyLevel = level;
127 auto &changeDatas = item.second;
128 for (auto &changeData : changeDatas) {
129 notifyInfo.infos.push_back(changeData);
130 ACCURATE_INFO("notify PHOTOS info: operationType(0x%{public}x), level(%{public}d), info(%{public}s)",
131 static_cast<int32_t>(item.first),
132 static_cast<int32_t>(notifyInfo.notifyLevel.priority), changeData.ToString().c_str());
133 }
134 // 调用发送通知接口
135 Notification::MediaLibraryNotifyNew::AddItem(notifyInfo);
136 }
137 }
138
InsertNotifyInfo(AssetRefreshOperation operationType,const PhotoAssetChangeData & changeData)139 void AssetChangeNotifyExecution::InsertNotifyInfo(AssetRefreshOperation operationType,
140 const PhotoAssetChangeData &changeData)
141 {
142 PhotoAssetChangeData modifiedChangeData = changeData;
143 if ((operationType & ASSET_ADD) == ASSET_ADD) {
144 modifiedChangeData.infoBeforeChange_.fileId_ = INVALID_INT32_VALUE;
145 ACCURATE_DEBUG("origin data: %{public}s", changeData.ToString(true).c_str());
146 ACCURATE_DEBUG("modify add data: %{public}s", modifiedChangeData.ToString(true).c_str());
147 } else if ((operationType & ASSET_REMOVE) == ASSET_REMOVE) {
148 modifiedChangeData.infoAfterChange_.fileId_ = INVALID_INT32_VALUE;
149 ACCURATE_DEBUG("origin data: %{public}s", changeData.ToString(true).c_str());
150 ACCURATE_DEBUG("modify remove data: %{public}s", modifiedChangeData.ToString(true).c_str());
151 }
152 auto iter = notifyInfos_.find(operationType);
153 if (iter == notifyInfos_.end()) {
154 vector<PhotoAssetChangeData> infos;
155 infos.push_back(modifiedChangeData);
156 notifyInfos_.emplace(operationType, infos);
157 } else {
158 auto &infos = iter->second;
159 infos.push_back(modifiedChangeData);
160 }
161 }
162
GetAddOperation(const PhotoAssetChangeInfo & changeInfo)163 AssetRefreshOperation AssetChangeNotifyExecution::GetAddOperation(const PhotoAssetChangeInfo &changeInfo)
164 {
165 if (TrashAssetHelper::IsAsset(changeInfo)) {
166 return ASSET_OPERATION_ADD_TRASH;
167 }
168 if (HiddenAssetHelper::IsAsset(changeInfo)) {
169 return ASSET_OPERATION_ADD_HIDDEN;
170 }
171 if (AlbumAssetHelper::IsCommonSystemAsset(changeInfo)) {
172 return ASSET_OPERATION_ADD;
173 }
174 return ASSET_OPERATION_UNDEFINED;
175 }
176
GetRemoveOperation(const PhotoAssetChangeInfo & changeInfo)177 AssetRefreshOperation AssetChangeNotifyExecution::GetRemoveOperation(const PhotoAssetChangeInfo &changeInfo)
178 {
179 if (TrashAssetHelper::IsAsset(changeInfo)) {
180 return ASSET_OPERATION_REMOVE_TRASH;
181 }
182 if (HiddenAssetHelper::IsAsset(changeInfo)) {
183 return ASSET_OPERATION_REMOVE_HIDDEN;
184 }
185 if (AlbumAssetHelper::IsCommonSystemAsset(changeInfo)) {
186 return ASSET_OPERATION_REMOVE;
187 }
188 return ASSET_OPERATION_UNDEFINED;
189 }
190
InsertNormalAssetOperation(const PhotoAssetChangeData & changeData)191 void AssetChangeNotifyExecution::InsertNormalAssetOperation(const PhotoAssetChangeData &changeData)
192 {
193 AssetType before =
194 AlbumAssetHelper::IsCommonSystemAsset(changeData.infoBeforeChange_) ? ASSET_NORMAL : ASSET_INVALID;
195 AssetType after =
196 AlbumAssetHelper::IsCommonSystemAsset(changeData.infoAfterChange_) ? ASSET_NORMAL : ASSET_INVALID;
197 ACCURATE_DEBUG("before: 0x%{public}x, after: 0x%{public}x", static_cast<int32_t>(before),
198 static_cast<int32_t>(after));
199 for (auto &operationCal : NORMAL_ASSET_OPERATION_CALS) {
200 if (operationCal.first({before, after})) {
201 InsertNotifyInfo(operationCal.second, changeData);
202 ACCURATE_DEBUG("insert normal operation: %{public}x", operationCal.second);
203 }
204 }
205 }
206
InsertTrashAssetOperation(const PhotoAssetChangeData & changeData)207 void AssetChangeNotifyExecution::InsertTrashAssetOperation(const PhotoAssetChangeData &changeData)
208 {
209 AssetType before = TrashAssetHelper::IsAsset(changeData.infoBeforeChange_) ? ASSET_TRASH : ASSET_INVALID;
210 AssetType after = TrashAssetHelper::IsAsset(changeData.infoAfterChange_) ? ASSET_TRASH : ASSET_INVALID;
211 ACCURATE_DEBUG("before: 0x%{public}x, after: 0x%{public}x", static_cast<int32_t>(before),
212 static_cast<int32_t>(after));
213 for (auto &operationCal : TRASH_ASSET_OPERATION_CALS) {
214 if (operationCal.first({before, after})) {
215 InsertNotifyInfo(operationCal.second, changeData);
216 ACCURATE_DEBUG("insert trash operation: %{public}x", operationCal.second);
217 }
218 }
219 }
220
InsertHiddenlAssetOperation(const PhotoAssetChangeData & changeData)221 void AssetChangeNotifyExecution::InsertHiddenlAssetOperation(const PhotoAssetChangeData &changeData)
222 {
223 AssetType before = HiddenAssetHelper::IsAsset(changeData.infoBeforeChange_) ? ASSET_HIDDEN : ASSET_INVALID;
224 AssetType after = HiddenAssetHelper::IsAsset(changeData.infoAfterChange_) ? ASSET_HIDDEN : ASSET_INVALID;
225 ACCURATE_DEBUG("before: 0x%{public}x, after: 0x%{public}x", static_cast<int32_t>(before),
226 static_cast<int32_t>(after));
227 for (auto &operationCal : HIDDEN_ASSET_OPERATION_CALS) {
228 if (operationCal.first({before, after})) {
229 InsertNotifyInfo(operationCal.second, changeData);
230 ACCURATE_DEBUG("insert hidden operation: %{public}x", operationCal.second);
231 }
232 }
233 }
234
235 } // namespace Media
236 } // namespace OHOS