1 /*
2  * Copyright (c) 2022 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 "cloud_download_callback_client.h"
17 #include "cloud_sync_manager_impl.h"
18 #include "cloud_sync_callback_client.h"
19 #include "cloud_sync_service_proxy.h"
20 #include "dfs_error.h"
21 #include "system_ability_definition.h"
22 #include "iservice_registry.h"
23 #include "utils_log.h"
24 
25 namespace OHOS::FileManagement::CloudSync {
26 using namespace std;
27 constexpr int32_t MIN_USER_ID = 100;
28 constexpr int32_t MAX_FILE_CACHE_NUM = 400;
GetInstance()29 CloudSyncManagerImpl &CloudSyncManagerImpl::GetInstance()
30 {
31     static CloudSyncManagerImpl instance;
32     return instance;
33 }
34 
RegisterCallback(const std::shared_ptr<CloudSyncCallback> callback,const std::string & bundleName)35 int32_t CloudSyncManagerImpl::RegisterCallback(const std::shared_ptr<CloudSyncCallback> callback,
36                                                const std::string &bundleName)
37 {
38     if (!callback) {
39         LOGE("callback is null");
40         return E_INVAL_ARG;
41     }
42     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
43     if (!CloudSyncServiceProxy) {
44         LOGE("proxy is null");
45         return E_SA_LOAD_FAILED;
46     }
47     auto ret = CloudSyncServiceProxy->RegisterCallbackInner(sptr(new (std::nothrow) CloudSyncCallbackClient(callback)),
48                                                             bundleName);
49     {
50         unique_lock<mutex> lock(callbackMutex_);
51         callback_ = callback;
52     }
53     SubscribeListener(bundleName);
54     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
55     LOGI("RegisterCallback ret %{public}d", ret);
56     return ret;
57 }
58 
UnRegisterCallback(const std::string & bundleName)59 int32_t CloudSyncManagerImpl::UnRegisterCallback(const std::string &bundleName)
60 {
61     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
62     if (!CloudSyncServiceProxy) {
63         LOGE("proxy is null");
64         return E_SA_LOAD_FAILED;
65     }
66 
67     auto ret = CloudSyncServiceProxy->UnRegisterCallbackInner(bundleName);
68     if (!ret) {
69         {
70             unique_lock<mutex> lock(callbackMutex_);
71             callback_ = nullptr;
72         }
73         SubscribeListener();
74     }
75     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
76     LOGI("UnRegisterCallback ret %{public}d", ret);
77     return ret;
78 }
79 
StartSync(const std::string & bundleName)80 int32_t CloudSyncManagerImpl::StartSync(const std::string &bundleName)
81 {
82     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
83     if (!CloudSyncServiceProxy) {
84         LOGE("proxy is null");
85         return E_SA_LOAD_FAILED;
86     }
87     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
88     return CloudSyncServiceProxy->StartSyncInner(true, bundleName);
89 }
90 
GetSyncTime(int64_t & syncTime,const std::string & bundleName)91 int32_t CloudSyncManagerImpl::GetSyncTime(int64_t &syncTime, const std::string &bundleName)
92 {
93     LOGI("GetSyncTime Start");
94     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
95     if (!CloudSyncServiceProxy) {
96         LOGE("proxy is null");
97         return E_SA_LOAD_FAILED;
98     }
99     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
100     return CloudSyncServiceProxy->GetSyncTimeInner(syncTime, bundleName);
101 }
102 
StartSync(bool forceFlag,const std::shared_ptr<CloudSyncCallback> callback)103 int32_t CloudSyncManagerImpl::StartSync(bool forceFlag, const std::shared_ptr<CloudSyncCallback> callback)
104 {
105     if (!callback) {
106         LOGE("callback is null");
107         return E_INVAL_ARG;
108     }
109     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
110     if (!CloudSyncServiceProxy) {
111         LOGE("proxy is null");
112         return E_SA_LOAD_FAILED;
113     }
114 
115     if (!isFirstCall_.test()) {
116         LOGI("Register callback");
117         auto ret =
118             CloudSyncServiceProxy->RegisterCallbackInner(sptr(new (std::nothrow) CloudSyncCallbackClient(callback)));
119         if (ret) {
120             LOGE("Register callback failed");
121             isFirstCall_.clear();
122             return ret;
123         }
124         callback_ = callback;
125         SubscribeListener();
126         SetDeathRecipient(CloudSyncServiceProxy->AsObject());
127     }
128 
129     return CloudSyncServiceProxy->StartSyncInner(forceFlag);
130 }
131 
TriggerSync(const std::string & bundleName,const int32_t & userId)132 int32_t CloudSyncManagerImpl::TriggerSync(const std::string &bundleName, const int32_t &userId)
133 {
134     if (bundleName.empty() || userId < MIN_USER_ID) {
135         LOGE("Trigger Sync parameter is invalid");
136         return E_INVAL_ARG;
137     }
138     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
139     if (!CloudSyncServiceProxy) {
140         LOGE("proxy is null");
141         return E_SA_LOAD_FAILED;
142     }
143     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
144     return CloudSyncServiceProxy->TriggerSyncInner(bundleName, userId);
145 }
146 
StopSync(const std::string & bundleName,bool forceFlag)147 int32_t CloudSyncManagerImpl::StopSync(const std::string &bundleName, bool forceFlag)
148 {
149     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
150     if (!CloudSyncServiceProxy) {
151         LOGE("proxy is null");
152         return E_SA_LOAD_FAILED;
153     }
154     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
155     return CloudSyncServiceProxy->StopSyncInner(bundleName, forceFlag);
156 }
157 
ResetCursor(const std::string & bundleName)158 int32_t CloudSyncManagerImpl::ResetCursor(const std::string &bundleName)
159 {
160     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
161     if (!CloudSyncServiceProxy) {
162         LOGE("proxy is null");
163         return E_SA_LOAD_FAILED;
164     }
165     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
166     return CloudSyncServiceProxy->ResetCursor(bundleName);
167 }
168 
ChangeAppSwitch(const std::string & accoutId,const std::string & bundleName,bool status)169 int32_t CloudSyncManagerImpl::ChangeAppSwitch(const std::string &accoutId, const std::string &bundleName, bool status)
170 {
171     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
172     if (!CloudSyncServiceProxy) {
173         LOGE("proxy is null");
174         return E_SA_LOAD_FAILED;
175     }
176 
177     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
178 
179     int32_t ret = CloudSyncServiceProxy->ChangeAppSwitch(accoutId, bundleName, status);
180     LOGI("ChangeAppSwitch ret %{public}d", ret);
181     return ret;
182 }
183 
NotifyDataChange(const std::string & accoutId,const std::string & bundleName)184 int32_t CloudSyncManagerImpl::NotifyDataChange(const std::string &accoutId, const std::string &bundleName)
185 {
186     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
187     if (!CloudSyncServiceProxy) {
188         LOGE("proxy is null");
189         return E_SA_LOAD_FAILED;
190     }
191 
192     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
193 
194     int32_t ret = CloudSyncServiceProxy->NotifyDataChange(accoutId, bundleName);
195     LOGI("NotifyDataChange ret %{public}d", ret);
196     return ret;
197 }
198 
NotifyEventChange(int32_t userId,const std::string & eventId,const std::string & extraData)199 int32_t CloudSyncManagerImpl::NotifyEventChange(
200     int32_t userId, const std::string &eventId, const std::string &extraData)
201 {
202     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
203     if (!CloudSyncServiceProxy) {
204         LOGE("proxy is null");
205         return E_SA_LOAD_FAILED;
206     }
207 
208     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
209 
210     int32_t ret = CloudSyncServiceProxy->NotifyEventChange(userId, eventId, extraData);
211     LOGI("NotifyDataChange ret %{public}d", ret);
212     return ret;
213 }
214 
StartDownloadFile(const std::string & uri)215 int32_t CloudSyncManagerImpl::StartDownloadFile(const std::string &uri)
216 {
217     LOGI("StartDownloadFile start");
218     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
219     if (!CloudSyncServiceProxy) {
220         LOGE("proxy is null");
221         return E_SA_LOAD_FAILED;
222     }
223     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
224     int32_t ret = CloudSyncServiceProxy->StartDownloadFile(uri);
225     LOGI("StartDownloadFile ret %{public}d", ret);
226     return ret;
227 }
228 
StartFileCache(const std::string & uri)229 int32_t CloudSyncManagerImpl::StartFileCache(const std::string &uri)
230 {
231     LOGI("StartFileCache start");
232     int64_t downloadId = 0;
233     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
234     if (!CloudSyncServiceProxy) {
235         LOGE("proxy is null");
236         return E_SA_LOAD_FAILED;
237     }
238     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
239     std::vector<std::string> uriVec;
240     uriVec.push_back(uri);
241     int32_t ret = CloudSyncServiceProxy->StartFileCache(uriVec, downloadId);
242     LOGI("StartFileCache ret %{public}d", ret);
243     return ret;
244 }
245 
StartFileCache(const std::vector<std::string> & uriVec,int64_t & downloadId,std::bitset<FIELD_KEY_MAX_SIZE> fieldkey,const std::shared_ptr<CloudDownloadCallback> downloadCallback)246 int32_t CloudSyncManagerImpl::StartFileCache(const std::vector<std::string> &uriVec,
247                                              int64_t &downloadId, std::bitset<FIELD_KEY_MAX_SIZE> fieldkey,
248                                              const std::shared_ptr<CloudDownloadCallback> downloadCallback)
249 {
250     LOGI("StartFileCache batch start, uriVec size: %{public}zu, fieldKey: %{public}llu, Callback is null: %{public}d",
251          uriVec.size(), static_cast<unsigned long long>(fieldkey.to_ulong()), (downloadCallback == nullptr));
252     if (uriVec.empty()) {
253         LOGE("StartFileCache, uri list is empty");
254         return E_INVAL_ARG;
255     }
256     if (uriVec.size() > MAX_FILE_CACHE_NUM) {
257         LOGE("StartFileCache, the size of uri list exceeded the maximum limit, size: %{public}zu", uriVec.size());
258         return E_EXCEED_MAX_SIZE;
259     }
260     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
261     if (!CloudSyncServiceProxy) {
262         LOGE("proxy is null");
263         return E_SA_LOAD_FAILED;
264     }
265     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
266 
267     bool isCallbackValid = false;
268     sptr<CloudDownloadCallbackClient> dlCallback = nullptr;
269     if (downloadCallback != nullptr) {
270         dlCallback = sptr(new (std::nothrow) CloudDownloadCallbackClient(downloadCallback));
271         isCallbackValid = true;
272         if (dlCallback == nullptr) {
273             LOGE("register download callback failed");
274             isCallbackValid = false;
275         }
276     }
277 
278     int32_t ret = CloudSyncServiceProxy->StartFileCache(uriVec, downloadId, fieldkey, isCallbackValid, dlCallback);
279     LOGI("StartFileCache batch ret %{public}d", ret);
280     return ret;
281 }
282 
StopDownloadFile(const std::string & uri,bool needClean)283 int32_t CloudSyncManagerImpl::StopDownloadFile(const std::string &uri,  bool needClean)
284 {
285     LOGI("StopDownloadFile start");
286     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
287     if (!CloudSyncServiceProxy) {
288         LOGE("proxy is null");
289         return E_SA_LOAD_FAILED;
290     }
291     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
292     int32_t ret = CloudSyncServiceProxy->StopDownloadFile(uri, needClean);
293     LOGI("StopDownloadFile ret %{public}d", ret);
294     return ret;
295 }
296 
StopFileCache(const int64_t & downloadId,bool needClean)297 int32_t CloudSyncManagerImpl::StopFileCache(const int64_t &downloadId,  bool needClean)
298 {
299     LOGI("StopFileCache start");
300     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
301     if (!CloudSyncServiceProxy) {
302         LOGE("proxy is null");
303         return E_SA_LOAD_FAILED;
304     }
305     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
306     int32_t ret = CloudSyncServiceProxy->StopFileCache(downloadId, needClean);
307     LOGI("StopFileCache ret %{public}d", ret);
308     return ret;
309 }
310 
RegisterDownloadFileCallback(const std::shared_ptr<CloudDownloadCallback> downloadCallback)311 int32_t CloudSyncManagerImpl::RegisterDownloadFileCallback(
312     const std::shared_ptr<CloudDownloadCallback> downloadCallback)
313 {
314     LOGI("RegisterDownloadFileCallback start");
315     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
316     if (!CloudSyncServiceProxy) {
317         LOGE("proxy is null");
318         return E_SA_LOAD_FAILED;
319     }
320     {
321         unique_lock<mutex> lock(downloadMutex_);
322         auto dlCallback = sptr(new (std::nothrow) CloudDownloadCallbackClient(downloadCallback));
323         if (dlCallback == nullptr ||
324             CloudSyncServiceProxy->RegisterDownloadFileCallback(dlCallback) != E_OK) {
325             LOGE("register download callback failed");
326         } else  {
327             downloadCallback_ = downloadCallback;
328         }
329     }
330     SubscribeListener();
331     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
332     return E_OK;
333 }
334 
UnregisterDownloadFileCallback()335 int32_t CloudSyncManagerImpl::UnregisterDownloadFileCallback()
336 {
337     LOGI("UnregisterDownloadFileCallback start");
338     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
339     if (!CloudSyncServiceProxy) {
340         LOGE("proxy is null");
341         return E_SA_LOAD_FAILED;
342     }
343     int32_t ret = E_OK;
344     {
345         unique_lock<mutex> lock(downloadMutex_);
346         ret = CloudSyncServiceProxy->UnregisterDownloadFileCallback();
347         LOGI("UnregisterDownloadFileCallback ret %{public}d", ret);
348         if (ret == E_OK) {
349             downloadCallback_ = nullptr;
350         }
351     }
352     SubscribeListener();
353     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
354     return ret;
355 }
SetDeathRecipient(const sptr<IRemoteObject> & remoteObject)356 void CloudSyncManagerImpl::SetDeathRecipient(const sptr<IRemoteObject> &remoteObject)
357 {
358     if (!isFirstCall_.test_and_set()) {
359         auto deathCallback = [this](const wptr<IRemoteObject> &obj) {
360             LOGE("service died.");
361             CloudSyncServiceProxy::InvaildInstance();
362             if (callback_) {
363                 callback_->OnSyncStateChanged(CloudSyncState::COMPLETED, ErrorType::NO_ERROR);
364             }
365             isFirstCall_.clear();
366         };
367         deathRecipient_ = sptr(new SvcDeathRecipient(deathCallback));
368         if (!remoteObject->AddDeathRecipient(deathRecipient_)) {
369             LOGE("add death recipient failed");
370             isFirstCall_.clear();
371         }
372     }
373 }
374 
EnableCloud(const std::string & accoutId,const SwitchDataObj & switchData)375 int32_t CloudSyncManagerImpl::EnableCloud(const std::string &accoutId,
376                                           const SwitchDataObj &switchData)
377 {
378     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
379     if (!CloudSyncServiceProxy) {
380         LOGE("proxy is null");
381         return E_SA_LOAD_FAILED;
382     }
383 
384     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
385 
386     return CloudSyncServiceProxy->EnableCloud(accoutId, switchData);
387 }
388 
DisableCloud(const std::string & accoutId)389 int32_t CloudSyncManagerImpl::DisableCloud(const std::string &accoutId)
390 {
391     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
392     if (!CloudSyncServiceProxy) {
393         LOGE("proxy is null");
394         return E_SA_LOAD_FAILED;
395     }
396 
397     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
398     return CloudSyncServiceProxy->DisableCloud(accoutId);
399 }
400 
Clean(const std::string & accountId,const CleanOptions & cleanOptions)401 int32_t CloudSyncManagerImpl::Clean(const std::string &accountId, const CleanOptions &cleanOptions)
402 {
403     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
404     if (!CloudSyncServiceProxy) {
405         LOGE("proxy is null");
406         return E_SA_LOAD_FAILED;
407     }
408 
409     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
410 
411     return CloudSyncServiceProxy->Clean(accountId, cleanOptions);
412 }
413 
CleanCache(const std::string & uri)414 int32_t CloudSyncManagerImpl::CleanCache(const std::string &uri)
415 {
416     LOGI("CleanCache Start");
417     auto CloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
418     if (!CloudSyncServiceProxy) {
419         LOGE("proxy is null");
420         return E_SA_LOAD_FAILED;
421     }
422     SetDeathRecipient(CloudSyncServiceProxy->AsObject());
423     return CloudSyncServiceProxy->CleanCacheInner(uri);
424 }
425 
SubscribeListener(std::string bundleName)426 void CloudSyncManagerImpl::SubscribeListener(std::string bundleName)
427 {
428     unique_lock<mutex> lock(subscribeMutex_);
429     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
430     if (samgr == nullptr) {
431         LOGE("Samgr is nullptr");
432         return;
433     }
434     if (listener_ != nullptr) {
435         auto ret = samgr->UnSubscribeSystemAbility(FILEMANAGEMENT_CLOUD_SYNC_SERVICE_SA_ID, listener_);
436         LOGI("unsubscribed to systemAbility ret %{public}d", ret);
437     }
438     if (callback_ != nullptr || downloadCallback_ != nullptr) {
439         listener_ = new SystemAbilityStatusChange(bundleName);
440         auto ret = samgr->SubscribeSystemAbility(FILEMANAGEMENT_CLOUD_SYNC_SERVICE_SA_ID, listener_);
441         LOGI("subscribed to systemAbility ret %{public}d", ret);
442     } else {
443         listener_ = nullptr;
444     }
445 }
446 
ResetProxyCallback(uint32_t retryCount,const string & bundleName)447 bool CloudSyncManagerImpl::ResetProxyCallback(uint32_t retryCount, const string &bundleName)
448 {
449     auto cloudSyncServiceProxy = CloudSyncServiceProxy::GetInstance();
450     if (cloudSyncServiceProxy == nullptr) {
451         LOGE("proxy is null");
452         return false;
453     }
454     bool hasCallback = false;
455     {
456         unique_lock<mutex> downloadLock(downloadMutex_);
457         if (downloadCallback_ != nullptr) {
458             auto dlCallback = sptr(new (std::nothrow) CloudDownloadCallbackClient(downloadCallback_));
459             if (dlCallback == nullptr ||
460                 cloudSyncServiceProxy->RegisterDownloadFileCallback(dlCallback) != E_OK) {
461                 LOGW("register download callback failed, try time is %{public}d", retryCount);
462             } else {
463                 hasCallback = true;
464             }
465         }
466     }
467     if (callback_ != nullptr) {
468         auto callback = sptr(new (std::nothrow) CloudSyncCallbackClient(callback_));
469         if (callback == nullptr ||
470             cloudSyncServiceProxy->RegisterCallbackInner(callback, bundleName) != E_OK) {
471             LOGW("register callback failed, try time is %{public}d", retryCount);
472         } else {
473             hasCallback = true;
474         }
475     }
476     if (hasCallback) {
477         CloudSyncManagerImpl::GetInstance().SetDeathRecipient(cloudSyncServiceProxy->AsObject());
478     }
479     return true;
480 }
481 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)482 void CloudSyncManagerImpl::SystemAbilityStatusChange::OnAddSystemAbility(int32_t systemAbilityId,
483     const std::string &deviceId)
484 {
485     const uint32_t RETRY_TIMES = 3;
486     const uint32_t SLEEP_TIME = 20 * 1000;
487     uint32_t retryCount = 0;
488     LOGI("saId %{public}d loaded", systemAbilityId);
489     do {
490         usleep(SLEEP_TIME);
491         if (!CloudSyncManagerImpl::GetInstance().ResetProxyCallback(retryCount, bundleName_)) {
492             continue;
493         }
494         return;
495     } while (++retryCount < RETRY_TIMES);
496     LOGE("register callback failed, try too many times");
497 }
498 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)499 void CloudSyncManagerImpl::SystemAbilityStatusChange::OnRemoveSystemAbility(int32_t systemAbilityId,
500     const std::string &deviceId)
501 {
502     return;
503 }
504 } // namespace OHOS::FileManagement::CloudSync
505