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