• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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