• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "MediaLibraryAllAlbumRefreshProcessor"
17 
18 #include "medialibrary_all_album_refresh_processor.h"
19 
20 #include "albums_refresh_manager.h"
21 #include "cloud_sync_helper.h"
22 #include "ffrt.h"
23 #include "ffrt_inner.h"
24 #include "media_log.h"
25 #include "medialibrary_errno.h"
26 #include "medialibrary_rdb_utils.h"
27 #include "medialibrary_unistore_manager.h"
28 #include "photo_album_column.h"
29 #include "vision_album_column.h"
30 #include "vision_column.h"
31 
32 namespace OHOS {
33 namespace Media {
34 using namespace std;
35 namespace {
36 const int64_t REFRESH_ALL_ALBUMS_INTERVAL = 86400000000;  // 24 hours
37 }
38 
39 shared_ptr<MediaLibraryAllAlbumRefreshProcessor> MediaLibraryAllAlbumRefreshProcessor::instance_ = nullptr;
40 mutex MediaLibraryAllAlbumRefreshProcessor::instanceMutex_;
41 
GetInstance()42 shared_ptr<MediaLibraryAllAlbumRefreshProcessor> MediaLibraryAllAlbumRefreshProcessor::GetInstance()
43 {
44     if (instance_ == nullptr) {
45         lock_guard<mutex> guard(instanceMutex_);
46         if (instance_ != nullptr) {
47             return instance_;
48         }
49         auto *mediaLibraryAllAlbumRefreshProcessor = new (nothrow)MediaLibraryAllAlbumRefreshProcessor();
50         if (mediaLibraryAllAlbumRefreshProcessor == nullptr) {
51             MEDIA_ERR_LOG("Failed to new MediaLibraryAllAlbumRefreshProcessor");
52         }
53         instance_ = shared_ptr<MediaLibraryAllAlbumRefreshProcessor>(mediaLibraryAllAlbumRefreshProcessor);
54     }
55     return instance_;
56 }
57 
MediaLibraryAllAlbumRefreshProcessor()58 MediaLibraryAllAlbumRefreshProcessor::MediaLibraryAllAlbumRefreshProcessor()
59 {
60 }
61 
GetNowTimeUs()62 int64_t MediaLibraryAllAlbumRefreshProcessor::GetNowTimeUs()
63 {
64     struct timespec t;
65     constexpr int64_t SEC_TO_USEC = 1e6;
66     constexpr int64_t NSEC_TO_USEC = 1e3;
67     clock_gettime(CLOCK_REALTIME, &t);
68     return t.tv_sec * SEC_TO_USEC + t.tv_nsec / NSEC_TO_USEC;
69 }
70 
OnCurrentStatusChanged(bool currentStatus)71 void MediaLibraryAllAlbumRefreshProcessor::OnCurrentStatusChanged(bool currentStatus)
72 {
73     std::lock_guard<std::mutex> lock(refreshAllAlbumsLock_);
74     currentStatus_ = currentStatus;
75     MEDIA_INFO_LOG("OnCurrentStatusChanged! %{public}d", currentStatus_);
76     if (currentStatus_) {
77         PostRefreshAllAlbumsTask();
78     }
79 }
80 
OnCloudSyncStateChanged(bool isCloudSyncing)81 void MediaLibraryAllAlbumRefreshProcessor::OnCloudSyncStateChanged(bool isCloudSyncing)
82 {
83     std::lock_guard<std::mutex> lock(refreshAllAlbumsLock_);
84     isCloudSyncing_ = isCloudSyncing;
85     MEDIA_INFO_LOG("OnCloudSyncStateChanged! %{public}d", isCloudSyncing_);
86     if (!isCloudSyncing_) {
87         PostRefreshAllAlbumsTask();
88     }
89 }
90 
CheckRefreshConditionLocked()91 bool MediaLibraryAllAlbumRefreshProcessor::CheckRefreshConditionLocked()
92 {
93     return currentStatus_ && !isCloudSyncing_ &&
94            (albumRefreshStatus_ != AlbumRefreshStatus::NOT_START || lastRefreshAllAlbumsTime_ == 0 ||
95                GetNowTimeUs() - lastRefreshAllAlbumsTime_ > REFRESH_ALL_ALBUMS_INTERVAL);
96 }
97 
GetNextRefreshStatus(AlbumRefreshStatus albumRefreshStatus)98 AlbumRefreshStatus GetNextRefreshStatus(AlbumRefreshStatus albumRefreshStatus)
99 {
100     switch (albumRefreshStatus) {
101         case AlbumRefreshStatus::NOT_START:
102             return AlbumRefreshStatus::SYSTEM;
103         case AlbumRefreshStatus::SYSTEM:
104             return AlbumRefreshStatus::USER;
105         case AlbumRefreshStatus::USER:
106             return AlbumRefreshStatus::SOURCE;
107         case AlbumRefreshStatus::SOURCE:
108             return AlbumRefreshStatus::ANALYSIS;
109         case AlbumRefreshStatus::ANALYSIS:
110             return AlbumRefreshStatus::NOT_START;
111         default:
112             return AlbumRefreshStatus::NOT_START;
113     }
114 }
115 
GetAlbumId(const shared_ptr<NativeRdb::ResultSet> & resultSet)116 static int32_t GetAlbumId(const shared_ptr<NativeRdb::ResultSet>& resultSet)
117 {
118     int32_t albumId = 0;
119     CHECK_AND_RETURN_RET_LOG(resultSet->GetInt(0, albumId) == NativeRdb::E_OK,
120         E_HAS_DB_ERROR, "Failed to get album_id");
121     return albumId;
122 }
123 
GetPhotoAlbumIds(PhotoAlbumSubType albumSubtype,int32_t currentAlbumId,vector<int32_t> & albumIds)124 int32_t GetPhotoAlbumIds(PhotoAlbumSubType albumSubtype, int32_t currentAlbumId, vector<int32_t>& albumIds)
125 {
126     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
127     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "rdbStore is null");
128 
129     NativeRdb::RdbPredicates predicates(PhotoAlbumColumns::TABLE);
130     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(albumSubtype))
131     ->And()
132     ->GreaterThan(PhotoAlbumColumns::ALBUM_ID, currentAlbumId)
133     ->OrderByAsc(PhotoAlbumColumns::ALBUM_ID);
134     vector<string> columns = { PhotoAlbumColumns::ALBUM_ID };
135     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->Query(predicates, columns);
136     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Failed to query photo album");
137 
138     while (resultSet->GoToNextRow() == E_OK) {
139         int32_t albumId = GetAlbumId(resultSet);
140         if (albumId <= 0) {
141             MEDIA_WARN_LOG("Failed to GetAlbumId: %{public}d", albumId);
142             continue;
143         }
144         albumIds.push_back(albumId);
145     }
146     return E_OK;
147 }
148 
GetAnalysisAlbumIds(int32_t currentAlbumId,vector<int32_t> & albumIds)149 int32_t GetAnalysisAlbumIds(int32_t currentAlbumId, vector<int32_t>& albumIds)
150 {
151     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
152     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "rdbStore is null");
153 
154     NativeRdb::RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
155     predicates.GreaterThan(ALBUM_ID, currentAlbumId)->OrderByAsc(ALBUM_ID);
156     vector<string> columns = { ALBUM_ID };
157     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->Query(predicates, columns);
158     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Failed to query analysis album");
159 
160     while (resultSet->GoToNextRow() == E_OK) {
161         int32_t albumId = GetAlbumId(resultSet);
162         if (albumId <= 0) {
163             MEDIA_WARN_LOG("Failed to GetAlbumId: %{public}d", albumId);
164             continue;
165         }
166         albumIds.push_back(albumId);
167     }
168     return E_OK;
169 }
170 
GetAlbumIds(AlbumRefreshStatus albumRefreshStatus,int32_t currentAlbumId,vector<int32_t> & albumIds)171 int32_t GetAlbumIds(AlbumRefreshStatus albumRefreshStatus, int32_t currentAlbumId, vector<int32_t>& albumIds)
172 {
173     switch (albumRefreshStatus) {
174         case AlbumRefreshStatus::SYSTEM:
175             // refresh all albums for system album, no need to fill albumIds
176             return E_OK;
177         case AlbumRefreshStatus::USER:
178             return GetPhotoAlbumIds(PhotoAlbumSubType::USER_GENERIC, currentAlbumId, albumIds);
179         case AlbumRefreshStatus::SOURCE:
180             return GetPhotoAlbumIds(PhotoAlbumSubType::SOURCE_GENERIC, currentAlbumId, albumIds);
181         case AlbumRefreshStatus::ANALYSIS:
182             return GetAnalysisAlbumIds(currentAlbumId, albumIds);
183         default:
184             MEDIA_ERR_LOG("Failed to check album refresh status: %{public}d", static_cast<int32_t>(albumRefreshStatus));
185             return E_ERR;
186     }
187 }
188 
RefreshAlbums(AlbumRefreshStatus albumRefreshStatus,const vector<int32_t> & albumIds)189 int32_t MediaLibraryAllAlbumRefreshProcessor::RefreshAlbums(AlbumRefreshStatus albumRefreshStatus,
190     const vector<int32_t>& albumIds)
191 {
192     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
193     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "rdbStore is null");
194     if (albumRefreshStatus == AlbumRefreshStatus::SYSTEM) {
195         MediaLibraryRdbUtils::UpdateSystemAlbumsByUris(rdbStore, AlbumOperationType::DEFAULT);
196         return E_OK;
197     }
198 
199     int32_t currentAlbumId = currentAlbumId_;
200     for (auto iter = albumIds.begin(); iter != albumIds.end(); iter++) {
201         int32_t albumId = *iter;
202         if (albumRefreshStatus == AlbumRefreshStatus::USER) {
203             MediaLibraryRdbUtils::UpdateUserAlbumInternal(rdbStore, { to_string(albumId) }, false, false);
204             MediaLibraryRdbUtils::UpdateUserAlbumHiddenState(rdbStore, { to_string(albumId) });
205         } else if (albumRefreshStatus == AlbumRefreshStatus::SOURCE) {
206             MediaLibraryRdbUtils::UpdateSourceAlbumInternal(rdbStore, { to_string(albumId) }, false, false);
207             MediaLibraryRdbUtils::UpdateSourceAlbumHiddenState(rdbStore, { to_string(albumId) });
208         } else if (albumRefreshStatus == AlbumRefreshStatus::ANALYSIS) {
209             MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore, { to_string(albumId) });
210         } else {
211             MEDIA_WARN_LOG("Ignore to refresh album %{public}d id: %{public}d",
212                 static_cast<int32_t>(albumRefreshStatus), albumId);
213         }
214 
215         currentAlbumId = albumId;
216         if (!currentStatus_ || isCloudSyncing_) {
217             MEDIA_INFO_LOG("Condition changes, currentStatus_: %{public}d, isCloudSyncing_: %{public}d",
218                 currentStatus_, isCloudSyncing_);
219             break;
220         }
221     }
222 
223     if (albumIds.empty() || currentAlbumId == albumIds.back()) {
224         MEDIA_INFO_LOG("Finish refreshing album type: %{public}d", albumRefreshStatus);
225         return E_OK;
226     }
227     MEDIA_INFO_LOG(
228         "Refresh album type: %{public}d, album id: %{public}d, currentStatus_: %{public}d, isCloudSyncing_: %{public}d",
229         albumRefreshStatus, currentAlbumId, currentStatus_, isCloudSyncing_);
230     return currentAlbumId;
231 }
232 
TryRefreshAllAlbums()233 void MediaLibraryAllAlbumRefreshProcessor::TryRefreshAllAlbums()
234 {
235     {
236         std::lock_guard<std::mutex> lock(refreshAllAlbumsLock_);
237         if (!CheckRefreshConditionLocked()) {
238             MEDIA_DEBUG_LOG("Not meet the condition of refreshing albums");
239             return;
240         }
241         MEDIA_INFO_LOG("RefreshAllAlbums! now: %{public}" PRId64 ", last : %{public}" PRId64,
242             GetNowTimeUs(), lastRefreshAllAlbumsTime_);
243         lastRefreshAllAlbumsTime_ = GetNowTimeUs();
244     }
245 
246     if (albumRefreshStatus_ == AlbumRefreshStatus::NOT_START) {
247         albumRefreshStatus_ = GetNextRefreshStatus(AlbumRefreshStatus::NOT_START);
248     }
249 
250     while (albumRefreshStatus_ != AlbumRefreshStatus::NOT_START && currentStatus_ && !isCloudSyncing_) {
251         vector<int32_t> albumIds = {};
252         int32_t ret = GetAlbumIds(albumRefreshStatus_, currentAlbumId_, albumIds);
253         if (ret < E_OK) {
254             albumRefreshStatus_ = GetNextRefreshStatus(albumRefreshStatus_);
255             currentAlbumId_ = 0;
256             continue;
257         }
258 
259         ret = RefreshAlbums(albumRefreshStatus_, albumIds);
260         if (ret > 0) {
261             currentAlbumId_ = ret;
262             break;
263         }
264         albumRefreshStatus_ = GetNextRefreshStatus(albumRefreshStatus_);
265         currentAlbumId_ = 0;
266     }
267 }
268 
PostRefreshAllAlbumsTask()269 void MediaLibraryAllAlbumRefreshProcessor::PostRefreshAllAlbumsTask()
270 {
271     ffrt::submit([this]() { TryRefreshAllAlbums(); });
272 }
273 } // namespace Media
274 } // namespace OHOS
275