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