• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 LOG_TAG "CloudServiceImpl"
17 
18 #include "cloud_service_impl.h"
19 #include "accesstoken_kit.h"
20 #include "account/account_delegate.h"
21 #include "checker/checker_manager.h"
22 #include "cloud/cloud_server.h"
23 #include "communicator/device_manager_adapter.h"
24 #include "device_manager_adapter.h"
25 #include "eventcenter/event_center.h"
26 #include "ipc_skeleton.h"
27 #include "log_print.h"
28 #include "metadata/meta_data_manager.h"
29 #include "rdb_cloud_data_translate.h"
30 #include "runtime_config.h"
31 #include "store/auto_cache.h"
32 #include "store/general_store.h"
33 #include "utils/anonymous.h"
34 #include "sync_manager.h"
35 namespace OHOS::CloudData {
36 using namespace DistributedData;
37 using namespace std::chrono;
38 using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter;
39 using Account = OHOS::DistributedKv::AccountDelegate;
40 using AccessTokenKit = Security::AccessToken::AccessTokenKit;
41 __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_;
42 
Factory()43 CloudServiceImpl::Factory::Factory() noexcept
44 {
45     FeatureSystem::GetInstance().RegisterCreator(
46         CloudServiceImpl::SERVICE_NAME,
47         [this]() {
48             if (product_ == nullptr) {
49                 product_ = std::make_shared<CloudServiceImpl>();
50             }
51             return product_;
52         },
53         FeatureSystem::BIND_NOW);
54 }
55 
~Factory()56 CloudServiceImpl::Factory::~Factory() {}
57 
CloudServiceImpl()58 CloudServiceImpl::CloudServiceImpl()
59 {
60     EventCenter::GetInstance().Subscribe(CloudEvent::GET_SCHEMA, [this](const Event &event) {
61         GetSchema(event);
62     });
63 }
64 
EnableCloud(const std::string & id,const std::map<std::string,int32_t> & switches)65 int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map<std::string, int32_t> &switches)
66 {
67     CloudInfo cloudInfo;
68     auto status = GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo);
69     if (status != SUCCESS) {
70         return status;
71     }
72     cloudInfo.enableCloud = true;
73     for (const auto &[bundle, value] : switches) {
74         if (!cloudInfo.Exist(bundle)) {
75             continue;
76         }
77         cloudInfo.apps[bundle].cloudSwitch = (value == SWITCH_ON);
78     }
79     if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) {
80         return ERROR;
81     }
82     Execute(GenTask(0, cloudInfo.user));
83     syncManager_.DoCloudSync({ cloudInfo.user });
84     return SUCCESS;
85 }
86 
DisableCloud(const std::string & id)87 int32_t CloudServiceImpl::DisableCloud(const std::string &id)
88 {
89     CloudInfo cloudInfo;
90     auto status = GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo);
91     if (status != SUCCESS) {
92         return status;
93     }
94     cloudInfo.enableCloud = false;
95     if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) {
96         return ERROR;
97     }
98     Execute(GenTask(0, cloudInfo.user));
99     syncManager_.StopCloudSync(cloudInfo.user);
100     return SUCCESS;
101 }
102 
ChangeAppSwitch(const std::string & id,const std::string & bundleName,int32_t appSwitch)103 int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch)
104 {
105     CloudInfo cloudInfo;
106     auto status = GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo);
107     if (status != SUCCESS) {
108         return status;
109     }
110     if (!cloudInfo.Exist(bundleName)) {
111         ZLOGE("bundleName:%{public}s", bundleName.c_str());
112         return INVALID_ARGUMENT;
113     }
114     cloudInfo.apps[bundleName].cloudSwitch = (appSwitch == SWITCH_ON);
115     if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) {
116         return ERROR;
117     }
118     Execute(GenTask(0, cloudInfo.user, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB }));
119     if (cloudInfo.enableCloud && appSwitch == SWITCH_ON) {
120         syncManager_.DoCloudSync({ cloudInfo.user, bundleName });
121     }
122     return SUCCESS;
123 }
124 
DoClean(CloudInfo & cloudInfo,const std::map<std::string,int32_t> & actions)125 int32_t CloudServiceImpl::DoClean(CloudInfo &cloudInfo, const std::map<std::string, int32_t> &actions)
126 {
127     syncManager_.StopCloudSync(cloudInfo.user);
128     auto keys = cloudInfo.GetSchemaKey();
129     for (const auto &[bundle, action] : actions) {
130         if (!cloudInfo.Exist(bundle)) {
131             continue;
132         }
133         SchemaMeta schemaMeta;
134         if (!MetaDataManager::GetInstance().LoadMeta(keys[bundle], schemaMeta, true)) {
135             ZLOGE("failed, no schema meta:bundleName:%{public}s", bundle.c_str());
136             return ERROR;
137         }
138         for (const auto &database : schemaMeta.databases) {
139             // action
140             StoreMetaData meta;
141             meta.bundleName = schemaMeta.bundleName;
142             meta.storeId = database.name;
143             meta.user = std::to_string(cloudInfo.user);
144             meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
145             meta.instanceId = cloudInfo.apps[bundle].instanceId;
146             if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) {
147                 ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
148                     meta.GetStoreAlias().c_str());
149                 continue;
150             }
151             AutoCache::Store store = SyncManager::GetStore(meta, cloudInfo.user, false);
152             if (store == nullptr) {
153                 ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str());
154                 return ERROR;
155             }
156             auto status = store->Clean({}, action, "");
157             if (status != E_OK) {
158                 ZLOGW("remove device data status:%{public}d, user:%{pubilc}d, bundleName:%{public}s, "
159                       "storeId:%{public}s",
160                     status, static_cast<int>(cloudInfo.user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str());
161                 continue;
162             }
163         }
164     }
165     return SUCCESS;
166 }
167 
Clean(const std::string & id,const std::map<std::string,int32_t> & actions)168 int32_t CloudServiceImpl::Clean(const std::string &id, const std::map<std::string, int32_t> &actions)
169 {
170     CloudInfo cloudInfo;
171     auto tokenId = IPCSkeleton::GetCallingTokenID();
172     cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId);
173     if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) {
174         ZLOGE("get cloud meta failed user:%{public}d", static_cast<int>(cloudInfo.user));
175         return ERROR;
176     }
177     if (id != cloudInfo.id) {
178         ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(),
179             Anonymous::Change(id).c_str());
180     }
181     return DoClean(cloudInfo, actions);
182 }
183 
NotifyDataChange(const std::string & id,const std::string & bundleName)184 int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::string &bundleName)
185 {
186     CloudInfo cloudInfo;
187     auto tokenId = IPCSkeleton::GetCallingTokenID();
188     cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId);
189     if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) {
190         return ERROR;
191     }
192     if (cloudInfo.id != id) {
193         ZLOGE("invalid args, [input] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(id).c_str(),
194             Anonymous::Change(cloudInfo.id).c_str());
195         return INVALID_ARGUMENT;
196     }
197     if (!cloudInfo.enableCloud) {
198         return CLOUD_DISABLE;
199     }
200     if (!cloudInfo.Exist(bundleName)) {
201         ZLOGE("bundleName:%{public}s", bundleName.c_str());
202         return INVALID_ARGUMENT;
203     }
204     if (!cloudInfo.apps[bundleName].cloudSwitch) {
205         return CLOUD_DISABLE_SWITCH;
206     }
207     syncManager_.DoCloudSync(SyncManager::SyncInfo(cloudInfo.user, bundleName));
208     return SUCCESS;
209 }
210 
OnInitialize()211 int32_t CloudServiceImpl::OnInitialize()
212 {
213     DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared<DistributedRdb::RdbCloudDataTranslate>());
214     Execute(GenTask(0, 0, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB }));
215     return E_OK;
216 }
217 
OnBind(const BindInfo & info)218 int32_t CloudServiceImpl::OnBind(const BindInfo &info)
219 {
220     if (executor_ != nullptr || info.executors == nullptr) {
221         return E_INVALID_ARGS;
222     }
223 
224     executor_ = std::move(info.executors);
225     syncManager_.Bind(executor_);
226     return E_OK;
227 }
228 
OnUserChange(uint32_t code,const std::string & user,const std::string & account)229 int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account)
230 {
231     int32_t userId = atoi(user.c_str());
232     if (code == static_cast<uint32_t>(DistributedKv::AccountStatus::DEVICE_ACCOUNT_SWITCHED)) {
233         Execute(GenTask(0, userId, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB }));
234     }
235     syncManager_.StopCloudSync(userId);
236     return E_OK;
237 }
238 
Online(const std::string & device)239 int32_t CloudServiceImpl::Online(const std::string &device)
240 {
241     if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) {
242         ZLOGI("Not network online");
243         return SUCCESS;
244     }
245     std::vector<int32_t> users;
246     Account::GetInstance()->QueryUsers(users);
247     if (users.empty()) {
248         return SUCCESS;
249     }
250     auto it = users.begin();
251     syncManager_.DoCloudSync({ *it });
252     Execute(GenTask(0, *it, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB }));
253     return SUCCESS;
254 }
255 
Offline(const std::string & device)256 int32_t CloudServiceImpl::Offline(const std::string &device)
257 {
258     if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) {
259         ZLOGI("Not network offline");
260         return SUCCESS;
261     }
262     std::vector<int32_t> users;
263     Account::GetInstance()->QueryUsers(users);
264     if (users.empty()) {
265         return SUCCESS;
266     }
267     auto it = users.begin();
268     syncManager_.StopCloudSync(*it);
269     return SUCCESS;
270 }
271 
GetCloudInfo(uint32_t tokenId,const std::string & id,CloudInfo & cloudInfo)272 int32_t CloudServiceImpl::GetCloudInfo(uint32_t tokenId, const std::string &id, CloudInfo &cloudInfo)
273 {
274     cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId);
275     if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) {
276         auto status = GetCloudInfoFromServer(cloudInfo);
277         if (status != SUCCESS) {
278             ZLOGE("user:%{public}d", cloudInfo.user);
279             return status;
280         }
281     }
282     if (cloudInfo.id != id) {
283         ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s", Anonymous::Change(id).c_str(),
284             Anonymous::Change(cloudInfo.id).c_str());
285         return INVALID_ARGUMENT;
286     }
287     return SUCCESS;
288 }
289 
GetCloudInfoFromMeta(CloudInfo & cloudInfo)290 int32_t CloudServiceImpl::GetCloudInfoFromMeta(CloudInfo &cloudInfo)
291 {
292     if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) {
293         ZLOGE("no exist meta, user:%{public}d", cloudInfo.user);
294         return ERROR;
295     }
296     return SUCCESS;
297 }
298 
GetCloudInfoFromServer(CloudInfo & cloudInfo)299 int32_t CloudServiceImpl::GetCloudInfoFromServer(CloudInfo &cloudInfo)
300 {
301     auto instance = CloudServer::GetInstance();
302     if (instance == nullptr) {
303         return NOT_SUPPORT;
304     }
305     cloudInfo = instance->GetServerInfo(cloudInfo.user);
306     if (!cloudInfo.IsValid()) {
307         ZLOGE("cloud is empty, user%{public}d", cloudInfo.user);
308         return ERROR;
309     }
310     return SUCCESS;
311 }
312 
UpdateCloudInfo(int32_t user)313 bool CloudServiceImpl::UpdateCloudInfo(int32_t user)
314 {
315     CloudInfo cloudInfo;
316     cloudInfo.user = user;
317     if (GetCloudInfoFromServer(cloudInfo) != SUCCESS) {
318         ZLOGE("failed, user:%{public}d", user);
319         return false;
320     }
321     CloudInfo oldInfo;
322     if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), oldInfo, true)) {
323         MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
324         return true;
325     }
326     if (oldInfo.id != cloudInfo.id) {
327         ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(),
328             Anonymous::Change(oldInfo.id).c_str());
329         std::map<std::string, int32_t> actions;
330         for (auto &[bundle, app] : cloudInfo.apps) {
331             actions[bundle] = GeneralStore::CleanMode::CLOUD_INFO;
332         }
333         DoClean(oldInfo, actions);
334     }
335     if (cloudInfo.enableCloud) {
336         for (auto &[bundle, app] : cloudInfo.apps) {
337             if (app.cloudSwitch && !oldInfo.apps[bundle].cloudSwitch) {
338                 syncManager_.DoCloudSync({ cloudInfo.user, bundle });
339             }
340         }
341     }
342     MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
343     return true;
344 }
345 
UpdateSchema(int32_t user)346 bool CloudServiceImpl::UpdateSchema(int32_t user)
347 {
348     CloudInfo cloudInfo;
349     cloudInfo.user = user;
350     if (GetCloudInfoFromServer(cloudInfo) != SUCCESS) {
351         ZLOGE("failed, user:%{public}d", user);
352         return false;
353     }
354     auto keys = cloudInfo.GetSchemaKey();
355     for (const auto &[bundle, key] : keys) {
356         SchemaMeta schemaMeta;
357         if (MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true)) {
358             continue;
359         }
360         if (GetAppSchema(cloudInfo.user, bundle, schemaMeta) != SUCCESS) {
361             return false;
362         }
363         MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true);
364     }
365     return true;
366 }
367 
GetAppSchema(int32_t user,const std::string & bundleName,SchemaMeta & schemaMeta)368 int32_t CloudServiceImpl::GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta)
369 {
370     auto instance = CloudServer::GetInstance();
371     if (instance == nullptr) {
372         return SERVER_UNAVAILABLE;
373     }
374     schemaMeta = instance->GetAppSchema(user, bundleName);
375     return SUCCESS;
376 }
377 
GenTask(int32_t retry,int32_t user,Handles handles)378 ExecutorPool::Task CloudServiceImpl::GenTask(int32_t retry, int32_t user, Handles handles)
379 {
380     return [this, retry, user, works = std::move(handles)]() mutable {
381         auto executor = executor_;
382         if (retry >= RETRY_TIMES || executor == nullptr || works.empty()) {
383             return;
384         }
385         if (!DmAdapter::GetInstance().IsNetworkAvailable()) {
386             return;
387         }
388         bool finished = true;
389         std::vector<int32_t> users;
390         if (user == 0) {
391             auto account = Account::GetInstance();
392             finished = !(account == nullptr) && account->QueryUsers(users);
393         } else {
394             users.push_back(user);
395         }
396 
397         auto handle = works.front();
398         for (auto user : users) {
399             finished = (this->*handle)(user) && finished;
400         }
401         if (!finished || users.empty()) {
402             executor->Schedule(std::chrono::seconds(RETRY_INTERVAL), GenTask(retry + 1, user, std::move(works)));
403             return;
404         }
405         works.pop_front();
406         if (!works.empty()) {
407             executor->Execute(GenTask(retry, user, std::move(works)));
408         }
409     };
410 }
411 
GetSchemaMeta(int32_t userId,const std::string & bundleName,int32_t instanceId)412 SchemaMeta CloudServiceImpl::GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId)
413 {
414     SchemaMeta schemaMeta;
415     CloudInfo cloudInfo = GetCloudInfo(userId);
416     if (!cloudInfo.IsValid()) {
417         // GetCloudInfo has print the log info. so we don`t need print again.
418         return schemaMeta;
419     }
420 
421     if (!bundleName.empty() && !cloudInfo.Exist(bundleName, instanceId)) {
422         ZLOGD("bundleName:%{public}s instanceId:%{public}d is not exist", bundleName.c_str(), instanceId);
423         return schemaMeta;
424     }
425     std::string schemaKey = cloudInfo.GetSchemaKey(bundleName, instanceId);
426     if (MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) {
427         return schemaMeta;
428     }
429 
430     auto instance = CloudServer::GetInstance();
431     if (instance == nullptr) {
432         return schemaMeta;
433     }
434     schemaMeta = instance->GetAppSchema(userId, bundleName);
435     if (!schemaMeta.IsValid()) {
436         ZLOGE("download schema from cloud failed, user:%{public}d, bundleName:%{public}s", userId, bundleName.c_str());
437     }
438     MetaDataManager::GetInstance().SaveMeta(schemaKey, schemaMeta, true);
439     return schemaMeta;
440 }
441 
GetCloudInfo(int32_t userId)442 CloudInfo CloudServiceImpl::GetCloudInfo(int32_t userId)
443 {
444     CloudInfo cloudInfo;
445     cloudInfo.user = userId;
446     if (MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) {
447         return cloudInfo;
448     }
449     auto instance = CloudServer::GetInstance();
450     if (instance == nullptr) {
451         return cloudInfo;
452     }
453 
454     cloudInfo = instance->GetServerInfo(userId);
455     if (!cloudInfo.IsValid()) {
456         ZLOGE("no cloud info %{public}d", userId);
457         return cloudInfo;
458     }
459 
460     MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
461     return cloudInfo;
462 }
463 
OnAppUninstall(const std::string & bundleName,int32_t user,int32_t index)464 int32_t CloudServiceImpl::OnAppUninstall(
465     const std::string &bundleName, int32_t user, int32_t index)
466 {
467     MetaDataManager::GetInstance().DelMeta(Subscription::GetRelationKey(user, bundleName), true);
468     MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(user, bundleName, index), true);
469     return E_OK;
470 }
471 
GetSchema(const Event & event)472 void CloudServiceImpl::GetSchema(const Event &event)
473 {
474     auto &rdbEvent = static_cast<const CloudEvent &>(event);
475     auto &storeInfo = rdbEvent.GetStoreInfo();
476     ZLOGD("Start GetSchema, bundleName:%{public}s, storeName:%{public}s, instanceId:%{public}d",
477         storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId);
478     GetSchemaMeta(storeInfo.user, storeInfo.bundleName, storeInfo.instanceId);
479 }
480 
DoSubscribe(int32_t user)481 bool CloudServiceImpl::DoSubscribe(int32_t user)
482 {
483     Subscription sub;
484     sub.userId = user;
485     MetaDataManager::GetInstance().LoadMeta(sub.GetKey(), sub, true);
486     if (CloudServer::GetInstance() == nullptr) {
487         ZLOGI("not support cloud server");
488         return true;
489     }
490 
491     CloudInfo cloudInfo;
492     cloudInfo.user = sub.userId;
493     auto exits = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true);
494     if (!exits) {
495         ZLOGW("error, there is no cloud info for user(%{public}d)", sub.userId);
496         return false;
497     }
498 
499     ZLOGD("begin cloud:%{public}d user:%{public}d apps:%{public}zu", cloudInfo.enableCloud, sub.userId,
500         cloudInfo.apps.size());
501     auto onThreshold = duration_cast<milliseconds>((system_clock::now() + hours(EXPIRE_INTERVAL)).time_since_epoch());
502     auto offThreshold = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
503     std::map<std::string, std::vector<SchemaMeta::Database>> subDbs;
504     std::map<std::string, std::vector<SchemaMeta::Database>> unsubDbs;
505     for (auto &[bundle, app] : cloudInfo.apps) {
506         auto enabled = cloudInfo.enableCloud && app.cloudSwitch;
507         auto &dbs = enabled ? subDbs : unsubDbs;
508         auto it = sub.expiresTime.find(bundle);
509         // cloud is enabled, but the subscription won't expire
510         if (enabled && (it != sub.expiresTime.end() && it->second >= static_cast<uint64_t>(onThreshold.count()))) {
511             continue;
512         }
513         // cloud is disabled, we don't care the subscription which was expired or didn't subscribe.
514         if (!enabled && (it == sub.expiresTime.end() || it->second <= static_cast<uint64_t>(offThreshold.count()))) {
515             continue;
516         }
517 
518         SchemaMeta schemaMeta;
519         exits = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(bundle), schemaMeta, true);
520         if (exits) {
521             dbs.insert_or_assign(bundle, std::move(schemaMeta.databases));
522         }
523     }
524 
525     ZLOGI("cloud switch:%{public}d user%{public}d, sub:%{public}zu, unsub:%{public}zu", cloudInfo.enableCloud,
526         sub.userId, subDbs.size(), unsubDbs.size());
527     ZLOGD("Subscribe user%{public}d details:%{public}s", sub.userId, Serializable::Marshall(subDbs).c_str());
528     ZLOGD("Unsubscribe user%{public}d details:%{public}s", sub.userId, Serializable::Marshall(unsubDbs).c_str());
529     CloudServer::GetInstance()->Subscribe(sub.userId, subDbs);
530     CloudServer::GetInstance()->Unsubscribe(sub.userId, unsubDbs);
531     return subDbs.empty() && unsubDbs.empty();
532 }
533 
Execute(Task task)534 void CloudServiceImpl::Execute(Task task)
535 {
536     auto executor = executor_;
537     if (executor == nullptr) {
538         return;
539     }
540     executor->Execute(std::move(task));
541 }
542 } // namespace OHOS::CloudData