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::AlbumRefreshExecution"
17
18 #include <sstream>
19
20 #include "album_refresh_execution.h"
21 #include "owner_album_info_calculation.h"
22 #include "cloud_enhancement_asset_helper.h"
23 #include "favorite_asset_helper.h"
24 #include "hidden_asset_helper.h"
25 #include "image_asset_helper.h"
26 #include "trash_asset_helper.h"
27 #include "video_asset_helper.h"
28 #include "medialibrary_rdb_utils.h"
29 #include "medialibrary_unistore_manager.h"
30 #include "accurate_debug_log.h"
31 #include "medialibrary_notify.h"
32 #include "album_accurate_refresh_manager.h"
33 #include "medialibrary_data_manager_utils.h"
34 #include "media_file_utils.h"
35 #include "medialibrary_tracer.h"
36 #include "dfx_refresh_manager.h"
37 #include "dfx_refresh_hander.h"
38
39 using namespace std;
40 using namespace OHOS::NativeRdb;
41
42 namespace OHOS {
43 namespace Media::AccurateRefresh {
44
45 mutex AlbumRefreshExecution::albumRefreshMtx_;
46
47 std::unordered_map<PhotoAlbumSubType, SystemAlbumInfoCalculation>
48 AlbumRefreshExecution::systemTypeAlbumCalculations_ = {
49 { PhotoAlbumSubType::FAVORITE, { FavoriteAssetHelper::IsAsset, FavoriteAssetHelper::IsVideoAsset,
50 FavoriteAssetHelper::IsHiddenAsset, FavoriteAssetHelper::IsNewerAsset,
51 FavoriteAssetHelper::IsNewerHiddenAsset, PhotoAlbumSubType::FAVORITE }},
52 { PhotoAlbumSubType::VIDEO, { VideoAssetHelper::IsAsset, VideoAssetHelper::IsVideoAsset,
53 VideoAssetHelper::IsHiddenAsset, VideoAssetHelper::IsNewerAsset,
54 VideoAssetHelper::IsNewerHiddenAsset, PhotoAlbumSubType::VIDEO }},
55 { PhotoAlbumSubType::HIDDEN, { HiddenAssetHelper::IsAsset, HiddenAssetHelper::IsVideoAsset,
56 HiddenAssetHelper::IsHiddenAsset, HiddenAssetHelper::IsNewerAsset,
57 HiddenAssetHelper::IsNewerHiddenAsset, PhotoAlbumSubType::HIDDEN }},
58 { PhotoAlbumSubType::TRASH, { TrashAssetHelper::IsAsset, TrashAssetHelper::IsVideoAsset,
59 TrashAssetHelper::IsHiddenAsset, TrashAssetHelper::IsNewerAsset,
60 TrashAssetHelper::IsNewerHiddenAsset, PhotoAlbumSubType::TRASH }},
61 { PhotoAlbumSubType::IMAGE, { ImageAssetHelper::IsAsset, ImageAssetHelper::IsVideoAsset,
62 ImageAssetHelper::IsHiddenAsset, ImageAssetHelper::IsNewerAsset,
63 ImageAssetHelper::IsNewerHiddenAsset, PhotoAlbumSubType::IMAGE }},
64 { PhotoAlbumSubType::CLOUD_ENHANCEMENT, { CloudEnhancementAssetHelper::IsAsset,
65 CloudEnhancementAssetHelper::IsVideoAsset, CloudEnhancementAssetHelper::IsHiddenAsset,
66 CloudEnhancementAssetHelper::IsNewerAsset, CloudEnhancementAssetHelper::IsNewerHiddenAsset,
67 PhotoAlbumSubType::CLOUD_ENHANCEMENT }}
68 };
69
70 std::unordered_map<int32_t, SystemAlbumInfoCalculation> AlbumRefreshExecution::systemAlbumCalculations_;
71
RefreshAlbum(const vector<PhotoAssetChangeData> & assetChangeDatas,NotifyAlbumType notifyAlbumType,bool isRefreshWithDateModified)72 int32_t AlbumRefreshExecution::RefreshAlbum(const vector<PhotoAssetChangeData> &assetChangeDatas,
73 NotifyAlbumType notifyAlbumType, bool isRefreshWithDateModified)
74 {
75 // 计算影响相册和refresh info,结果放入systemAlbumInfos_和ownerAlbumInfos_
76 CalRefreshInfos(assetChangeDatas);
77 CHECK_AND_RETURN_RET_INFO_LOG(!albumRefreshInfos_.empty(), ACCURATE_REFRESH_RET_OK, "no refresh album");
78
79 // 相册执行逻辑只能串行执行
80 lock_guard<mutex> lock(albumRefreshMtx_);
81 isRefreshWithDateModified_ = isRefreshWithDateModified;
82
83 // 计算相册信息
84 CalAlbumsInfos();
85
86 // 更新相册
87 UpdateAllAlbums(notifyAlbumType);
88
89 return ACCURATE_REFRESH_RET_OK;
90 }
91
CalRefreshInfos(const vector<PhotoAssetChangeData> & assetChangeDatas)92 int32_t AlbumRefreshExecution::CalRefreshInfos(const vector<PhotoAssetChangeData> &assetChangeDatas)
93 {
94 CheckInitSystemCalculation();
95 // 计算系统相册信息
96 {
97 MediaLibraryTracer tracer;
98 tracer.Start("AlbumRefreshExecution::CalRefreshInfos system");
99 for (auto &item : systemAlbumCalculations_) {
100 for (auto const &assetChangeData : assetChangeDatas) {
101 const auto &albumId = item.first;
102 SystemAlbumInfoCalculation &calculation = item.second;
103 auto subTypeInfoIter = systemAlbumRefreshInfos_.find(albumId);
104 if (subTypeInfoIter != systemAlbumRefreshInfos_.end()) {
105 calculation.CalAlbumRefreshInfo(assetChangeData, subTypeInfoIter->second, albumId);
106 continue;
107 }
108 AlbumRefreshInfo refreshInfo;
109 if (calculation.CalAlbumRefreshInfo(assetChangeData, refreshInfo, albumId)) {
110 systemAlbumRefreshInfos_.emplace(albumId, refreshInfo);
111 }
112 }
113 }
114 }
115
116 // 计算用户和来源相册
117 {
118 MediaLibraryTracer tracer;
119 tracer.Start("AlbumRefreshExecution::CalRefreshInfos owner albumId");
120 ownerAlbumRefreshInfos_ = OwnerAlbumInfoCalculation::CalOwnerAlbumRefreshInfo(assetChangeDatas);
121 albumRefreshInfos_.insert(systemAlbumRefreshInfos_.begin(), systemAlbumRefreshInfos_.end());
122 albumRefreshInfos_.insert(ownerAlbumRefreshInfos_.begin(), ownerAlbumRefreshInfos_.end());
123 if (IS_ACCURATE_DEBUG) {
124 for (auto const &albumInfo : albumRefreshInfos_) {
125 ACCURATE_INFO("albumId: %{public}d, refreshInfo: %{public}s", albumInfo.first,
126 albumInfo.second.ToString().c_str());
127 }
128 }
129 }
130
131 return ACCURATE_REFRESH_RET_OK;
132 }
133
CalAlbumsInfos()134 int32_t AlbumRefreshExecution::CalAlbumsInfos()
135 {
136 MediaLibraryTracer tracer;
137 tracer.Start("AlbumRefreshExecution::CalAlbumsInfos");
138 // 查询相册数据
139 albumRefresh_.Init(GetAlbumIds());
140 initAlbumInfos_ = albumRefresh_.GetInitAlbumInfos();
141 if (initAlbumInfos_.empty()) {
142 ACCURATE_DEBUG("empty album Info, insert.");
143 return ACCURATE_REFRESH_RET_OK;
144 }
145
146 // 修改数据
147 for (auto item : initAlbumInfos_) {
148 auto &albumInfo = item.second;
149 auto albumId = albumInfo.albumId_;
150 auto calAlbumInfoIter = albumRefreshInfos_.find(static_cast<PhotoAlbumSubType>(albumId));
151 if (calAlbumInfoIter == albumRefreshInfos_.end()) {
152 MEDIA_ERR_LOG("no album[%{public}d] found", albumInfo.albumId_);
153 continue;
154 }
155 AlbumRefreshInfo &refreshInfo = calAlbumInfoIter->second;
156 auto albumInfoBefore = albumInfo;
157 auto subType = albumInfo.albumSubType_;
158 bool isAccurateRefresh = CalAlbumInfos(albumInfo, refreshInfo, subType);
159 ACCURATE_INFO("albumInfo: %{public}s", albumInfoBefore.ToString(true).c_str());
160 if (isAccurateRefresh) {
161 ACCURATE_INFO("refresh info: %{public}s", refreshInfo.ToString().c_str());
162 ACCURATE_INFO("cal albumInfo: %{public}s", albumInfo.ToString(true).c_str());
163 }
164 }
165
166 return ACCURATE_REFRESH_RET_OK;
167 }
168
Notify()169 int32_t AlbumRefreshExecution::Notify()
170 {
171 albumRefresh_.Notify(dfxRefreshManager_);
172 return ACCURATE_REFRESH_RET_OK;
173 }
174
GetAlbumIds()175 vector<int32_t> AlbumRefreshExecution::GetAlbumIds()
176 {
177 vector<int32_t> albumIds;
178 for (auto const &item : albumRefreshInfos_) {
179 albumIds.push_back(item.first);
180 }
181 return albumIds;
182 }
183
UpdateAllAlbums(NotifyAlbumType notifyAlbumType)184 int32_t AlbumRefreshExecution::UpdateAllAlbums(NotifyAlbumType notifyAlbumType)
185 {
186 MediaLibraryTracer tracer;
187 tracer.Start("AlbumRefreshExecution::UpdateAllAlbums");
188 for (auto &albumId : forceRefreshAlbums_) {
189 // 封装刷新处理;全量刷新指定的相册(系统相册、用户相册、来源相册)
190 ForceUpdateAlbums(albumId, false, notifyAlbumType);
191 }
192
193 for (auto &albumId : forceRefreshHiddenAlbums_) {
194 // 封装刷新处理;全量刷新指定的隐藏相册
195 ForceUpdateAlbums(albumId, true, notifyAlbumType);
196 }
197
198 AccurateUpdateAlbums(notifyAlbumType);
199 return ACCURATE_REFRESH_RET_OK;
200 }
201
ForceUpdateAlbums(int32_t albumId,bool isHidden,NotifyAlbumType notifyAlbumType)202 int32_t AlbumRefreshExecution::ForceUpdateAlbums(int32_t albumId, bool isHidden, NotifyAlbumType notifyAlbumType)
203 {
204 DfxRefreshHander::SetOperationStartTimeHander(dfxRefreshManager_);
205 const auto &iter = initAlbumInfos_.find(albumId);
206 if (iter == initAlbumInfos_.end()) {
207 MEDIA_WARN_LOG("no album info.");
208 return ACCURATE_REFRESH_ALBUM_INFO_NULL;
209 }
210 AlbumRefreshTimestampRecord refreshRecord(albumId, isHidden);
211 MediaLibraryTracer tracer;
212 tracer.Start("AlbumRefreshExecution::ForceUpdateAlbums " + to_string(albumId) + (isHidden ? " hidden" : ""));
213 ACCURATE_DEBUG("force update albumId[%{public}d], isHidden[%{public}d]", albumId, isHidden);
214 auto &albumInfo = iter->second;
215 PhotoAlbumSubType subtype = static_cast<PhotoAlbumSubType>(albumInfo.albumSubType_);
216 ValuesBucket values;
217 NotifyType type = NOTIFY_INVALID;
218 GetUpdateValues(values, albumInfo, isHidden, type);
219 if (values.IsEmpty()) {
220 MEDIA_ERR_LOG("albumId[%{public}d], subType[%{public}d], hidden[%{public}d] no need update.", albumId, subtype,
221 isHidden);
222 refreshRecord.ClearRecord();
223 return ACCURATE_REFRESH_RET_OK;
224 }
225
226 RdbPredicates predicates(PhotoAlbumColumns::TABLE);
227 predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(subtype));
228 predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(albumInfo.albumId_));
229 int32_t changedRows = 0;
230 auto ret = albumRefresh_.Update(changedRows, values, predicates);
231 ACCURATE_DEBUG("ret: %{public}d, changed: %{public}d, type: %{public}d, albumId: %{public}d, isHidden: %{public}d",
232 ret, changedRows, albumInfo.albumSubType_, albumInfo.albumId_, isHidden);
233 if (ret == ACCURATE_REFRESH_RET_OK) {
234 if (!isHidden) {
235 CheckNotifyOldNotification(notifyAlbumType, albumInfo, type);
236 }
237 refreshRecord.RefreshAlbumEnd();
238 }
239 DfxRefreshHander::SetAlbumIdAndOptTimeHander(albumId, isHidden, dfxRefreshManager_);
240 return ACCURATE_REFRESH_RET_OK;
241 }
242
GetUpdateValues(ValuesBucket & values,const AlbumChangeInfo & albumInfo,bool isHidden,NotifyType & type)243 int32_t AlbumRefreshExecution::GetUpdateValues(ValuesBucket &values, const AlbumChangeInfo &albumInfo,
244 bool isHidden, NotifyType &type)
245 {
246 MediaLibraryTracer tracer;
247 tracer.Start("AlbumRefreshExecution::GetUpdateValues");
248 PhotoAlbumSubType subtype = static_cast<PhotoAlbumSubType>(albumInfo.albumSubType_);
249 struct UpdateAlbumData data;
250 data.albumSubtype = albumInfo.albumSubType_;
251 data.albumId = albumInfo.albumId_;
252 data.hiddenCount = albumInfo.hiddenCount_;
253 data.albumCount = albumInfo.count_;
254 data.albumImageCount = albumInfo.imageCount_;
255 data.albumVideoCount = albumInfo.videoCount_;
256 data.hiddenCover = albumInfo.hiddenCoverUri_;
257 data.albumCoverUri = albumInfo.coverUri_;
258 data.coverDateTime = albumInfo.coverDateTime_;
259 data.coverUriSource = albumInfo.coverUriSource_;
260 data.hiddenCoverDateTime = albumInfo.hiddenCoverDateTime_;
261 if (!isHidden && (subtype == PhotoAlbumSubType::USER_GENERIC ||
262 subtype == PhotoAlbumSubType::SOURCE_GENERIC) && isRefreshWithDateModified_) {
263 data.shouldUpdateDateModified = true; // 非隐藏全量刷新时,说明相册封面有变化,需要设置
264 }
265 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
266 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, ACCURATE_REFRESH_RDB_NULL, "rdbStore null");
267 int32_t ret = MediaLibraryRdbUtils::GetUpdateValues(rdbStore, data, values, isHidden);
268 type = data.albumCount < data.newTotalCount ? NOTIFY_ALBUM_ADD_ASSET :
269 (data.albumCount > data.newTotalCount ? NOTIFY_ALBUM_REMOVE_ASSET : NOTIFY_UPDATE);
270 return ret;
271 }
272
CheckUpdateValues(const AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo,ValuesBucket & values)273 void AlbumRefreshExecution::CheckUpdateValues(const AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo,
274 ValuesBucket &values)
275 {
276 if ((albumInfo.albumSubType_ == PhotoAlbumSubType::USER_GENERIC ||
277 albumInfo.albumSubType_ == PhotoAlbumSubType::SOURCE_GENERIC) && refreshInfo.assetModifiedCnt_ > 0 &&
278 isRefreshWithDateModified_) {
279 values.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
280 ACCURATE_DEBUG("album date modified.");
281 }
282 }
283
AccurateUpdateAlbums(NotifyAlbumType notifyAlbumType)284 int32_t AlbumRefreshExecution::AccurateUpdateAlbums(NotifyAlbumType notifyAlbumType)
285 {
286 ACCURATE_INFO("AccurateUpdateAlbums notifyAlbumType[0x%{public}x]", notifyAlbumType);
287 MediaLibraryTracer tracer;
288 tracer.Start("AlbumRefreshExecution::AccurateUpdateAlbums");
289 for (auto &iter : refreshAlbums_) {
290 DfxRefreshHander::SetOperationStartTimeHander(dfxRefreshManager_);
291 auto &albumInfo = iter.second.second;
292 ACCURATE_DEBUG("## Update type: %{public}d, albumId: %{public}d start", albumInfo.albumSubType_,
293 albumInfo.albumId_);
294 const auto &initIter = initAlbumInfos_.find(albumInfo.albumId_);
295 if (initIter == initAlbumInfos_.end()) {
296 MEDIA_WARN_LOG("no album info.");
297 return ACCURATE_REFRESH_ALBUM_INFO_NULL;
298 }
299
300 auto &initAlbumInfo = initIter->second;
301 NotifyType type = NOTIFY_INVALID;
302 ValuesBucket values = albumInfo.GetUpdateValues(initAlbumInfo, type);
303 CheckUpdateValues(albumInfo, iter.second.first, values);
304 if (values.IsEmpty()) {
305 MEDIA_ERR_LOG("no need update.");
306 continue;
307 }
308 RdbPredicates predicates(PhotoAlbumColumns::TABLE);
309 predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(albumInfo.albumId_));
310 int32_t changedRows = 0;
311
312 albumRefresh_.Update(changedRows, values, predicates);
313 auto &albumChangeInfo = iter.second.first;
314 if (albumChangeInfo.IsAlbumInfoRefresh()) {
315 CheckNotifyOldNotification(notifyAlbumType, albumInfo, type);
316 }
317 ACCURATE_DEBUG("## Update type: %{public}d, albumId: %{public}d end", albumInfo.albumSubType_,
318 albumInfo.albumId_);
319 DfxRefreshHander::SetOptEndTimeHander(predicates, dfxRefreshManager_);
320 DfxRefreshHander::SetAlbumIdHander(albumInfo.albumId_, dfxRefreshManager_);
321 }
322 return ACCURATE_REFRESH_RET_OK;
323 }
324
CheckHiddenAlbumInfo(ValuesBucket & values,stringstream & ss)325 void AlbumRefreshExecution::CheckHiddenAlbumInfo(ValuesBucket &values, stringstream &ss)
326 {
327 int32_t hiddenCount;
328 ValueObject value;
329 if (values.GetObject(PhotoAlbumColumns::HIDDEN_COUNT, value)) {
330 value.GetInt(hiddenCount);
331 ss << " hiddenCount: " << hiddenCount;
332 }
333 string hiddenCover;
334 if (values.GetObject(PhotoAlbumColumns::HIDDEN_COVER, value)) {
335 value.GetString(hiddenCover);
336 ss << " hiddenCover: " << hiddenCover;
337 }
338 int64_t hiddenCoverDateTime;
339 if (values.GetObject(PhotoAlbumColumns::HIDDEN_COVER_DATE_TIME, value)) {
340 value.GetLong(hiddenCoverDateTime);
341 ss << " hiddenCoverDateTime: " << hiddenCoverDateTime;
342 }
343 int32_t containHidden;
344 if (values.GetObject(PhotoAlbumColumns::CONTAINS_HIDDEN, value)) {
345 value.GetInt(containHidden);
346 ss << " containHidden: " << containHidden;
347 }
348 }
349
CheckAlbumInfo(ValuesBucket & values,stringstream & ss)350 void AlbumRefreshExecution::CheckAlbumInfo(ValuesBucket &values, stringstream &ss)
351 {
352 int32_t count;
353 ValueObject value;
354 if (values.GetObject(PhotoAlbumColumns::ALBUM_COUNT, value)) {
355 value.GetInt(count);
356 ss << " count: " << count;
357 }
358 string cover;
359 if (values.GetObject(PhotoAlbumColumns::ALBUM_COVER_URI, value)) {
360 value.GetString(cover);
361 ss << " cover: " << cover;
362 }
363 int64_t coverDateTime;
364 if (values.GetObject(PhotoAlbumColumns::COVER_DATE_TIME, value)) {
365 value.GetLong(coverDateTime);
366 ss << " coverDateTime: " << coverDateTime;
367 }
368
369 int32_t videoCount;
370 if (values.GetObject(PhotoAlbumColumns::ALBUM_VIDEO_COUNT, value)) {
371 value.GetInt(videoCount);
372 ss << " videoCount: " << videoCount;
373 }
374
375 int32_t imageCount;
376 if (values.GetObject(PhotoAlbumColumns::ALBUM_IMAGE_COUNT, value)) {
377 value.GetInt(imageCount);
378 ss << " imageCount: " << imageCount;
379 }
380 }
381
CheckUpdateAlbumInfo(const AlbumChangeInfo & albumInfo,bool isHidden)382 void AlbumRefreshExecution::CheckUpdateAlbumInfo(const AlbumChangeInfo &albumInfo, bool isHidden)
383 {
384 ValuesBucket values;
385 NotifyType type;
386 GetUpdateValues(values, albumInfo, isHidden, type);
387 if (values.IsEmpty()) {
388 return;
389 }
390 stringstream ss;
391 ValueObject value;
392 if (isHidden) {
393 CheckHiddenAlbumInfo(values, ss);
394 } else {
395 CheckAlbumInfo(values, ss);
396 }
397
398 int64_t dateModified;
399 if (values.GetObject(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, value)) {
400 value.GetLong(dateModified);
401 ss << "dateModified: " << dateModified;
402 }
403
404 ACCURATE_INFO("album cal wrong, albumId[%{public}d], isHiden[%{public}d]: %{public}s", albumInfo.albumId_,
405 isHidden, ss.str().c_str());
406 }
407
CalAlbumHiddenCount(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo)408 bool AlbumRefreshExecution::CalAlbumHiddenCount(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo)
409 {
410 albumInfo.hiddenCount_ += refreshInfo.deltaHiddenCount_;
411 return refreshInfo.deltaHiddenCount_ != 0;
412 }
413
CalAlbumCount(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo)414 bool AlbumRefreshExecution::CalAlbumCount(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo)
415 {
416 // count 更新
417 albumInfo.count_ += refreshInfo.deltaCount_;
418 albumInfo.videoCount_ += refreshInfo.deltaVideoCount_;
419 albumInfo.imageCount_ += (refreshInfo.deltaCount_ - refreshInfo.deltaVideoCount_);
420 return refreshInfo.deltaCount_ != 0 || refreshInfo.deltaVideoCount_ != 0;
421 }
422
IsValidCover(const PhotoAssetChangeInfo & assetInfo)423 bool AlbumRefreshExecution::IsValidCover(const PhotoAssetChangeInfo &assetInfo)
424 {
425 return assetInfo.fileId_ != INVALID_INT32_VALUE;
426 }
427
CalAlbumInfos(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo,int32_t subType)428 bool AlbumRefreshExecution::CalAlbumInfos(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo,
429 int32_t subType)
430 {
431 bool needRefreshAblum = CalAlbumInfo(albumInfo, refreshInfo, subType);
432 bool needRefreshHiddenAlbum = CalHiddenAlbumInfo(albumInfo, refreshInfo, subType);
433 // 相册的普通信息和隐藏信息在同一个albumInfo中,只刷新其中一类信息时,另一类信息为无效值
434 if (needRefreshAblum || needRefreshHiddenAlbum) {
435 refreshAlbums_.insert(make_pair(albumInfo.albumId_, make_pair(refreshInfo, albumInfo)));
436 return true;
437 }
438 ACCURATE_INFO("accurate refresh album_info[%{public}d], hidden_album_info[%{public}d]", needRefreshAblum,
439 needRefreshHiddenAlbum);
440 return false;
441 }
442
CalAlbumInfo(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo,int32_t subType)443 bool AlbumRefreshExecution::CalAlbumInfo(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo,
444 int32_t subType)
445 {
446 // 计算结果需要forceRefresh
447 if (refreshInfo.isForceRefresh_) {
448 forceRefreshAlbums_.insert(albumInfo.albumId_);
449 ClearAlbumInfo(albumInfo);
450 ACCURATE_DEBUG("force refresh album[%{public}d] info", albumInfo.albumId_);
451 return false;
452 }
453 // 增量计算后相册有变化
454 if (refreshInfo.IsAlbumInfoRefresh()) {
455 bool isTimestampMatch = AlbumAccurateRefreshManager::GetInstance().IsRefreshTimestampMatch(albumInfo.albumId_,
456 false, refreshInfo.albumRefreshTimestamp_);
457 bool isAccurateRefresh = AlbumAccurateRefreshManager::GetInstance().IsAlbumAccurateRefresh(albumInfo.albumId_,
458 false);
459 // 增量计算时间戳不匹配 || 不能增量刷新(需要全量刷新)
460 if (!isTimestampMatch || !isAccurateRefresh) {
461 forceRefreshAlbums_.insert(albumInfo.albumId_);
462 ClearAlbumInfo(albumInfo);
463 ACCURATE_DEBUG("force refresh album[%{public}d] info, isTimestampMatch[%{public}d], "
464 "isAccurateRefresh[%{public}d]", albumInfo.albumId_, isTimestampMatch, isAccurateRefresh);
465 return false;
466 }
467 }
468
469 // 更新count
470 bool isRefreshAlbumCount = CalAlbumCount(albumInfo, refreshInfo);
471 // 更新uri、dateTimeForCover
472 bool isRefreshAlbumCover = CalAlbumCover(albumInfo, refreshInfo, subType);
473
474 // 增量刷新场景:不强制刷新 && count/video count/cover无变化
475 return forceRefreshAlbums_.find(albumInfo.albumId_) == forceRefreshAlbums_.end() &&
476 (isRefreshAlbumCover || isRefreshAlbumCount);
477 }
478
CalHiddenAlbumInfo(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo,int32_t subType)479 bool AlbumRefreshExecution::CalHiddenAlbumInfo(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo,
480 int32_t subType)
481 {
482 if (CheckSetHiddenAlbumInfo(albumInfo)) {
483 return false;
484 }
485 // 计算结果需要forceRefresh || 增量计算后相册有变化(增量计算时间戳不匹配 || 不能增量刷新)
486 if (refreshInfo.isHiddenForceRefresh_) {
487 forceRefreshHiddenAlbums_.insert(albumInfo.albumId_);
488 ClearHiddenAlbumInfo(albumInfo);
489 ACCURATE_DEBUG("force update album[%{public}d] hidden info", albumInfo.albumId_);
490 return false;
491 }
492 if (refreshInfo.IsAlbumHiddenInfoRefresh()) {
493 bool isTimestampMatch = AlbumAccurateRefreshManager::GetInstance().IsRefreshTimestampMatch(albumInfo.albumId_,
494 true, refreshInfo.albumHiddenRefreshTimestamp_);
495 bool isAccurateRefresh = AlbumAccurateRefreshManager::GetInstance().IsAlbumAccurateRefresh(albumInfo.albumId_,
496 true);
497 if (!isTimestampMatch || !isAccurateRefresh) {
498 forceRefreshHiddenAlbums_.insert(albumInfo.albumId_);
499 ClearHiddenAlbumInfo(albumInfo);
500 ACCURATE_DEBUG("force update album[%{public}d] hidden info, isTimestampMatch[%{public}d], "
501 "isAccurateRefresh[%{public}d]", albumInfo.albumId_, isTimestampMatch, isAccurateRefresh);
502 return false;
503 }
504 }
505 bool isRefreshHiddenAlbumCount = CalAlbumHiddenCount(albumInfo, refreshInfo);
506 // 更新hiddenCoverUri、dateTimeForHiddenCover
507 bool isRefreshHiddenAlbumCover = CalAlbumHiddenCover(albumInfo, refreshInfo);
508
509 // 增量刷新场景:不强制刷新 && hidden count/cover无变化
510 return forceRefreshHiddenAlbums_.find(albumInfo.albumId_) ==
511 forceRefreshHiddenAlbums_.end() && (isRefreshHiddenAlbumCover || isRefreshHiddenAlbumCount);
512 }
513
CalCoverSetCover(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo)514 bool AlbumRefreshExecution::CalCoverSetCover(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo)
515 {
516 bool isCoverSet = albumInfo.coverUriSource_ > 0;
517 if (!isCoverSet) {
518 return false;
519 }
520 auto coverFileId = MediaLibraryDataManagerUtils::GetFileIdNumFromPhotoUri(albumInfo.coverUri_);
521 if (coverFileId <= 0 || refreshInfo.removeFileIds.find(coverFileId) != refreshInfo.removeFileIds.end()) {
522 forceRefreshAlbums_.insert(albumInfo.albumId_);
523 ClearAlbumInfo(albumInfo);
524 ACCURATE_DEBUG("cover already set, refresh album for setcover.");
525 } else {
526 ACCURATE_DEBUG("cover already set, no need cal album cover.");
527 }
528 return true;
529 }
530
CalAlbumCover(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo,int32_t subType)531 bool AlbumRefreshExecution::CalAlbumCover(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo,
532 int32_t subType)
533 {
534 if (CalCoverSetCover(albumInfo, refreshInfo)) {
535 return false;
536 }
537 bool isRefreshAlbum = false;
538 // 系统相册、用户、来源资产对比默认为date_taken
539 auto dateTimeForAddCover = refreshInfo.deltaAddCover_.dateTakenMs_;
540 if (subType == static_cast<int32_t>(PhotoAlbumSubType::VIDEO) ||
541 subType == static_cast<int32_t>(PhotoAlbumSubType::IMAGE)) {
542 // date_added
543 dateTimeForAddCover = refreshInfo.deltaAddCover_.dateAddedMs_;
544 } else if (subType == static_cast<int32_t>(PhotoAlbumSubType::HIDDEN)) {
545 // hidden_time
546 dateTimeForAddCover = refreshInfo.deltaAddCover_.hiddenTime_;
547 }
548
549 // 普通cover 更新
550 auto coverFileId = MediaLibraryDataManagerUtils::GetFileIdNumFromPhotoUri(albumInfo.coverUri_);
551 if (IsValidCover(refreshInfo.deltaAddCover_) && refreshInfo.removeFileIds.size() == 0) { // 新增场景
552 bool isRefresh = dateTimeForAddCover > albumInfo.coverDateTime_ ||
553 (dateTimeForAddCover == albumInfo.coverDateTime_ && refreshInfo.deltaAddCover_.fileId_ > coverFileId);
554 if (isRefresh) {
555 albumInfo.coverInfo_ = refreshInfo.deltaAddCover_;
556 albumInfo.coverDateTime_ = dateTimeForAddCover;
557 // 更新coverUri
558 albumInfo.coverUri_ = refreshInfo.deltaAddCover_.uri_;
559 isRefreshAlbum = true;
560 }
561 ACCURATE_DEBUG("Add[%{public}d], refresh[%{public}d], albumInfo cover id: %{public}d, addCover id: %{public}d",
562 albumInfo.albumId_, isRefresh, albumInfo.coverInfo_.fileId_, refreshInfo.deltaAddCover_.fileId_);
563 } else if (!IsValidCover(refreshInfo.deltaAddCover_) && refreshInfo.removeFileIds.size() > 0) { // 删除场景
564 // 当前cover没有removeCover新
565 bool isForceRefresh = refreshInfo.removeFileIds.find(coverFileId) != refreshInfo.removeFileIds.end();
566 if (coverFileId <= 0 || isForceRefresh) {
567 forceRefreshAlbums_.insert(albumInfo.albumId_);
568 ClearAlbumInfo(albumInfo);
569 }
570 ACCURATE_DEBUG("Del[%{public}d], forceRefresh[%{public}d], old cover fileId:%{public}d", albumInfo.albumId_,
571 isForceRefresh, coverFileId);
572 } else if (IsValidCover(refreshInfo.deltaAddCover_) && refreshInfo.removeFileIds.size() > 0) {
573 // 异常场景:同一个相册中cover既有新增又有删除;同一个相册中没有新增也没有删除
574 // 全量刷新指定的系统相册
575 forceRefreshAlbums_.insert(albumInfo.albumId_);
576 ClearAlbumInfo(albumInfo);
577 ACCURATE_ERR("Abnormal[%{public}d], forceRefresh, addCover: %{public}s, remove size: %{public}zu",
578 albumInfo.albumId_, refreshInfo.deltaAddCover_.ToString().c_str(),
579 refreshInfo.removeFileIds.size());
580 }
581 return isRefreshAlbum;
582 }
583
CalAlbumHiddenCover(AlbumChangeInfo & albumInfo,const AlbumRefreshInfo & refreshInfo)584 bool AlbumRefreshExecution::CalAlbumHiddenCover(AlbumChangeInfo &albumInfo, const AlbumRefreshInfo &refreshInfo)
585 {
586 bool isRefreshHiddenAlbum = false;
587 auto coverFileId = MediaLibraryDataManagerUtils::GetFileIdNumFromPhotoUri(albumInfo.hiddenCoverUri_);
588 if (IsValidCover(refreshInfo.deltaAddHiddenCover_) && refreshInfo.removeHiddenFileIds.size() == 0) {
589 // 新增场景
590 bool isRefresh = refreshInfo.deltaAddHiddenCover_.hiddenTime_ > albumInfo.hiddenCoverDateTime_ ||
591 (refreshInfo.deltaAddHiddenCover_.hiddenTime_ == albumInfo.hiddenCoverDateTime_ &&
592 refreshInfo.deltaAddHiddenCover_.fileId_ > coverFileId);
593 if (isRefresh) {
594 albumInfo.hiddenCoverInfo_ = refreshInfo.deltaAddHiddenCover_;
595 albumInfo.hiddenCoverDateTime_ = refreshInfo.deltaAddHiddenCover_.hiddenTime_;
596 // 更新coverUri
597 albumInfo.hiddenCoverUri_ = refreshInfo.deltaAddHiddenCover_.uri_;
598 isRefreshHiddenAlbum = true;
599 }
600 ACCURATE_DEBUG("Add hidden[%{public}d], refresh[%{public}d] album hidden cover id[%{public}d, %{public}d]",
601 albumInfo.albumId_, isRefresh, albumInfo.hiddenCoverInfo_.fileId_,
602 refreshInfo.deltaAddHiddenCover_.fileId_);
603 } else if (!IsValidCover(refreshInfo.deltaAddHiddenCover_) && refreshInfo.removeHiddenFileIds.size() > 0) {
604 // 删除场景
605 // 当前cover没有removeCover新
606 bool isRefresh = refreshInfo.removeHiddenFileIds.find(coverFileId) != refreshInfo.removeHiddenFileIds.end();
607 if (coverFileId <= 0 || isRefresh) {
608 forceRefreshHiddenAlbums_.insert(albumInfo.albumId_);
609 ClearHiddenAlbumInfo(albumInfo);
610 }
611 ACCURATE_DEBUG("Del hidden[%{public}d], forceRefresh[%{public}d], coverFileId[%{public}d]",
612 albumInfo.albumId_, isRefresh, coverFileId);
613 } else if (IsValidCover(refreshInfo.deltaAddHiddenCover_) && refreshInfo.removeHiddenFileIds.size() > 0) {
614 // 异常场景:同一个相册中cover既有新增又有删除
615 // 全量刷新指定的系统相册
616 forceRefreshHiddenAlbums_.insert(albumInfo.albumId_);
617 ClearHiddenAlbumInfo(albumInfo);
618 ACCURATE_DEBUG("Abnormal hidden[%{public}d], force: %{public}s, add/remove[%{public}s/%{public}zu]",
619 albumInfo.albumId_, albumInfo.ToString().c_str(), refreshInfo.deltaAddHiddenCover_.ToString().c_str(),
620 refreshInfo.removeHiddenFileIds.size());
621 }
622 return isRefreshHiddenAlbum;
623 }
624
ClearAlbumInfo(AlbumChangeInfo & albumInfo)625 void AlbumRefreshExecution::ClearAlbumInfo(AlbumChangeInfo &albumInfo)
626 {
627 albumInfo.imageCount_ = INVALID_INT32_VALUE;
628 albumInfo.videoCount_ = INVALID_INT32_VALUE;
629 albumInfo.count_ = INVALID_INT32_VALUE;
630 albumInfo.coverUri_ = EMPTY_STR;
631 albumInfo.coverDateTime_ = INVALID_INT64_VALUE;
632 }
633
ClearHiddenAlbumInfo(AlbumChangeInfo & albumInfo)634 void AlbumRefreshExecution::ClearHiddenAlbumInfo(AlbumChangeInfo &albumInfo)
635 {
636 albumInfo.hiddenCount_ = INVALID_INT32_VALUE;
637 albumInfo.hiddenCoverUri_ = EMPTY_STR;
638 albumInfo.hiddenCoverDateTime_ = INVALID_INT64_VALUE;
639 }
640
CheckNotifyOldNotification(NotifyAlbumType notifyAlbumType,const AlbumChangeInfo & albumInfo,NotifyType type)641 void AlbumRefreshExecution::CheckNotifyOldNotification(NotifyAlbumType notifyAlbumType,
642 const AlbumChangeInfo &albumInfo, NotifyType type)
643 {
644 if (notifyAlbumType == NotifyAlbumType::NO_NOTIFY || notifyAlbumType == NotifyAlbumType::ANA_ALBUM) {
645 ACCURATE_DEBUG("no need old notification");
646 return;
647 }
648 if (type == NotifyType::NOTIFY_INVALID) {
649 ACCURATE_ERR("invalid notify type.");
650 return;
651 }
652
653 if (albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::TRASH) ||
654 albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::HIDDEN)) {
655 ACCURATE_DEBUG("subtype[%{public}d] no need old notification.", albumInfo.albumId_);
656 return;
657 }
658
659 auto watch = MediaLibraryNotify::GetInstance();
660 if (watch == nullptr) {
661 ACCURATE_ERR("watch nullptr no old notification");
662 return;
663 }
664 bool needSystemNotify = notifyAlbumType & NotifyAlbumType::SYS_ALBUM;
665 bool isSystemAlbum = albumInfo.albumType_ == static_cast<int32_t>(PhotoAlbumType::SYSTEM) &&
666 (albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::FAVORITE) ||
667 albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::VIDEO) ||
668 albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::IMAGE) ||
669 albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::CLOUD_ENHANCEMENT));
670
671 bool needUserNotify = notifyAlbumType & NotifyAlbumType::USER_ALBUM;
672 bool isUserAlbum = albumInfo.albumType_ == static_cast<int32_t>(PhotoAlbumType::USER) &&
673 albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::USER_GENERIC);
674
675 bool needSourceNotify = notifyAlbumType & NotifyAlbumType::SOURCE_ALBUM;
676 bool isSourceAlbum = albumInfo.albumType_ == static_cast<int32_t>(PhotoAlbumType::SOURCE) &&
677 albumInfo.albumSubType_ == static_cast<int32_t>(PhotoAlbumSubType::SOURCE_GENERIC);
678
679 bool needNotify = (needSystemNotify && isSystemAlbum) || (needUserNotify && isUserAlbum)
680 || (needSourceNotify && isSourceAlbum);
681 if (needNotify) {
682 watch->Notify(PhotoColumn::PHOTO_URI_PREFIX, type, albumInfo.albumId_);
683 ACCURATE_DEBUG("old notification: type[%{public}d], albumId[%{public}d], notifyAlbumType[0x%{public}x]",
684 type, albumInfo.albumId_, notifyAlbumType);
685 } else {
686 ACCURATE_DEBUG("no notification albumType[%{public}d], subType[%{public}d], notifyAlbumType[0x%{public}x]",
687 albumInfo.albumType_, albumInfo.albumSubType_, notifyAlbumType);
688 }
689 }
690
RefreshAllAlbum(NotifyAlbumType notifyAlbumType,bool isRefreshWithDateModified)691 int32_t AlbumRefreshExecution::RefreshAllAlbum(NotifyAlbumType notifyAlbumType, bool isRefreshWithDateModified)
692 {
693 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
694 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, ACCURATE_REFRESH_RDB_NULL, "rdbStore null");
695 ACCURATE_DEBUG("force update all albums");
696 lock_guard<mutex> lock(albumRefreshMtx_);
697 isRefreshWithDateModified_ = isRefreshWithDateModified;
698 MediaLibraryRdbUtils::UpdateSystemAlbumsByUris(rdbStore, AlbumOperationType::DEFAULT, {}, notifyAlbumType);
699 MediaLibraryRdbUtils::UpdateUserAlbumByUri(rdbStore, {}, notifyAlbumType & USER_ALBUM,
700 isRefreshWithDateModified);
701 MediaLibraryRdbUtils::UpdateSourceAlbumByUri(rdbStore, {}, notifyAlbumType & SOURCE_ALBUM,
702 isRefreshWithDateModified);
703 return ACCURATE_REFRESH_RET_OK;
704 }
705
CheckSetHiddenAlbumInfo(AlbumChangeInfo & albumInfo)706 bool AlbumRefreshExecution::CheckSetHiddenAlbumInfo(AlbumChangeInfo &albumInfo)
707 {
708 if (albumInfo.albumSubType_ == PhotoAlbumSubType::HIDDEN) {
709 albumInfo.hiddenCount_ = albumInfo.count_;
710 albumInfo.hiddenCoverInfo_ = albumInfo.coverInfo_;
711 albumInfo.hiddenCoverUri_ = albumInfo.coverUri_;
712 albumInfo.hiddenCoverDateTime_ = albumInfo.coverDateTime_;
713 ACCURATE_DEBUG("hiddenCount_[%{public}d], hiddenCover[%{public}s], dateTime[%{public}" PRId64 "]",
714 albumInfo.count_, MediaFileUtils::DesensitizeUri(albumInfo.coverUri_).c_str(), albumInfo.coverDateTime_);
715 return true;
716 }
717 return false;
718 }
719
CheckInitSystemCalculation()720 void AlbumRefreshExecution::CheckInitSystemCalculation()
721 {
722 if (!systemAlbumCalculations_.empty()) {
723 return;
724 }
725 lock_guard<mutex> lock(albumRefreshMtx_);
726 if (!systemAlbumCalculations_.empty()) {
727 return;
728 }
729 vector<string> subTypes;
730 for (auto calculation : systemTypeAlbumCalculations_) {
731 auto albumId = MediaLibraryRdbUtils::GetAlbumIdBySubType(calculation.first);
732 if (albumId <= 0) {
733 MEDIA_ERR_LOG("no subType[%{public}d] calculation.", calculation.first);
734 continue;
735 }
736 systemAlbumCalculations_.insert_or_assign(albumId, calculation.second);
737 }
738 }
739
740 } // namespace Media
741 } // namespace OHOS