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