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