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