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