• 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 #include <chrono>
17 #include <vector>
18 #include <string>
19 #include <thread>
20 
21 #include "cloud_sync_observer.h"
22 
23 #include "cloud_media_asset_manager.h"
24 #include "cloud_sync_notify_handler.h"
25 #include "media_analysis_helper.h"
26 #include "media_file_utils.h"
27 #include "medialibrary_unistore_manager.h"
28 #include "media_column.h"
29 #include "media_log.h"
30 #include "result_set_utils.h"
31 #include "albums_refresh_manager.h"
32 #include "photo_album_column.h"
33 #include "albums_refresh_notify.h"
34 #include "notify_responsibility_chain_factory.h"
35 #include "post_event_utils.h"
36 
37 using namespace std;
38 
39 namespace OHOS {
40 namespace Media {
41 constexpr int32_t SYNC_INTERVAL = 10000;
HandleCloudNotify(AsyncTaskData * data)42 static void HandleCloudNotify(AsyncTaskData *data)
43 {
44     auto* taskData = static_cast<CloudSyncNotifyData*>(data);
45     shared_ptr<CloudSyncNotifyHandler> notifyHandler = make_shared<CloudSyncNotifyHandler>(taskData->notifyInfo_);
46     notifyHandler->MakeResponsibilityChain();
47 }
48 
DealCloudSync(const ChangeInfo & changeInfo)49 void CloudSyncObserver::DealCloudSync(const ChangeInfo &changeInfo)
50 {
51     SyncNotifyInfo info;
52     info.uris = changeInfo.uris_;
53     std::string dataString = (const char *)changeInfo.data_;
54     if (!nlohmann::json::accept(dataString)) {
55         MEDIA_WARN_LOG("Failed to verify the meataData format, metaData is: %{public}s", dataString.c_str());
56         return;
57     }
58     nlohmann::json jsonData = nlohmann::json::parse(dataString);
59     if (jsonData.contains("taskType")) {
60         info.taskType = jsonData["taskType"];
61     }
62     if (jsonData.contains("syncId")) {
63         info.syncId = jsonData["syncId"];
64     }
65     if (jsonData.contains("syncType")) {
66         info.syncType = jsonData["syncType"];
67     }
68     if (jsonData.contains("totalAssets")) {
69         info.totalAssets = jsonData["totalAssets"];
70     }
71     if (jsonData.contains("totalAlbums")) {
72         info.totalAlbums = jsonData["totalAlbums"];
73     }
74     if (info.taskType == TIME_BEGIN_SYNC) {
75         PostEventUtils::GetInstance().CreateCloudDownloadSyncStat(info.syncId);
76         VariantMap map = {
77             {KEY_START_DOWNLOAD_TIME, MediaFileUtils::UTCTimeMilliSeconds()}, {KEY_DOWNLOAD_TYPE, info.syncType}};
78         PostEventUtils::GetInstance().UpdateCloudDownloadSyncStat(map);
79         AlbumsRefreshManager::GetInstance().AddAlbumRefreshTask(info);
80     } else if (info.taskType == TIME_END_SYNC) {
81         AlbumsRefreshManager::GetInstance().AddAlbumRefreshTask(info);
82     }
83 }
84 
DealAlbumGallery(CloudSyncNotifyInfo & notifyInfo)85 void CloudSyncObserver::DealAlbumGallery(CloudSyncNotifyInfo &notifyInfo)
86 {
87     SyncNotifyInfo info = AlbumsRefreshManager::GetInstance().GetSyncNotifyInfo(notifyInfo, ALBUM_URI_TYPE);
88     AlbumsRefreshManager::GetInstance().AddAlbumRefreshTask(info);
89     VariantMap map;
90     if (info.notifyType == NOTIFY_ADD) {
91         map = {{KEY_TOTAL_ALBUM_NUM, info.urisSize}, {KEY_ADD_ALBUM_NUM, info.urisSize}};
92     } else if (info.notifyType == NOTIFY_UPDATE) {
93         map = {{KEY_TOTAL_ALBUM_NUM, info.urisSize}, {KEY_UPDATE_ALBUM_NUM, info.urisSize}};
94     } else if (info.notifyType == NOTIFY_REMOVE) {
95         map = {{KEY_TOTAL_ALBUM_NUM, info.urisSize}, {KEY_DELETE_ALBUM_NUM, info.urisSize}};
96     }
97     PostEventUtils::GetInstance().UpdateCloudDownloadSyncStat(map);
98 }
99 
DealPhotoGallery(CloudSyncNotifyInfo & notifyInfo)100 void CloudSyncObserver::DealPhotoGallery(CloudSyncNotifyInfo &notifyInfo)
101 {
102     if (notifyInfo.type == ChangeType::UPDATE || notifyInfo.type == ChangeType::OTHER) {
103         CloudSyncHandleData handleData;
104         handleData.orgInfo = notifyInfo;
105         shared_ptr<BaseHandler> chain = NotifyResponsibilityChainFactory::CreateChain(GALLERY_PHOTO_DELETE);
106         if (chain != nullptr) {
107             chain->Handle(handleData);
108         } else {
109             MEDIA_ERR_LOG("uri OR type is Invalid");
110         }
111     }
112     SyncNotifyInfo info = AlbumsRefreshManager::GetInstance().GetSyncNotifyInfo(notifyInfo, PHOTO_URI_TYPE);
113     AlbumsRefreshManager::GetInstance().AddAlbumRefreshTask(info);
114     VariantMap map;
115     if (info.notifyType == NOTIFY_ADD) {
116         map = {{KEY_TOTAL_ASSET_NUM, info.urisSize}, {KEY_ADD_ASSET_NUM, info.urisSize}};
117     } else if (info.notifyType == NOTIFY_UPDATE) {
118         map = {{KEY_TOTAL_ASSET_NUM, info.urisSize}, {KEY_UPDATE_ASSET_NUM, info.urisSize}};
119     } else if (info.notifyType == NOTIFY_REMOVE) {
120         map = {{KEY_TOTAL_ASSET_NUM, info.urisSize}, {KEY_DELETE_ASSET_NUM, info.urisSize}};
121     }
122     PostEventUtils::GetInstance().UpdateCloudDownloadSyncStat(map);
123     if (notifyInfo.type == ChangeType::DELETE) {
124         CloudMediaAssetManager::GetInstance().SetIsThumbnailUpdate();
125     }
126 }
127 
DealGalleryDownload(CloudSyncNotifyInfo & notifyInfo)128 void CloudSyncObserver::DealGalleryDownload(CloudSyncNotifyInfo &notifyInfo)
129 {
130     if (notifyInfo.type == ChangeType::OTHER) {
131         if (notifyInfo.uris.empty()) {
132             MEDIA_ERR_LOG("gallery download notify uri empty");
133             return;
134         }
135         string uriString = notifyInfo.uris.front().ToString();
136         string downloadString = "gallery/download";
137         string::size_type pos = uriString.find(downloadString);
138         if (pos == string::npos) {
139             MEDIA_ERR_LOG("gallery download notify uri err");
140             return;
141         }
142         auto it = notifyInfo.uris.begin();
143         *it = Uri(uriString.replace(pos, downloadString.length(), "Photo"));
144         notifyInfo.type = ChangeType::UPDATE;
145         CloudSyncHandleData handleData;
146         handleData.orgInfo = notifyInfo;
147         shared_ptr<BaseHandler> chain = NotifyResponsibilityChainFactory::CreateChain(TRANSPARENT);
148         if (chain != nullptr) {
149             chain->Handle(handleData);
150         }
151     }
152 }
153 
OnChange(const ChangeInfo & changeInfo)154 void CloudSyncObserver::OnChange(const ChangeInfo &changeInfo)
155 {
156     CloudSyncNotifyInfo notifyInfo = {changeInfo.uris_, changeInfo.changeType_, changeInfo.data_};
157     string uriString = notifyInfo.uris.front().ToString();
158     MEDIA_DEBUG_LOG("#uriString: %{public}s, #uriSize: %{public}zu changeType: %{public}d",
159         uriString.c_str(), changeInfo.uris_.size(), changeInfo.changeType_);
160 
161     if (uriString.find(PhotoAlbumColumns::PHOTO_GALLERY_CLOUD_SYNC_INFO_URI_PREFIX) != string::npos) {
162         DealCloudSync(changeInfo);
163         return;
164     }
165 
166     if (uriString.find(PhotoColumn::PHOTO_CLOUD_URI_PREFIX) != string::npos && notifyInfo.type == ChangeType::OTHER) {
167         lock_guard<mutex> lock(syncMutex_);
168         if (!isPending_) {
169             MEDIA_INFO_LOG("set timer handle index");
170             std::thread([this]() { this->HandleIndex(); }).detach();
171             isPending_ = true;
172         }
173     }
174 
175     if (uriString.find(PhotoAlbumColumns::ALBUM_GALLERY_CLOUD_URI_PREFIX) != string::npos) {
176         DealAlbumGallery(notifyInfo);
177         return;
178     }
179 
180     if (uriString.find(PhotoColumn::PHOTO_GALLERY_CLOUD_URI_PREFIX) != string::npos) {
181         DealPhotoGallery(notifyInfo);
182         return;
183     }
184 
185     if (uriString.find(PhotoAlbumColumns::PHOTO_GALLERY_DOWNLOAD_URI_PREFIX) != string::npos) {
186         DealGalleryDownload(notifyInfo);
187         return;
188     }
189 
190     auto *taskData = new (nothrow) CloudSyncNotifyData(notifyInfo);
191     CHECK_AND_RETURN_LOG(taskData != nullptr, "Failed to new taskData");
192     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
193     if (asyncWorker == nullptr) {
194         MEDIA_ERR_LOG("Can not get asyncWorker");
195         delete taskData;
196         return;
197     }
198     shared_ptr<MediaLibraryAsyncTask> notifyHandleAsyncTask = make_shared<MediaLibraryAsyncTask>(
199         HandleCloudNotify, taskData);
200     if (notifyHandleAsyncTask != nullptr) {
201         asyncWorker->AddTask(notifyHandleAsyncTask, true);
202     }
203 }
204 
HandleIndex()205 void CloudSyncObserver::HandleIndex()
206 {
207     std::this_thread::sleep_for(std::chrono::milliseconds(SYNC_INTERVAL));
208     lock_guard<mutex> lock(syncMutex_);
209     std::vector<std::string> idToDeleteIndex;
210     MediaAnalysisHelper::AsyncStartMediaAnalysisService(
211         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_DELETE_INDEX), idToDeleteIndex);
212 
213     //update index
214     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
215     CHECK_AND_RETURN_LOG(uniStore != nullptr, "uniStore is nullptr!");
216     const std::string queryIdToUpdateIndex = "SELECT file_id FROM tab_analysis_search_index WHERE photo_status = 2";
217     auto resultSetUpdateIndex = uniStore->QuerySql(queryIdToUpdateIndex);
218     CHECK_AND_RETURN_LOG(resultSetUpdateIndex != nullptr, "resultSetUpdateIndex is nullptr!");
219     std::vector<std::string> idToUpdateIndex;
220     while (resultSetUpdateIndex->GoToNextRow() == NativeRdb::E_OK) {
221         idToUpdateIndex.push_back(to_string(GetInt32Val("file_id", resultSetUpdateIndex)));
222     }
223 
224     MEDIA_INFO_LOG("HandleIndex idToUpdateIndex size: %{public}zu", idToUpdateIndex.size());
225     if (!idToUpdateIndex.empty()) {
226         MediaAnalysisHelper::AsyncStartMediaAnalysisService(
227             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), idToUpdateIndex);
228     }
229     isPending_ = false;
230 }
231 } // namespace Media
232 } // namespace OHOS
233