• 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 
20 #include <chrono>
21 #include <cinttypes>
22 
23 #include "accesstoken_kit.h"
24 #include "account/account_delegate.h"
25 #include "checker/checker_manager.h"
26 #include "cloud/cloud_last_sync_info.h"
27 #include "cloud/cloud_server.h"
28 #include "cloud/cloud_share_event.h"
29 #include "cloud/make_query_event.h"
30 #include "cloud/sharing_center.h"
31 #include "cloud_data_translate.h"
32 #include "cloud_value_util.h"
33 #include "device_manager_adapter.h"
34 #include "radar_reporter.h"
35 #include "eventcenter/event_center.h"
36 #include "hap_token_info.h"
37 #include "ipc_skeleton.h"
38 #include "log_print.h"
39 #include "metadata/meta_data_manager.h"
40 #include "network/network_delegate.h"
41 #include "rdb_types.h"
42 #include "reporter.h"
43 #include "relational_store_manager.h"
44 #include "runtime_config.h"
45 #include "store/auto_cache.h"
46 #include "sync_manager.h"
47 #include "sync_strategies/network_sync_strategy.h"
48 #include "utils/anonymous.h"
49 #include "values_bucket.h"
50 #include "xcollie.h"
51 
52 namespace OHOS::CloudData {
53 using namespace DistributedData;
54 using namespace std::chrono;
55 using namespace SharingUtil;
56 using namespace Security::AccessToken;
57 using namespace DistributedDataDfx;
58 using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter;
59 using Account = AccountDelegate;
60 using AccessTokenKit = Security::AccessToken::AccessTokenKit;
61 static constexpr uint32_t RESTART_SERVICE_TIME_THRESHOLD = 60;
62 static constexpr const char *FT_ENABLE_CLOUD = "ENABLE_CLOUD";
63 static constexpr const char *FT_DISABLE_CLOUD = "DISABLE_CLOUD";
64 static constexpr const char *FT_SWITCH_ON = "SWITCH_ON";
65 static constexpr const char *FT_SWITCH_OFF = "SWITCH_OFF";
66 static constexpr const char *FT_QUERY_INFO = "QUERY_SYNC_INFO";
67 static constexpr const char *FT_USER_CHANGE = "USER_CHANGE";
68 static constexpr const char *FT_USER_UNLOCK = "USER_UNLOCK";
69 static constexpr const char *FT_NETWORK_RECOVERY = "NETWORK_RECOVERY";
70 static constexpr const char *FT_SERVICE_INIT = "SERVICE_INIT";
71 static constexpr const char *FT_SYNC_TASK = "SYNC_TASK";
72 __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_;
73 const CloudServiceImpl::SaveStrategy CloudServiceImpl::STRATEGY_SAVERS[Strategy::STRATEGY_BUTT] = {
74     &CloudServiceImpl::SaveNetworkStrategy
75 };
76 
Factory()77 CloudServiceImpl::Factory::Factory() noexcept
78 {
79     FeatureSystem::GetInstance().RegisterCreator(
80         CloudServiceImpl::SERVICE_NAME,
81         [this]() {
82             if (product_ == nullptr) {
83                 product_ = std::make_shared<CloudServiceImpl>();
84             }
85             return product_;
86         },
87         FeatureSystem::BIND_NOW);
88     staticActs_ = std::make_shared<CloudStatic>();
89     FeatureSystem::GetInstance().RegisterStaticActs(CloudServiceImpl::SERVICE_NAME, staticActs_);
90 }
91 
~Factory()92 CloudServiceImpl::Factory::~Factory() {}
93 
CloudServiceImpl()94 CloudServiceImpl::CloudServiceImpl()
95 {
96     EventCenter::GetInstance().Subscribe(CloudEvent::GET_SCHEMA, [this](const Event &event) {
97         GetSchema(event);
98     });
99     EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SHARE, [this](const Event &event) {
100         CloudShare(event);
101     });
102     MetaDataManager::GetInstance().Subscribe(
103         Subscription::GetPrefix({ "" }), [this](const std::string &key,
104             const std::string &value, int32_t flag) -> auto {
105             if (flag != MetaDataManager::INSERT && flag != MetaDataManager::UPDATE) {
106                 return true;
107             }
108             Subscription sub;
109             Subscription::Unmarshall(value, sub);
110             InitSubTask(sub, SUBSCRIPTION_INTERVAL);
111             return true;
112         }, true);
113 }
114 
EnableCloud(const std::string & id,const std::map<std::string,int32_t> & switches)115 int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map<std::string, int32_t> &switches)
116 {
117     XCollie xcollie(
118         __FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY, RESTART_SERVICE_TIME_THRESHOLD);
119     auto tokenId = IPCSkeleton::GetCallingTokenID();
120     auto user = Account::GetInstance()->GetUserByToken(tokenId);
121     auto [status, cloudInfo] = GetCloudInfo(user);
122     if (status != SUCCESS) {
123         Report(FT_ENABLE_CLOUD, Fault::CSF_CLOUD_INFO, "", "EnableCloud ret=" + std::to_string(status));
124         return status;
125     }
126     cloudInfo.enableCloud = true;
127     for (const auto &[bundle, value] : switches) {
128         if (!cloudInfo.Exist(bundle)) {
129             continue;
130         }
131         cloudInfo.apps[bundle].cloudSwitch = (value == SWITCH_ON);
132         ZLOGI("EnableCloud: change app[%{public}s] switch to %{public}d", bundle.c_str(), value);
133     }
134     if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) {
135         return ERROR;
136     }
137     Execute(GenTask(0, cloudInfo.user, CloudSyncScene::ENABLE_CLOUD,
138         { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB }));
139     ZLOGI("EnableCloud success, id:%{public}s, count:%{public}zu", Anonymous::Change(id).c_str(), switches.size());
140     return SUCCESS;
141 }
142 
Report(const std::string & faultType,Fault errCode,const std::string & bundleName,const std::string & appendix)143 void CloudServiceImpl::Report(
144     const std::string &faultType, Fault errCode, const std::string &bundleName, const std::string &appendix)
145 {
146     ArkDataFaultMsg msg = { .faultType = faultType,
147         .bundleName = bundleName,
148         .moduleName = ModuleName::CLOUD_SERVER,
149         .errorType = static_cast<int32_t>(errCode) + SyncManager::GenStore::CLOUD_ERR_OFFSET,
150         .appendixMsg = appendix };
151     Reporter::GetInstance()->CloudSyncFault()->Report(msg);
152 }
153 
DisableCloud(const std::string & id)154 int32_t CloudServiceImpl::DisableCloud(const std::string &id)
155 {
156     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
157     auto tokenId = IPCSkeleton::GetCallingTokenID();
158     auto user = Account::GetInstance()->GetUserByToken(tokenId);
159     ReleaseUserInfo(user, CloudSyncScene::DISABLE_CLOUD);
160     std::lock_guard<decltype(rwMetaMutex_)> lock(rwMetaMutex_);
161     auto [status, cloudInfo] = GetCloudInfo(user);
162     if (status != SUCCESS) {
163         Report(FT_DISABLE_CLOUD, Fault::CSF_CLOUD_INFO, "", "DisableCloud ret=" + std::to_string(status));
164         return status;
165     }
166     if (cloudInfo.id != id) {
167         ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s", Anonymous::Change(id).c_str(),
168             Anonymous::Change(cloudInfo.id).c_str());
169         return INVALID_ARGUMENT;
170     }
171     cloudInfo.enableCloud = false;
172     if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) {
173         return ERROR;
174     }
175     Execute(GenTask(0, cloudInfo.user, CloudSyncScene::DISABLE_CLOUD, { WORK_STOP_CLOUD_SYNC, WORK_SUB }));
176     ZLOGI("DisableCloud success, id:%{public}s", Anonymous::Change(id).c_str());
177     return SUCCESS;
178 }
179 
ChangeAppSwitch(const std::string & id,const std::string & bundleName,int32_t appSwitch)180 int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch)
181 {
182     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
183     auto tokenId = IPCSkeleton::GetCallingTokenID();
184     auto user = Account::GetInstance()->GetUserByToken(tokenId);
185     CloudSyncScene scene;
186     if (appSwitch == SWITCH_ON) {
187         scene = CloudSyncScene::SWITCH_ON;
188     } else {
189         scene = CloudSyncScene::SWITCH_OFF;
190     }
191     std::lock_guard<decltype(rwMetaMutex_)> lock(rwMetaMutex_);
192     auto [status, cloudInfo] = GetCloudInfo(user);
193     if (status != SUCCESS || !cloudInfo.enableCloud) {
194         Report(appSwitch == SWITCH_ON ? FT_SWITCH_ON : FT_SWITCH_OFF, Fault::CSF_CLOUD_INFO, bundleName,
195             "ChangeAppSwitch ret = " + std::to_string(status));
196         return status;
197     }
198     if (cloudInfo.id != id) {
199         ZLOGW("invalid args, [input] id:%{public}s, [exist] id:%{public}s, bundleName:%{public}s",
200             Anonymous::Change(id).c_str(), Anonymous::Change(cloudInfo.id).c_str(), bundleName.c_str());
201         Execute(GenTask(0, cloudInfo.user, scene, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB,
202             WORK_DO_CLOUD_SYNC }));
203         return INVALID_ARGUMENT;
204     }
205     if (!cloudInfo.Exist(bundleName)) {
206         std::tie(status, cloudInfo) = GetCloudInfoFromServer(user);
207         if (status != SUCCESS || !cloudInfo.enableCloud || cloudInfo.id != id || !cloudInfo.Exist(bundleName)) {
208             ZLOGE("invalid args, status:%{public}d, enableCloud:%{public}d, [input] id:%{public}s,"
209                   "[exist] id:%{public}s, bundleName:%{public}s", status, cloudInfo.enableCloud,
210                   Anonymous::Change(id).c_str(), Anonymous::Change(cloudInfo.id).c_str(), bundleName.c_str());
211             Report(appSwitch == SWITCH_ON ? FT_SWITCH_ON : FT_SWITCH_OFF, Fault::CSF_CLOUD_INFO, bundleName,
212                 "ChangeAppSwitch ret=" + std::to_string(status));
213             return INVALID_ARGUMENT;
214         }
215         ZLOGI("add app switch, bundleName:%{public}s", bundleName.c_str());
216     }
217     cloudInfo.apps[bundleName].cloudSwitch = (appSwitch == SWITCH_ON);
218     if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) {
219         return ERROR;
220     }
221     Execute(GenTask(0, cloudInfo.user, scene, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB }));
222     if (cloudInfo.enableCloud && appSwitch == SWITCH_ON) {
223         SyncManager::SyncInfo info(cloudInfo.user, bundleName);
224         syncManager_.DoCloudSync(info);
225     }
226     ZLOGI("ChangeAppSwitch success, id:%{public}s app:%{public}s, switch:%{public}d", Anonymous::Change(id).c_str(),
227         bundleName.c_str(), appSwitch);
228     return SUCCESS;
229 }
230 
DoClean(const CloudInfo & cloudInfo,const std::map<std::string,int32_t> & actions)231 int32_t CloudServiceImpl::DoClean(const CloudInfo &cloudInfo, const std::map<std::string, int32_t> &actions)
232 {
233     syncManager_.StopCloudSync(cloudInfo.user);
234     for (const auto &[bundle, action] : actions) {
235         if (!cloudInfo.Exist(bundle)) {
236             ZLOGW("user:%{public}d, bundleName:%{public}s is not exist", cloudInfo.user, bundle.c_str());
237             continue;
238         }
239         SchemaMeta schemaMeta;
240         if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(bundle), schemaMeta, true)) {
241             ZLOGE("failed, no schema meta:bundleName:%{public}s", bundle.c_str());
242             continue;
243         }
244         DoClean(cloudInfo.user, schemaMeta, action);
245     }
246     return SUCCESS;
247 }
248 
DoClean(int32_t user,const SchemaMeta & schemaMeta,int32_t action)249 void CloudServiceImpl::DoClean(int32_t user, const SchemaMeta &schemaMeta, int32_t action)
250 {
251     StoreMetaData meta;
252     meta.bundleName = schemaMeta.bundleName;
253     meta.user = std::to_string(user);
254     meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
255     meta.instanceId = 0;
256     for (const auto &database : schemaMeta.databases) {
257         // action
258         meta.storeId = database.name;
259         if (!GetStoreMetaData(meta)) {
260             continue;
261         }
262         auto store = AutoCache::GetInstance().GetStore(meta, {});
263         if (store == nullptr) {
264             ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str());
265             continue;
266         }
267         DistributedData::StoreInfo storeInfo;
268         storeInfo.bundleName = meta.bundleName;
269         storeInfo.user = atoi(meta.user.c_str());
270         storeInfo.storeName = meta.storeId;
271         EventCenter::GetInstance().PostEvent(std::make_unique<CloudEvent>(CloudEvent::CLEAN_DATA, storeInfo));
272         auto status = store->Clean({}, action, "");
273         if (status != E_OK) {
274             ZLOGW("remove device data status:%{public}d, user:%{public}d, bundleName:%{public}s, "
275                   "storeId:%{public}s",
276                 status, static_cast<int>(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str());
277         } else {
278             ZLOGD("clean success, user:%{public}d, bundleName:%{public}s, storeId:%{public}s",
279                 static_cast<int>(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str());
280         }
281     }
282 }
283 
GetStoreMetaData(StoreMetaData & meta)284 bool CloudServiceImpl::GetStoreMetaData(StoreMetaData &meta)
285 {
286     if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
287         if (meta.user == "0") {
288             ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s, user = %{public}s",
289                   meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str());
290             return false;
291         }
292         meta.user = "0";
293         StoreMetaDataLocal localMeta;
294         if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) ||
295             !localMeta.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
296             ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s, user = %{public}s",
297                   meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str());
298             return false;
299         }
300     }
301     return true;
302 }
303 
Clean(const std::string & id,const std::map<std::string,int32_t> & actions)304 int32_t CloudServiceImpl::Clean(const std::string &id, const std::map<std::string, int32_t> &actions)
305 {
306     auto tokenId = IPCSkeleton::GetCallingTokenID();
307     auto user = Account::GetInstance()->GetUserByToken(tokenId);
308     auto [status, cloudInfo] = GetCloudInfoFromMeta(user);
309     if (status != SUCCESS) {
310         ZLOGE("get cloud meta failed user:%{public}d", static_cast<int>(cloudInfo.user));
311         return ERROR;
312     }
313     if (id != cloudInfo.id) {
314         ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(),
315             Anonymous::Change(id).c_str());
316         return ERROR;
317     }
318     auto dbActions = ConvertAction(actions);
319     if (dbActions.empty()) {
320         ZLOGE("invalid actions. id:%{public}s", Anonymous::Change(cloudInfo.id).c_str());
321         return ERROR;
322     }
323     return DoClean(cloudInfo, dbActions);
324 }
325 
CheckNotifyConditions(const std::string & id,const std::string & bundleName,CloudInfo & cloudInfo)326 int32_t CloudServiceImpl::CheckNotifyConditions(const std::string &id, const std::string &bundleName,
327     CloudInfo &cloudInfo)
328 {
329     if (cloudInfo.id != id) {
330         ZLOGE("invalid args, [input] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(id).c_str(),
331             Anonymous::Change(cloudInfo.id).c_str());
332         return INVALID_ARGUMENT;
333     }
334     if (!cloudInfo.enableCloud) {
335         ZLOGD("cloud is disabled, id:%{public}s, app:%{public}s ", Anonymous::Change(id).c_str(), bundleName.c_str());
336         return CLOUD_DISABLE;
337     }
338     if (!cloudInfo.Exist(bundleName)) {
339         ZLOGE("bundleName:%{public}s is not exist", bundleName.c_str());
340         return INVALID_ARGUMENT;
341     }
342     if (!cloudInfo.apps[bundleName].cloudSwitch) {
343         ZLOGD("cloud switch is disabled, id:%{public}s, app:%{public}s ", Anonymous::Change(id).c_str(),
344             bundleName.c_str());
345         return CLOUD_DISABLE_SWITCH;
346     }
347     return SUCCESS;
348 }
349 
GetDbInfoFromExtraData(const ExtraData & extraData,const SchemaMeta & schemaMeta)350 std::map<std::string, std::vector<std::string>> CloudServiceImpl::GetDbInfoFromExtraData(
351     const ExtraData &extraData, const SchemaMeta &schemaMeta)
352 {
353     std::map<std::string, std::vector<std::string>> dbInfos;
354     for (auto &db : schemaMeta.databases) {
355         if (db.alias != extraData.info.containerName) {
356             continue;
357         }
358         std::vector<std::string> tables;
359         if (extraData.info.tables.size() == 0) {
360             dbInfos.emplace(db.name, std::move(tables));
361             continue;
362         }
363         for (auto &table : db.tables) {
364             const auto &tbs = extraData.info.tables;
365             if (std::find(tbs.begin(), tbs.end(), table.alias) == tbs.end()) {
366                 continue;
367             }
368             if (extraData.isPrivate()) {
369                 ZLOGD("private table change, name:%{public}s", Anonymous::Change(table.name).c_str());
370                 tables.emplace_back(table.name);
371             }
372             if (extraData.isShared() && !table.sharedTableName.empty()) {
373                 ZLOGD("sharing table change, name:%{public}s", Anonymous::Change(table.sharedTableName).c_str());
374                 tables.emplace_back(table.sharedTableName);
375             }
376         }
377         if (!tables.empty()) {
378             dbInfos.emplace(db.name, std::move(tables));
379         }
380     }
381     if (dbInfos.empty()) {
382         for (auto &db : schemaMeta.databases) {
383             if (db.alias != extraData.info.containerName) {
384                 continue;
385             }
386             std::vector<std::string> tables;
387             dbInfos.emplace(db.name, std::move(tables));
388         }
389     }
390     return dbInfos;
391 }
392 
DoKvCloudSync(int32_t userId,const std::string & bundleName,int32_t triggerMode)393 bool CloudServiceImpl::DoKvCloudSync(int32_t userId, const std::string &bundleName, int32_t triggerMode)
394 {
395     auto stores = CheckerManager::GetInstance().GetDynamicStores();
396     auto staticStores = CheckerManager::GetInstance().GetStaticStores();
397     stores.insert(stores.end(), staticStores.begin(), staticStores.end());
398     bool found = std::any_of(stores.begin(), stores.end(), [&bundleName](const CheckerManager::StoreInfo &storeInfo) {
399         return bundleName.empty() || storeInfo.bundleName == bundleName;
400     });
401     if (!found) {
402         return found;
403     }
404     std::vector<int32_t> users;
405     if (userId != INVALID_USER_ID) {
406         users.emplace_back(userId);
407     } else {
408         Account::GetInstance()->QueryForegroundUsers(users);
409     }
410     for (auto user : users) {
411         for (const auto &store : stores) {
412             int32_t mode = (store.bundleName != bundleName && triggerMode == MODE_PUSH) ? MODE_CONSISTENCY
413                                                                                         : triggerMode;
414             syncManager_.DoCloudSync(SyncManager::SyncInfo(user, store.bundleName, store.storeId, {}, mode));
415         }
416     }
417     return found;
418 }
419 
NotifyDataChange(const std::string & id,const std::string & bundleName)420 int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::string &bundleName)
421 {
422     auto tokenId = IPCSkeleton::GetCallingTokenID();
423     auto user = Account::GetInstance()->GetUserByToken(tokenId);
424     auto [status, cloudInfo] = GetCloudInfoFromMeta(user);
425     if (CheckNotifyConditions(id, bundleName, cloudInfo) != E_OK) {
426         return INVALID_ARGUMENT;
427     }
428     syncManager_.DoCloudSync(SyncManager::SyncInfo(cloudInfo.user, bundleName));
429     return SUCCESS;
430 }
431 
NotifyDataChange(const std::string & eventId,const std::string & extraData,int32_t userId)432 int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId)
433 {
434     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
435     ExtraData exData;
436     if (eventId != DATA_CHANGE_EVENT_ID || extraData.empty() || !exData.Unmarshall(extraData)) {
437         ZLOGE("invalid args, eventId:%{public}s, user:%{public}d, extraData is %{public}s", eventId.c_str(),
438             userId, extraData.empty() ? "empty" : "not empty");
439         return INVALID_ARGUMENT;
440     }
441     std::vector<int32_t> users;
442     if (userId != INVALID_USER_ID) {
443         users.emplace_back(userId);
444     } else {
445         Account::GetInstance()->QueryForegroundUsers(users);
446     }
447     for (auto user : users) {
448         if (user == DEFAULT_USER) {
449             continue;
450         }
451         auto &bundleName = exData.info.bundleName;
452         auto &prepareTraceId = exData.info.context.prepareTraceId;
453         auto [status, cloudInfo] = GetCloudInfoFromMeta(user);
454         if (CheckNotifyConditions(exData.info.accountId, bundleName, cloudInfo) != E_OK) {
455             ZLOGD("invalid user:%{public}d, traceId:%{public}s", user, prepareTraceId.c_str());
456             syncManager_.Report({ user, bundleName, prepareTraceId, SyncStage::END, INVALID_ARGUMENT });
457             return INVALID_ARGUMENT;
458         }
459         auto schemaKey = CloudInfo::GetSchemaKey(user, bundleName);
460         SchemaMeta schemaMeta;
461         if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) {
462             ZLOGE("no exist meta, user:%{public}d, traceId:%{public}s", user, prepareTraceId.c_str());
463             syncManager_.Report({ user, bundleName, prepareTraceId, SyncStage::END, INVALID_ARGUMENT });
464             return INVALID_ARGUMENT;
465         }
466         auto dbInfos = GetDbInfoFromExtraData(exData, schemaMeta);
467         if (dbInfos.empty()) {
468             ZLOGE("GetDbInfoFromExtraData failed, empty database info. traceId:%{public}s.", prepareTraceId.c_str());
469             syncManager_.Report({ user, bundleName, prepareTraceId, SyncStage::END, INVALID_ARGUMENT });
470             return INVALID_ARGUMENT;
471         }
472         for (const auto &dbInfo : dbInfos) {
473             syncManager_.DoCloudSync(SyncManager::SyncInfo(
474                 { cloudInfo.user, bundleName, dbInfo.first, dbInfo.second, MODE_PUSH, prepareTraceId }));
475         }
476     }
477     return SUCCESS;
478 }
479 
ExecuteStatistics(const std::string & storeId,const CloudInfo & cloudInfo,const SchemaMeta & schemaMeta)480 std::map<std::string, StatisticInfos> CloudServiceImpl::ExecuteStatistics(const std::string &storeId,
481     const CloudInfo &cloudInfo, const SchemaMeta &schemaMeta)
482 {
483     std::map<std::string, StatisticInfos> result;
484     for (auto &database : schemaMeta.databases) {
485         if (storeId.empty() || database.alias == storeId) {
486             StoreMetaData meta;
487             meta.bundleName = schemaMeta.bundleName;
488             meta.storeId = database.name;
489             meta.user = std::to_string(cloudInfo.user);
490             meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
491             auto it = cloudInfo.apps.find(schemaMeta.bundleName);
492             if (it == cloudInfo.apps.end()) {
493                 ZLOGE("bundleName:%{public}s is not exist", schemaMeta.bundleName.c_str());
494                 break;
495             }
496             meta.instanceId = it->second.instanceId;
497             MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true);
498             result.insert_or_assign(database.alias, QueryStatistics(meta, database));
499         }
500     }
501     return result;
502 }
503 
QueryStatistics(const StoreMetaData & storeMetaData,const DistributedData::Database & database)504 StatisticInfos CloudServiceImpl::QueryStatistics(const StoreMetaData &storeMetaData,
505     const DistributedData::Database &database)
506 {
507     std::vector<StatisticInfo> infos;
508     auto store = AutoCache::GetInstance().GetStore(storeMetaData, {});
509     if (store == nullptr) {
510         ZLOGE("store failed, store is nullptr,bundleName:%{public}s",
511             Anonymous::Change(storeMetaData.bundleName).c_str());
512         return infos;
513     }
514     infos.reserve(database.tables.size());
515     for (const auto &table : database.tables) {
516         auto [success, info] = QueryTableStatistic(table.name, store);
517         if (success) {
518             info.table = table.alias;
519             infos.push_back(std::move(info));
520         }
521     }
522     return infos;
523 }
524 
QueryTableStatistic(const std::string & tableName,AutoCache::Store store)525 std::pair<bool, StatisticInfo> CloudServiceImpl::QueryTableStatistic(const std::string &tableName,
526     AutoCache::Store store)
527 {
528     StatisticInfo info;
529     auto sql = BuildStatisticSql(tableName);
530     auto [errCode, cursor] = store->Query(tableName, sql, {});
531     if (errCode != E_OK || cursor == nullptr || cursor->GetCount() != 1 || cursor->MoveToFirst() != E_OK) {
532         ZLOGE("query failed, cursor is nullptr or move to first failed,tableName:%{public}s",
533             Anonymous::Change(tableName).c_str());
534         return { false, info };
535     }
536     DistributedData::VBucket entry;
537     if (cursor->GetEntry(entry) != E_OK) {
538         ZLOGE("get entry failed,tableName:%{public}s", Anonymous::Change(tableName).c_str());
539         return { false, info };
540     }
541     auto it = entry.find("inserted");
542     if (it != entry.end() && it->second.index() == TYPE_INDEX<int64_t>) {
543         info.inserted = std::get<int64_t>(it->second);
544     }
545     it = entry.find("updated");
546     if (it != entry.end() && it->second.index() == TYPE_INDEX<int64_t>) {
547         info.updated = std::get<int64_t>(it->second);
548     }
549     it = entry.find("normal");
550     if (it != entry.end() && it->second.index() == TYPE_INDEX<int64_t>) {
551         info.normal = std::get<int64_t>(it->second);
552     }
553     return { true, info };
554 }
555 
BuildStatisticSql(const std::string & tableName)556 std::string CloudServiceImpl::BuildStatisticSql(const std::string &tableName)
557 {
558     std::string logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(tableName);
559     std::string sql = "select ";
560     sql.append("count(case when cloud_gid = '' and flag&(0x1|0x8|0x20) = 0x20 then 1 end) as inserted,");
561     sql.append("count(case when cloud_gid <> '' and flag&0x20 != 0  then 1 end) as updated,");
562     sql.append("count(case when cloud_gid <> '' and flag&(0x1|0x8|0x20) = 0 then 1 end) as normal");
563     sql.append(" from ").append(logTable);
564 
565     return sql;
566 }
567 
QueryStatistics(const std::string & id,const std::string & bundleName,const std::string & storeId)568 std::pair<int32_t, std::map<std::string, StatisticInfos>> CloudServiceImpl::QueryStatistics(const std::string &id,
569     const std::string &bundleName, const std::string &storeId)
570 {
571     std::map<std::string, StatisticInfos> result;
572     auto tokenId = IPCSkeleton::GetCallingTokenID();
573     auto user = Account::GetInstance()->GetUserByToken(tokenId);
574     auto [status, cloudInfo] = GetCloudInfoFromMeta(user);
575     if (status != SUCCESS) {
576         ZLOGE("get cloud meta failed user:%{public}d", static_cast<int>(cloudInfo.user));
577         return { ERROR, result };
578     }
579     if (id != cloudInfo.id || bundleName.empty() || cloudInfo.apps.find(bundleName) == cloudInfo.apps.end()) {
580         ZLOGE("[server] id:%{public}s, [meta] id:%{public}s, bundleName:%{public}s",
581             Anonymous::Change(cloudInfo.id).c_str(), Anonymous::Change(id).c_str(), bundleName.c_str());
582         return { ERROR, result };
583     }
584     SchemaMeta schemaMeta;
585     std::string schemaKey = cloudInfo.GetSchemaKey(bundleName);
586     if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) {
587         ZLOGE("get load meta failed user:%{public}d", static_cast<int>(cloudInfo.user));
588         return { ERROR, result };
589     }
590     result = ExecuteStatistics(storeId, cloudInfo, schemaMeta);
591     return { SUCCESS, result };
592 }
593 
SetGlobalCloudStrategy(Strategy strategy,const std::vector<CommonType::Value> & values)594 int32_t CloudServiceImpl::SetGlobalCloudStrategy(Strategy strategy, const std::vector<CommonType::Value> &values)
595 {
596     if (strategy >= Strategy::STRATEGY_BUTT) {
597         ZLOGE("invalid strategy:%{public}d, size:%{public}zu", strategy, values.size());
598         return INVALID_ARGUMENT;
599     }
600     auto tokenId = IPCSkeleton::GetCallingTokenID();
601     HapInfo hapInfo;
602     hapInfo.user = Account::GetInstance()->GetUserByToken(tokenId);
603     if (hapInfo.user == INVALID_USER_ID || hapInfo.user == 0) {
604         ZLOGE("invalid user:%{public}d, strategy:%{public}d, size:%{public}zu", hapInfo.user, strategy,
605             values.size());
606         return ERROR;
607     }
608     hapInfo.bundleName = SyncStrategy::GLOBAL_BUNDLE;
609     return STRATEGY_SAVERS[strategy](values, hapInfo);
610 }
611 
QueryLastSyncInfo(const std::string & id,const std::string & bundleName,const std::string & storeId)612 std::pair<int32_t, QueryLastResults> CloudServiceImpl::QueryLastSyncInfo(const std::string &id,
613     const std::string &bundleName, const std::string &storeId)
614 {
615     QueryLastResults results;
616     auto user = Account::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID());
617     auto [status, cloudInfo] = GetCloudInfo(user);
618     if (status != SUCCESS) {
619         Report(FT_QUERY_INFO, Fault::CSF_CLOUD_INFO, bundleName,
620             "QueryLastSyncInfo ret=" + std::to_string(status) + ",storeId=" + storeId);
621         return { ERROR, results };
622     }
623     if (cloudInfo.apps.find(bundleName) == cloudInfo.apps.end()) {
624         ZLOGE("Invalid bundleName: %{public}s", bundleName.c_str());
625         return { INVALID_ARGUMENT, results };
626     }
627     std::vector<SchemaMeta> schemas;
628     auto key = cloudInfo.GetSchemaPrefix(bundleName);
629     if (!MetaDataManager::GetInstance().LoadMeta(key, schemas, true) || schemas.empty()) {
630         return { ERROR, results };
631     }
632 
633     std::vector<QueryKey> queryKeys;
634     std::vector<Database> databases;
635     for (const auto &schema : schemas) {
636         if (schema.bundleName != bundleName) {
637             continue;
638         }
639         databases = schema.databases;
640         for (const auto &database : schema.databases) {
641             if (storeId.empty() || database.alias == storeId) {
642                 queryKeys.push_back({ user, id, bundleName, database.name });
643             }
644         }
645         if (queryKeys.empty()) {
646             ZLOGE("Invalid storeId: %{public}s", Anonymous::Change(storeId).c_str());
647             return { INVALID_ARGUMENT, results };
648         }
649     }
650 
651     auto [ret, lastSyncInfos] = syncManager_.QueryLastSyncInfo(queryKeys);
652     ZLOGI("code:%{public}d, id:%{public}s, bundleName:%{public}s, storeId:%{public}s, size:%{public}d", ret,
653         Anonymous::Change(id).c_str(), bundleName.c_str(), Anonymous::Change(storeId).c_str(),
654         static_cast<int32_t>(lastSyncInfos.size()));
655     if (lastSyncInfos.empty()) {
656         return { ret, results };
657     }
658     return { ret, AssembleLastResults(databases, lastSyncInfos) };
659 }
660 
OnInitialize()661 int32_t CloudServiceImpl::OnInitialize()
662 {
663     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
664     DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared<RdbCloudDataTranslate>());
665     Execute(GenTask(0, 0, CloudSyncScene::SERVICE_INIT,
666         { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB }));
667     std::vector<int> users;
668     Account::GetInstance()->QueryUsers(users);
669     for (auto user : users) {
670         if (user == DEFAULT_USER) {
671             continue;
672         }
673         Subscription sub;
674         sub.userId = user;
675         if (!MetaDataManager::GetInstance().LoadMeta(sub.GetKey(), sub, true)) {
676             continue;
677         }
678         InitSubTask(sub);
679     }
680     return E_OK;
681 }
682 
OnBind(const BindInfo & info)683 int32_t CloudServiceImpl::OnBind(const BindInfo &info)
684 {
685     if (executor_ != nullptr || info.executors == nullptr) {
686         return E_INVALID_ARGS;
687     }
688 
689     executor_ = std::move(info.executors);
690     syncManager_.Bind(executor_);
691     auto instance = CloudServer::GetInstance();
692     if (instance != nullptr) {
693         instance->Bind(executor_);
694     }
695     return E_OK;
696 }
697 
OnUserChange(uint32_t code,const std::string & user,const std::string & account)698 int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account)
699 {
700     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
701     int32_t userId = atoi(user.c_str());
702     ZLOGI("code:%{public}d, user:%{public}s, account:%{public}s", code, user.c_str(),
703         Anonymous::Change(account).c_str());
704     switch (code) {
705         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_SWITCHED):
706             Execute(GenTask(0, userId, CloudSyncScene::USER_CHANGE,
707                 { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB }));
708             break;
709         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_DELETE):
710         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_STOPPING):
711         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_STOPPED):
712             Execute(GenTask(0, userId, CloudSyncScene::ACCOUNT_STOP, { WORK_STOP_CLOUD_SYNC, WORK_RELEASE }));
713             break;
714         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_UNLOCKED):
715             Execute(GenTask(0, userId, CloudSyncScene::USER_UNLOCK,
716                 { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB }));
717             break;
718         default:
719             break;
720     }
721     return E_OK;
722 }
723 
OnReady(const std::string & device)724 int32_t CloudServiceImpl::OnReady(const std::string &device)
725 {
726     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
727     if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) {
728         return SUCCESS;
729     }
730     std::vector<int32_t> users;
731     Account::GetInstance()->QueryForegroundUsers(users);
732     if (users.empty()) {
733         return SUCCESS;
734     }
735     if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) {
736         return NETWORK_ERROR;
737     }
738     for (auto user : users) {
739         DoKvCloudSync(user, "", MODE_ONLINE);
740         Execute(GenTask(0, user, CloudSyncScene::NETWORK_RECOVERY,
741             { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB }));
742     }
743     return SUCCESS;
744 }
745 
Offline(const std::string & device)746 int32_t CloudServiceImpl::Offline(const std::string &device)
747 {
748     if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) {
749         ZLOGI("Not network offline");
750         return SUCCESS;
751     }
752     std::vector<int32_t> users;
753     Account::GetInstance()->QueryUsers(users);
754     if (users.empty()) {
755         return SUCCESS;
756     }
757     auto it = users.begin();
758     syncManager_.StopCloudSync(*it);
759     return SUCCESS;
760 }
761 
GetCloudInfoFromMeta(int32_t userId)762 std::pair<int32_t, CloudInfo> CloudServiceImpl::GetCloudInfoFromMeta(int32_t userId)
763 {
764     CloudInfo cloudInfo;
765     cloudInfo.user = userId;
766     if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) {
767         auto time = static_cast<uint64_t>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
768         ZLOGE("no exist meta, user:%{public}d times:%{public}" PRIu64 ".", cloudInfo.user, time);
769         return { ERROR, cloudInfo };
770     }
771     return { SUCCESS, cloudInfo };
772 }
773 
GetCloudInfoFromServer(int32_t userId)774 std::pair<int32_t, CloudInfo> CloudServiceImpl::GetCloudInfoFromServer(int32_t userId)
775 {
776     CloudInfo cloudInfo;
777     cloudInfo.user = userId;
778     if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) {
779         ZLOGD("network is not available");
780         return { NETWORK_ERROR, cloudInfo };
781     }
782     auto instance = CloudServer::GetInstance();
783     if (instance == nullptr) {
784         ZLOGD("cloud server is nullptr, user:%{public}d", userId);
785         return { SERVER_UNAVAILABLE, cloudInfo };
786     }
787     return instance->GetServerInfo(cloudInfo.user, false);
788 }
789 
UpdateCloudInfoFromServer(int32_t user)790 int32_t CloudServiceImpl::UpdateCloudInfoFromServer(int32_t user)
791 {
792     auto [status, cloudInfo] = GetCloudInfoFromServer(user);
793     if (status != SUCCESS || !cloudInfo.IsValid()) {
794         ZLOGE("userId:%{public}d, status:%{public}d", user, status);
795         return E_ERROR;
796     }
797     return MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true) ? E_OK : E_ERROR;
798 }
799 
UpdateCloudInfo(int32_t user,CloudSyncScene scene)800 bool CloudServiceImpl::UpdateCloudInfo(int32_t user, CloudSyncScene scene)
801 {
802     auto [status, cloudInfo] = GetCloudInfoFromServer(user);
803     if (status != SUCCESS) {
804         ZLOGE("user:%{public}d, status:%{public}d", user, status);
805         Report(GetDfxFaultType(scene), Fault::CSF_CLOUD_INFO, "", "UpdateCloudInfo ret=" + std::to_string(status));
806         return false;
807     }
808     ZLOGI("[server] id:%{public}s, enableCloud:%{public}d, user:%{public}d, app size:%{public}zu",
809           Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.enableCloud, cloudInfo.user, cloudInfo.apps.size());
810     CloudInfo oldInfo;
811     if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), oldInfo, true)) {
812         MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
813         return true;
814     }
815     MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
816     if (oldInfo.id != cloudInfo.id) {
817         ReleaseUserInfo(user, scene);
818         ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(),
819             Anonymous::Change(oldInfo.id).c_str());
820         MetaDataManager::GetInstance().DelMeta(Subscription::GetKey(user), true);
821         std::map<std::string, int32_t> actions;
822         for (auto &[bundle, app] : cloudInfo.apps) {
823             MetaDataManager::GetInstance().DelMeta(Subscription::GetRelationKey(user, bundle), true);
824             actions[bundle] = GeneralStore::CleanMode::CLOUD_INFO;
825         }
826         DoClean(oldInfo, actions);
827     }
828     return true;
829 }
830 
UpdateSchema(int32_t user,CloudSyncScene scene)831 bool CloudServiceImpl::UpdateSchema(int32_t user, CloudSyncScene scene)
832 {
833     auto [status, cloudInfo] = GetCloudInfo(user);
834     if (status != SUCCESS) {
835         Report(GetDfxFaultType(scene), Fault::CSF_APP_SCHEMA, "", "UpdateSchema ret=" + std::to_string(status));
836         return false;
837     }
838     auto keys = cloudInfo.GetSchemaKey();
839     for (const auto &[bundle, key] : keys) {
840         SchemaMeta schemaMeta;
841         std::tie(status, schemaMeta) = GetAppSchemaFromServer(user, bundle);
842         if (status == NOT_SUPPORT) {
843             ZLOGW("app not support, del cloudInfo! user:%{public}d, bundleName:%{public}s", user, bundle.c_str());
844             MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey(), true);
845             return false;
846         }
847         if (status != SUCCESS) {
848             continue;
849         }
850         SchemaMeta oldMeta;
851         if (MetaDataManager::GetInstance().LoadMeta(key, oldMeta, true)) {
852             UpgradeSchemaMeta(user, oldMeta);
853         }
854         MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true);
855     }
856     return true;
857 }
858 
GetAppSchemaFromServer(int32_t user,const std::string & bundleName)859 std::pair<int32_t, SchemaMeta> CloudServiceImpl::GetAppSchemaFromServer(int32_t user, const std::string &bundleName)
860 {
861     SchemaMeta schemaMeta;
862     if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) {
863         ZLOGD("network is not available");
864         return { NETWORK_ERROR, schemaMeta };
865     }
866     auto instance = CloudServer::GetInstance();
867     if (instance == nullptr) {
868         return { SERVER_UNAVAILABLE, schemaMeta };
869     }
870     int32_t status = E_OK;
871     std::tie(status, schemaMeta) = instance->GetAppSchema(user, bundleName);
872     if (status != E_OK || !schemaMeta.IsValid()) {
873         ZLOGE("schema is InValid, user:%{public}d, bundleName:%{public}s, status:%{public}d", user, bundleName.c_str(),
874             status);
875         return { status == E_NOT_SUPPORT ? NOT_SUPPORT : SCHEMA_INVALID, schemaMeta };
876     }
877     return { SUCCESS, schemaMeta };
878 }
879 
UpgradeSchemaMeta(int32_t user,const SchemaMeta & schemaMeta)880 void CloudServiceImpl::UpgradeSchemaMeta(int32_t user, const SchemaMeta &schemaMeta)
881 {
882     if (schemaMeta.metaVersion == SchemaMeta::CURRENT_VERSION) {
883         return;
884     }
885     // A major schema upgrade requires flag cleaning
886     if (SchemaMeta::GetHighVersion(schemaMeta.metaVersion) != SchemaMeta::GetHighVersion()) {
887         ZLOGI("start clean. user:%{public}d, bundleName:%{public}s, metaVersion:%{public}d", user,
888             schemaMeta.bundleName.c_str(), schemaMeta.metaVersion);
889         DoClean(user, schemaMeta, GeneralStore::CleanMode::CLOUD_INFO);
890     }
891 }
892 
GenTask(int32_t retry,int32_t user,CloudSyncScene scene,Handles handles)893 ExecutorPool::Task CloudServiceImpl::GenTask(int32_t retry, int32_t user, CloudSyncScene scene, Handles handles)
894 {
895     return [this, retry, user, scene, works = std::move(handles)]() mutable {
896         auto executor = executor_;
897         if (retry >= RETRY_TIMES || executor == nullptr || works.empty()) {
898             return;
899         }
900         if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) {
901             ZLOGD("network is not available");
902             return;
903         }
904         bool finished = true;
905         std::vector<int32_t> users;
906         if (user == 0) {
907             auto account = Account::GetInstance();
908             finished = (account != nullptr) && account->QueryUsers(users);
909         } else {
910             users.push_back(user);
911         }
912 
913         auto handle = works.front();
914         for (auto user : users) {
915             if (user == 0 || !Account::GetInstance()->IsVerified(user)) {
916                 continue;
917             }
918             finished = (this->*handle)(user, scene) && finished;
919         }
920         if (!finished || users.empty()) {
921             executor->Schedule(std::chrono::seconds(RETRY_INTERVAL), GenTask(retry + 1, user, scene, std::move(works)));
922             return;
923         }
924         works.pop_front();
925         if (!works.empty()) {
926             executor->Execute(GenTask(retry, user, scene, std::move(works)));
927         }
928     };
929 }
930 
GetSchemaMeta(int32_t userId,const std::string & bundleName,int32_t instanceId)931 std::pair<int32_t, SchemaMeta> CloudServiceImpl::GetSchemaMeta(int32_t userId, const std::string &bundleName,
932     int32_t instanceId)
933 {
934     SchemaMeta schemaMeta;
935     auto [status, cloudInfo] = GetCloudInfoFromMeta(userId);
936     if (status != SUCCESS) {
937         // GetCloudInfo has print the log info. so we don`t need print again.
938         return { status, schemaMeta };
939     }
940     if (!bundleName.empty() && !cloudInfo.Exist(bundleName, instanceId)) {
941         ZLOGD("bundleName:%{public}s instanceId:%{public}d is not exist", bundleName.c_str(), instanceId);
942         return { ERROR, schemaMeta };
943     }
944     std::string schemaKey = cloudInfo.GetSchemaKey(bundleName, instanceId);
945     if (MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true) &&
946         schemaMeta.metaVersion == SchemaMeta::CURRENT_VERSION) {
947         return { SUCCESS, schemaMeta };
948     }
949     UpgradeSchemaMeta(userId, schemaMeta);
950 
951     if (!Account::GetInstance()->IsVerified(userId)) {
952         ZLOGE("user:%{public}d is locked!", userId);
953         return { ERROR, schemaMeta };
954     }
955     std::tie(status, schemaMeta) = GetAppSchemaFromServer(userId, bundleName);
956     if (status == NOT_SUPPORT) {
957         ZLOGW("app not support, del cloudInfo! userId:%{public}d, bundleName:%{public}s", userId, bundleName.c_str());
958         MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey(), true);
959         return { status, schemaMeta };
960     }
961     if (status != SUCCESS) {
962         return { status, schemaMeta };
963     }
964     MetaDataManager::GetInstance().SaveMeta(schemaKey, schemaMeta, true);
965     return { SUCCESS, schemaMeta };
966 }
967 
GetCloudInfo(int32_t userId)968 std::pair<int32_t, CloudInfo> CloudServiceImpl::GetCloudInfo(int32_t userId)
969 {
970     auto [status, cloudInfo] = GetCloudInfoFromMeta(userId);
971     if (status == SUCCESS) {
972         return { status, cloudInfo };
973     }
974     if (!Account::GetInstance()->IsVerified(userId)) {
975         ZLOGW("user:%{public}d is locked!", userId);
976         return { ERROR, cloudInfo };
977     }
978     std::tie(status, cloudInfo) = GetCloudInfoFromServer(userId);
979     if (status != SUCCESS) {
980         ZLOGE("userId:%{public}d, status:%{public}d", userId, status);
981         return { status, cloudInfo };
982     }
983     MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
984     return { SUCCESS, cloudInfo };
985 }
986 
OnAppUninstall(const std::string & bundleName,int32_t user,int32_t index)987 int32_t CloudServiceImpl::CloudStatic::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index)
988 {
989     Subscription sub;
990     if (MetaDataManager::GetInstance().LoadMeta(Subscription::GetKey(user), sub, true)) {
991         sub.expiresTime.erase(bundleName);
992         MetaDataManager::GetInstance().SaveMeta(Subscription::GetKey(user), sub, true);
993     }
994 
995     CloudInfo cloudInfo;
996     cloudInfo.user = user;
997     if (MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) {
998         cloudInfo.apps.erase(bundleName);
999         MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true);
1000     }
1001 
1002     MetaDataManager::GetInstance().DelMeta(Subscription::GetRelationKey(user, bundleName), true);
1003     MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(user, bundleName, index), true);
1004     MetaDataManager::GetInstance().DelMeta(NetworkSyncStrategy::GetKey(user, bundleName), true);
1005     return E_OK;
1006 }
1007 
OnAppInstall(const std::string & bundleName,int32_t user,int32_t index)1008 int32_t CloudServiceImpl::CloudStatic::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index)
1009 {
1010     return UpdateCloudInfoFromServer(user);
1011 }
1012 
GetSchema(const Event & event)1013 void CloudServiceImpl::GetSchema(const Event &event)
1014 {
1015     auto &rdbEvent = static_cast<const CloudEvent &>(event);
1016     auto &storeInfo = rdbEvent.GetStoreInfo();
1017     ZLOGD("Start GetSchema, bundleName:%{public}s, storeName:%{public}s, instanceId:%{public}d",
1018         storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId);
1019     if (storeInfo.user == 0) {
1020         std::vector<int32_t> users;
1021         AccountDelegate::GetInstance()->QueryUsers(users);
1022         GetSchemaMeta(users[0], storeInfo.bundleName, storeInfo.instanceId);
1023     } else {
1024         GetSchemaMeta(storeInfo.user, storeInfo.bundleName, storeInfo.instanceId);
1025     }
1026 }
1027 
CloudShare(const Event & event)1028 void CloudServiceImpl::CloudShare(const Event &event)
1029 {
1030     auto &cloudShareEvent = static_cast<const CloudShareEvent &>(event);
1031     auto &storeInfo = cloudShareEvent.GetStoreInfo();
1032     auto query = cloudShareEvent.GetQuery();
1033     auto callback = cloudShareEvent.GetCallback();
1034     if (query == nullptr) {
1035         ZLOGE("query is null, bundleName:%{public}s, storeName:%{public}s, instanceId:%{public}d",
1036             storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId);
1037         if (callback) {
1038             callback(GeneralError::E_ERROR, nullptr);
1039         }
1040         return;
1041     }
1042     ZLOGD("Start PreShare, bundleName:%{public}s, storeName:%{public}s, instanceId:%{public}d",
1043         storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId);
1044     auto [status, cursor] = PreShare(storeInfo, *query);
1045 
1046     if (callback) {
1047         callback(status, cursor);
1048     }
1049 }
1050 
PreShare(const StoreInfo & storeInfo,GenQuery & query)1051 std::pair<int32_t, std::shared_ptr<DistributedData::Cursor>> CloudServiceImpl::PreShare(
1052     const StoreInfo &storeInfo, GenQuery &query)
1053 {
1054     StoreMetaData meta(storeInfo);
1055     meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
1056     if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
1057         ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
1058             meta.GetStoreAlias().c_str());
1059         return { GeneralError::E_ERROR, nullptr };
1060     }
1061     auto [status, store] = SyncManager::GetStore(meta, storeInfo.user, true);
1062     if (store == nullptr) {
1063         ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str());
1064         return { GeneralError::E_ERROR, nullptr };
1065     }
1066     return store->PreSharing(query);
1067 }
1068 
ReleaseUserInfo(int32_t user,CloudSyncScene scene)1069 bool CloudServiceImpl::ReleaseUserInfo(int32_t user, CloudSyncScene scene)
1070 {
1071     auto instance = CloudServer::GetInstance();
1072     if (instance == nullptr) {
1073         return true;
1074     }
1075     instance->ReleaseUserInfo(user);
1076     ZLOGI("notify release user info, user:%{public}d", user);
1077     return true;
1078 }
1079 
DoCloudSync(int32_t user,CloudSyncScene scene)1080 bool CloudServiceImpl::DoCloudSync(int32_t user, CloudSyncScene scene)
1081 {
1082     auto [status, cloudInfo] = GetCloudInfo(user);
1083     if (status != SUCCESS) {
1084         Report(GetDfxFaultType(scene), Fault::CSF_CLOUD_INFO, "", "DoCloudSync ret=" + std::to_string(status));
1085         return false;
1086     }
1087     for (const auto &appInfo : cloudInfo.apps) {
1088         SyncManager::SyncInfo info(user, appInfo.first);
1089         syncManager_.DoCloudSync(info);
1090     }
1091     return true;
1092 }
1093 
StopCloudSync(int32_t user,CloudSyncScene scene)1094 bool CloudServiceImpl::StopCloudSync(int32_t user, CloudSyncScene scene)
1095 {
1096     syncManager_.StopCloudSync(user);
1097     syncManager_.CleanCompensateSync(user);
1098     return true;
1099 }
1100 
DoSubscribe(int32_t user,CloudSyncScene scene)1101 bool CloudServiceImpl::DoSubscribe(int32_t user, CloudSyncScene scene)
1102 {
1103     Subscription sub;
1104     sub.userId = user;
1105     MetaDataManager::GetInstance().LoadMeta(sub.GetKey(), sub, true);
1106     if (CloudServer::GetInstance() == nullptr) {
1107         ZLOGE("not support cloud server");
1108         return true;
1109     }
1110     CloudInfo cloudInfo;
1111     cloudInfo.user = sub.userId;
1112     if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) {
1113         ZLOGW("error, there is no cloud info for user(%{public}d)", sub.userId);
1114         return false;
1115     }
1116     if (!sub.id.empty() && sub.id != cloudInfo.id) {
1117         CleanSubscription(sub);
1118     }
1119     auto onThreshold = duration_cast<milliseconds>((system_clock::now() + hours(EXPIRE_INTERVAL)).time_since_epoch());
1120     auto offThreshold = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
1121     std::map<std::string, std::vector<SchemaMeta::Database>> subDbs;
1122     std::map<std::string, std::vector<SchemaMeta::Database>> unsubDbs;
1123     for (auto &[bundle, app] : cloudInfo.apps) {
1124         auto enabled = cloudInfo.enableCloud && app.cloudSwitch;
1125         auto &dbs = enabled ? subDbs : unsubDbs;
1126         auto it = sub.expiresTime.find(bundle);
1127         // cloud is enabled, but the subscription won't expire
1128         if (enabled && (it != sub.expiresTime.end() && it->second >= static_cast<uint64_t>(onThreshold.count()))) {
1129             continue;
1130         }
1131         // cloud is disabled, we don't care the subscription which was expired or didn't subscribe.
1132         if (!enabled && (it == sub.expiresTime.end() || it->second <= static_cast<uint64_t>(offThreshold.count()))) {
1133             continue;
1134         }
1135         SchemaMeta schemaMeta;
1136         if (MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(bundle), schemaMeta, true)) {
1137             dbs.insert_or_assign(bundle, std::move(schemaMeta.databases));
1138         }
1139     }
1140     ZLOGI("cloud switch:%{public}d user%{public}d, sub:%{public}zu, unsub:%{public}zu", cloudInfo.enableCloud,
1141         sub.userId, subDbs.size(), unsubDbs.size());
1142     auto status = CloudServer::GetInstance()->Subscribe(sub.userId, subDbs);
1143     if (status != SUCCESS) {
1144         Report(GetDfxFaultType(scene), Fault::CSF_SUBSCRIBE, "", "Subscribe ret=" + std::to_string(status));
1145     }
1146     status = CloudServer::GetInstance()->Unsubscribe(sub.userId, unsubDbs);
1147     if (status != SUCCESS && scene != CloudSyncScene::DISABLE_CLOUD) {
1148         Report(GetDfxFaultType(scene), Fault::CSF_UNSUBSCRIBE, "", "Unsubscribe, ret=" + std::to_string(status));
1149     }
1150     return subDbs.empty() && unsubDbs.empty();
1151 }
1152 
CleanSubscription(Subscription & sub)1153 void CloudServiceImpl::CleanSubscription(Subscription &sub)
1154 {
1155     ZLOGD("id:%{public}s, size:%{public}zu", Anonymous::Change(sub.id).c_str(), sub.expiresTime.size());
1156     MetaDataManager::GetInstance().DelMeta(sub.GetKey(), true);
1157     for (const auto &[bundle, expireTime] : sub.expiresTime) {
1158         MetaDataManager::GetInstance().DelMeta(sub.GetRelationKey(bundle), true);
1159     }
1160     sub.id.clear();
1161     sub.expiresTime.clear();
1162 }
1163 
Execute(Task task)1164 void CloudServiceImpl::Execute(Task task)
1165 {
1166     auto executor = executor_;
1167     if (executor == nullptr) {
1168         return;
1169     }
1170     executor->Execute(std::move(task));
1171 }
1172 
ConvertAction(const std::map<std::string,int32_t> & actions)1173 std::map<std::string, int32_t> CloudServiceImpl::ConvertAction(const std::map<std::string, int32_t> &actions)
1174 {
1175     std::map<std::string, int32_t> genActions;
1176     for (const auto &[bundleName, action] : actions) {
1177         switch (action) {
1178             case CloudService::Action::CLEAR_CLOUD_INFO:
1179                 genActions.emplace(bundleName, GeneralStore::CleanMode::CLOUD_INFO);
1180                 break;
1181             case CloudService::Action::CLEAR_CLOUD_DATA_AND_INFO:
1182                 genActions.emplace(bundleName, GeneralStore::CleanMode::CLOUD_DATA);
1183                 break;
1184             default:
1185                 ZLOGE("invalid action. action:%{public}d, bundleName:%{public}s", action, bundleName.c_str());
1186                 return {};
1187         }
1188     }
1189     return genActions;
1190 }
1191 
AllocResourceAndShare(const std::string & storeId,const DistributedRdb::PredicatesMemo & predicates,const std::vector<std::string> & columns,const Participants & participants)1192 std::pair<int32_t, std::vector<NativeRdb::ValuesBucket>> CloudServiceImpl::AllocResourceAndShare(
1193     const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates,
1194     const std::vector<std::string> &columns, const Participants &participants)
1195 {
1196     auto tokenId = IPCSkeleton::GetCallingTokenID();
1197     auto hapInfo = GetHapInfo(tokenId);
1198     if (hapInfo.bundleName.empty() || hapInfo.user == INVALID_USER_ID) {
1199         ZLOGE("bundleName is empty or invalid user, user:%{public}d, storeId:%{public}s", hapInfo.user,
1200             Anonymous::Change(storeId).c_str());
1201         return { E_ERROR, {} };
1202     }
1203     if (predicates.tables_.empty()) {
1204         ZLOGE("invalid args, tables size:%{public}zu, storeId:%{public}s", predicates.tables_.size(),
1205             Anonymous::Change(storeId).c_str());
1206         return { E_INVALID_ARGS, {} };
1207     }
1208     auto memo = std::make_shared<DistributedRdb::PredicatesMemo>(predicates);
1209     StoreInfo storeInfo;
1210     storeInfo.bundleName = hapInfo.bundleName;
1211     storeInfo.tokenId = tokenId;
1212     storeInfo.user = hapInfo.user;
1213     storeInfo.storeName = storeId;
1214     std::shared_ptr<GenQuery> query;
1215     MakeQueryEvent::Callback asyncCallback = [&query](std::shared_ptr<GenQuery> genQuery) {
1216         query = genQuery;
1217     };
1218     auto evt = std::make_unique<MakeQueryEvent>(storeInfo, memo, columns, asyncCallback);
1219     EventCenter::GetInstance().PostEvent(std::move(evt));
1220     if (query == nullptr) {
1221         ZLOGE("query is null, storeId:%{public}s,", Anonymous::Change(storeId).c_str());
1222         return { E_ERROR, {} };
1223     }
1224     auto [status, cursor] = PreShare(storeInfo, *query);
1225     if (status != GeneralError::E_OK || cursor == nullptr) {
1226         ZLOGE("PreShare fail, storeId:%{public}s, status:%{public}d", Anonymous::Change(storeId).c_str(), status);
1227         return { E_ERROR, {} };
1228     }
1229     auto valueBuckets = ConvertCursor(cursor);
1230     Results results;
1231     for (auto &valueBucket : valueBuckets) {
1232         NativeRdb::ValueObject object;
1233         if (!valueBucket.GetObject(DistributedRdb::Field::SHARING_RESOURCE_FIELD, object)) {
1234             continue;
1235         }
1236         std::string shareRes;
1237         if (object.GetString(shareRes) != E_OK) {
1238             continue;
1239         }
1240         Share(shareRes, participants, results);
1241     }
1242     return { SUCCESS, std::move(valueBuckets) };
1243 }
1244 
ConvertCursor(std::shared_ptr<Cursor> cursor) const1245 std::vector<NativeRdb::ValuesBucket> CloudServiceImpl::ConvertCursor(std::shared_ptr<Cursor> cursor) const
1246 {
1247     std::vector<NativeRdb::ValuesBucket> valueBuckets;
1248     int32_t count = cursor->GetCount();
1249     valueBuckets.reserve(count);
1250     auto err = cursor->MoveToFirst();
1251     while (err == E_OK && count > 0) {
1252         VBucket entry;
1253         err = cursor->GetEntry(entry);
1254         if (err != E_OK) {
1255             break;
1256         }
1257         NativeRdb::ValuesBucket bucket;
1258         for (auto &[key, value] : entry) {
1259             NativeRdb::ValueObject object;
1260             DistributedData::Convert(std::move(value), object.value);
1261             bucket.values_.insert_or_assign(key, std::move(object));
1262         }
1263         valueBuckets.emplace_back(std::move(bucket));
1264         err = cursor->MoveToNext();
1265         count--;
1266     }
1267     return valueBuckets;
1268 }
1269 
GetHapInfo(uint32_t tokenId)1270 CloudServiceImpl::HapInfo CloudServiceImpl::GetHapInfo(uint32_t tokenId)
1271 {
1272     HapTokenInfo tokenInfo;
1273     int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
1274     if (errCode != RET_SUCCESS) {
1275         ZLOGE("GetHapTokenInfo error:%{public}d, tokenId:0x%{public}x", errCode, tokenId);
1276         return { INVALID_USER_ID, -1, "" };
1277     }
1278     return { tokenInfo.userID, tokenInfo.instIndex, tokenInfo.bundleName };
1279 }
1280 
GetDfxFaultType(CloudSyncScene scene)1281 std::string CloudServiceImpl::GetDfxFaultType(CloudSyncScene scene)
1282 {
1283     switch (scene) {
1284         case CloudSyncScene::ENABLE_CLOUD:
1285             return FT_ENABLE_CLOUD;
1286         case CloudSyncScene::DISABLE_CLOUD:
1287             return FT_DISABLE_CLOUD;
1288         case CloudSyncScene::SWITCH_ON:
1289             return FT_SWITCH_ON;
1290         case CloudSyncScene::SWITCH_OFF:
1291             return FT_SWITCH_OFF;
1292         case CloudSyncScene::QUERY_SYNC_INFO:
1293             return FT_QUERY_INFO;
1294         case CloudSyncScene::USER_CHANGE:
1295             return FT_USER_CHANGE;
1296         case CloudSyncScene::USER_UNLOCK:
1297             return FT_USER_UNLOCK;
1298         case CloudSyncScene::NETWORK_RECOVERY:
1299             return FT_NETWORK_RECOVERY;
1300         case CloudSyncScene::SERVICE_INIT:
1301             return FT_SERVICE_INIT;
1302         default:
1303             return FT_SYNC_TASK;
1304     }
1305 }
1306 
Share(const std::string & sharingRes,const Participants & participants,Results & results)1307 int32_t CloudServiceImpl::Share(const std::string &sharingRes, const Participants &participants, Results &results)
1308 {
1309     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1310     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1311     if (hapInfo.bundleName.empty()) {
1312         ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str());
1313         return E_ERROR;
1314     }
1315     RadarReporter radar(EventName::CLOUD_SHARING_BEHAVIOR, BizScene::SHARE, hapInfo.bundleName.c_str(), __FUNCTION__);
1316     auto instance = GetSharingHandle(hapInfo);
1317     if (instance == nullptr) {
1318         radar = CenterCode::NOT_SUPPORT + SharingCenter::SHARING_ERR_OFFSET;
1319         return NOT_SUPPORT;
1320     }
1321     results = instance->Share(hapInfo.user, hapInfo.bundleName, sharingRes, Convert(participants));
1322     int32_t status = std::get<0>(results);
1323     radar = (status == CenterCode::SUCCESS) ? CenterCode::SUCCESS : (status + SharingCenter::SHARING_ERR_OFFSET);
1324     ZLOGD("status:%{public}d", status);
1325     return Convert(static_cast<CenterCode>(status));
1326 }
1327 
Unshare(const std::string & sharingRes,const Participants & participants,Results & results)1328 int32_t CloudServiceImpl::Unshare(const std::string &sharingRes, const Participants &participants, Results &results)
1329 {
1330     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1331     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1332     if (hapInfo.bundleName.empty()) {
1333         ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str());
1334         return E_ERROR;
1335     }
1336     RadarReporter radar(EventName::CLOUD_SHARING_BEHAVIOR, BizScene::UNSHARE, hapInfo.bundleName.c_str(), __FUNCTION__);
1337     auto instance = GetSharingHandle(hapInfo);
1338     if (instance == nullptr) {
1339         radar = CenterCode::NOT_SUPPORT + SharingCenter::SHARING_ERR_OFFSET;
1340         return NOT_SUPPORT;
1341     }
1342     results = instance->Unshare(hapInfo.user, hapInfo.bundleName, sharingRes, Convert(participants));
1343     int32_t status = std::get<0>(results);
1344     radar = (status == CenterCode::SUCCESS) ? CenterCode::SUCCESS : (status + SharingCenter::SHARING_ERR_OFFSET);
1345     ZLOGD("status:%{public}d", status);
1346     return Convert(static_cast<CenterCode>(status));
1347 }
1348 
Exit(const std::string & sharingRes,std::pair<int32_t,std::string> & result)1349 int32_t CloudServiceImpl::Exit(const std::string &sharingRes, std::pair<int32_t, std::string> &result)
1350 {
1351     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1352     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1353     if (hapInfo.bundleName.empty()) {
1354         ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str());
1355         return E_ERROR;
1356     }
1357     RadarReporter radar(
1358         EventName::CLOUD_SHARING_BEHAVIOR, BizScene::EXIT_SHARING, hapInfo.bundleName.c_str(), __FUNCTION__);
1359     auto instance = GetSharingHandle(hapInfo);
1360     if (instance == nullptr) {
1361         radar = CenterCode::NOT_SUPPORT + SharingCenter::SHARING_ERR_OFFSET;
1362         return NOT_SUPPORT;
1363     }
1364     result = instance->Exit(hapInfo.user, hapInfo.bundleName, sharingRes);
1365     int32_t status = result.first;
1366     radar = (status == CenterCode::SUCCESS) ? CenterCode::SUCCESS : (status + SharingCenter::SHARING_ERR_OFFSET);
1367     ZLOGD("status:%{public}d", status);
1368     return Convert(static_cast<CenterCode>(status));
1369 }
1370 
ChangePrivilege(const std::string & sharingRes,const Participants & participants,Results & results)1371 int32_t CloudServiceImpl::ChangePrivilege(const std::string &sharingRes, const Participants &participants,
1372     Results &results)
1373 {
1374     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1375     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1376     if (hapInfo.bundleName.empty()) {
1377         ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str());
1378         return E_ERROR;
1379     }
1380     RadarReporter radar(
1381         EventName::CLOUD_SHARING_BEHAVIOR, BizScene::CHANGE_PRIVILEGE, hapInfo.bundleName.c_str(), __FUNCTION__);
1382     auto instance = GetSharingHandle(hapInfo);
1383     if (instance == nullptr) {
1384         radar = CenterCode::NOT_SUPPORT + SharingCenter::SHARING_ERR_OFFSET;
1385         return NOT_SUPPORT;
1386     }
1387     results = instance->ChangePrivilege(hapInfo.user, hapInfo.bundleName, sharingRes, Convert(participants));
1388     int32_t status = std::get<0>(results);
1389     radar = (status == CenterCode::SUCCESS) ? CenterCode::SUCCESS : (status + SharingCenter::SHARING_ERR_OFFSET);
1390     ZLOGD("status:%{public}d", status);
1391     return Convert(static_cast<CenterCode>(status));
1392 }
1393 
Query(const std::string & sharingRes,QueryResults & results)1394 int32_t CloudServiceImpl::Query(const std::string &sharingRes, QueryResults &results)
1395 {
1396     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1397     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1398     if (hapInfo.bundleName.empty()) {
1399         ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str());
1400         return E_ERROR;
1401     }
1402     auto instance = GetSharingHandle(hapInfo);
1403     if (instance == nullptr) {
1404         return NOT_SUPPORT;
1405     }
1406     auto queryResults = instance->Query(hapInfo.user, hapInfo.bundleName, sharingRes);
1407     results = Convert(queryResults);
1408     int32_t status = std::get<0>(queryResults);
1409     ZLOGD("status:%{public}d", status);
1410     return Convert(static_cast<CenterCode>(status));
1411 }
1412 
QueryByInvitation(const std::string & invitation,QueryResults & results)1413 int32_t CloudServiceImpl::QueryByInvitation(const std::string &invitation, QueryResults &results)
1414 {
1415     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1416     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1417     if (hapInfo.bundleName.empty()) {
1418         ZLOGE("bundleName is empty, invitation:%{public}s", Anonymous::Change(invitation).c_str());
1419         return E_ERROR;
1420     }
1421     auto instance = GetSharingHandle(hapInfo);
1422     if (instance == nullptr) {
1423         return NOT_SUPPORT;
1424     }
1425     auto queryResults = instance->QueryByInvitation(hapInfo.user, hapInfo.bundleName, invitation);
1426     results = Convert(queryResults);
1427     int32_t status = std::get<0>(queryResults);
1428     ZLOGD("status:%{public}d", status);
1429     return Convert(static_cast<CenterCode>(status));
1430 }
1431 
ConfirmInvitation(const std::string & invitation,int32_t confirmation,std::tuple<int32_t,std::string,std::string> & result)1432 int32_t CloudServiceImpl::ConfirmInvitation(const std::string &invitation, int32_t confirmation,
1433     std::tuple<int32_t, std::string, std::string> &result)
1434 {
1435     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1436     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1437     if (hapInfo.bundleName.empty()) {
1438         ZLOGE("bundleName is empty, invitation:%{public}s, confirmation:%{public}d",
1439             Anonymous::Change(invitation).c_str(), confirmation);
1440         return E_ERROR;
1441     }
1442     RadarReporter radar(
1443         EventName::CLOUD_SHARING_BEHAVIOR, BizScene::CONFIRM_INVITATION, hapInfo.bundleName.c_str(), __FUNCTION__);
1444     auto instance = GetSharingHandle(hapInfo);
1445     if (instance == nullptr) {
1446         radar = CenterCode::NOT_SUPPORT + SharingCenter::SHARING_ERR_OFFSET;
1447         return NOT_SUPPORT;
1448     }
1449     result = instance->ConfirmInvitation(hapInfo.user, hapInfo.bundleName, invitation, confirmation);
1450     int32_t status = std::get<0>(result);
1451     radar = (status == CenterCode::SUCCESS) ? CenterCode::SUCCESS : (status + SharingCenter::SHARING_ERR_OFFSET);
1452     ZLOGD("status:%{public}d", status);
1453     return Convert(static_cast<CenterCode>(status));
1454 }
1455 
ChangeConfirmation(const std::string & sharingRes,int32_t confirmation,std::pair<int32_t,std::string> & result)1456 int32_t CloudServiceImpl::ChangeConfirmation(const std::string &sharingRes, int32_t confirmation,
1457     std::pair<int32_t, std::string> &result)
1458 {
1459     XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY);
1460     auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID());
1461     if (hapInfo.bundleName.empty()) {
1462         ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str());
1463         return E_ERROR;
1464     }
1465     RadarReporter radar(
1466         EventName::CLOUD_SHARING_BEHAVIOR, BizScene::CHANGE_CONFIRMATION, hapInfo.bundleName.c_str(), __FUNCTION__);
1467     auto instance = GetSharingHandle(hapInfo);
1468     if (instance == nullptr) {
1469         radar = CenterCode::NOT_SUPPORT + SharingCenter::SHARING_ERR_OFFSET;
1470         return NOT_SUPPORT;
1471     }
1472     result = instance->ChangeConfirmation(hapInfo.user, hapInfo.bundleName, sharingRes, confirmation);
1473     int32_t status = result.first;
1474     radar = (status == CenterCode::SUCCESS) ? CenterCode::SUCCESS : (status + SharingCenter::SHARING_ERR_OFFSET);
1475     ZLOGD("status:%{public}d", status);
1476     return Convert(static_cast<CenterCode>(status));
1477 }
1478 
GetSharingHandle(const HapInfo & hapInfo)1479 std::shared_ptr<SharingCenter> CloudServiceImpl::GetSharingHandle(const HapInfo &hapInfo)
1480 {
1481     auto instance = CloudServer::GetInstance();
1482     if (instance == nullptr) {
1483         return nullptr;
1484     }
1485     auto handle = instance->ConnectSharingCenter(hapInfo.user, hapInfo.bundleName);
1486     return handle;
1487 }
1488 
GenSubTask(Task task,int32_t user)1489 ExecutorPool::Task CloudServiceImpl::GenSubTask(Task task, int32_t user)
1490 {
1491     return [this, user, work = std::move(task)]() {
1492         {
1493             std::lock_guard<decltype(mutex_)> lock(mutex_);
1494             subTask_ = ExecutorPool::INVALID_TASK_ID;
1495         }
1496         auto [status, cloudInfo] = GetCloudInfoFromMeta(user);
1497         if (status != SUCCESS || !cloudInfo.enableCloud || cloudInfo.IsAllSwitchOff()) {
1498             ZLOGW("[sub task] all switch off, status:%{public}d user:%{public}d enableCloud:%{public}d",
1499                 status, user, cloudInfo.enableCloud);
1500             return;
1501         }
1502         work();
1503     };
1504 }
1505 
InitSubTask(const Subscription & sub,uint64_t minInterval)1506 void CloudServiceImpl::InitSubTask(const Subscription &sub, uint64_t minInterval)
1507 {
1508     auto expire = sub.GetMinExpireTime();
1509     if (expire == INVALID_SUB_TIME) {
1510         return;
1511     }
1512     auto executor = executor_;
1513     if (executor == nullptr) {
1514         return;
1515     }
1516     ZLOGI("Subscription Info, subTask:%{public}" PRIu64 ", user:%{public}d", subTask_, sub.userId);
1517     expire = expire - TIME_BEFORE_SUB; // before 12 hours
1518     auto now = static_cast<uint64_t>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
1519     Duration delay = milliseconds(std::max(expire > now ? expire - now : 0, minInterval));
1520     std::lock_guard<decltype(mutex_)> lock(mutex_);
1521     if (subTask_ != ExecutorPool::INVALID_TASK_ID) {
1522         if (expire < expireTime_) {
1523             subTask_ = executor->Reset(subTask_, delay);
1524             expireTime_ = expire > now ? expire : now;
1525         }
1526         return;
1527     }
1528     subTask_ = executor->Schedule(delay, GenSubTask(GenTask(0, sub.userId, CloudSyncScene::SERVICE_INIT), sub.userId));
1529     expireTime_ = expire > now ? expire : now;
1530 }
1531 
SetCloudStrategy(Strategy strategy,const std::vector<CommonType::Value> & values)1532 int32_t CloudServiceImpl::SetCloudStrategy(Strategy strategy, const std::vector<CommonType::Value> &values)
1533 {
1534     if (strategy >= Strategy::STRATEGY_BUTT) {
1535         ZLOGE("invalid strategy:%{public}d, size:%{public}zu", strategy, values.size());
1536         return INVALID_ARGUMENT;
1537     }
1538     auto tokenId = IPCSkeleton::GetCallingTokenID();
1539     auto hapInfo = GetHapInfo(tokenId);
1540     if (hapInfo.bundleName.empty() || hapInfo.user == INVALID_USER_ID || hapInfo.user == 0) {
1541         ZLOGE("invalid, user:%{public}d, bundleName:%{public}s, strategy:%{public}d, values size:%{public}zu",
1542             hapInfo.user, hapInfo.bundleName.c_str(), strategy, values.size());
1543         return ERROR;
1544     }
1545     return STRATEGY_SAVERS[strategy](values, hapInfo);
1546 }
1547 
SaveNetworkStrategy(const std::vector<CommonType::Value> & values,const HapInfo & hapInfo)1548 int32_t CloudServiceImpl::SaveNetworkStrategy(const std::vector<CommonType::Value> &values, const HapInfo &hapInfo)
1549 {
1550     NetworkSyncStrategy::StrategyInfo info;
1551     info.strategy = 0;
1552     info.user = hapInfo.user;
1553     info.bundleName = hapInfo.bundleName;
1554     if (values.empty()) {
1555         return MetaDataManager::GetInstance().DelMeta(info.GetKey(), true) ? SUCCESS : ERROR;
1556     }
1557     for (auto &value : values) {
1558         auto strategy = std::get_if<int64_t>(&value);
1559         if (strategy != nullptr) {
1560             info.strategy |= static_cast<uint32_t>(*strategy);
1561         }
1562     }
1563     NetworkSyncStrategy::StrategyInfo oldInfo;
1564     MetaDataManager::GetInstance().LoadMeta(info.GetKey(), oldInfo, true);
1565     ZLOGI("Strategy[user:%{public}d,bundleName:%{public}s] to [%{public}d] from [%{public}d]",
1566           info.user, info.bundleName.c_str(), info.strategy, oldInfo.strategy);
1567     return MetaDataManager::GetInstance().SaveMeta(info.GetKey(), info, true) ? SUCCESS : ERROR;
1568 }
1569 
OnScreenUnlocked(int32_t user)1570 int32_t CloudServiceImpl::OnScreenUnlocked(int32_t user)
1571 {
1572     syncManager_.OnScreenUnlocked(user);
1573     return E_OK;
1574 }
1575 
AssembleLastResults(const std::vector<Database> & databases,const std::map<std::string,CloudLastSyncInfo> & lastSyncInfos)1576 QueryLastResults CloudServiceImpl::AssembleLastResults(const std::vector<Database> &databases,
1577     const std::map<std::string, CloudLastSyncInfo> &lastSyncInfos)
1578 {
1579     QueryLastResults results;
1580     for (const auto &database : databases) {
1581         auto iter = lastSyncInfos.find(database.name);
1582         if (iter != lastSyncInfos.end()) {
1583             CloudSyncInfo syncInfo = { .startTime = iter->second.startTime, .finishTime = iter->second.finishTime,
1584                                        .code = iter->second.code, .syncStatus = iter->second.syncStatus };
1585             results.insert({ database.alias, std::move(syncInfo) });
1586         }
1587     }
1588     return results;
1589 }
1590 } // namespace OHOS::CloudData