• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #define LOG_TAG "KVDBServiceImpl"
16 #include "kvdb_service_impl.h"
17 
18 #include <chrono>
19 #include <cinttypes>
20 
21 #include "accesstoken_kit.h"
22 #include "account/account_delegate.h"
23 #include "backup_manager.h"
24 #include "checker/checker_manager.h"
25 #include "communication_provider.h"
26 #include "crypto_manager.h"
27 #include "device_manager_adapter.h"
28 #include "directory_manager.h"
29 #include "eventcenter/event_center.h"
30 #include "ipc_skeleton.h"
31 #include "log_print.h"
32 #include "matrix_event.h"
33 #include "metadata/appid_meta_data.h"
34 #include "metadata/meta_data_manager.h"
35 #include "permit_delegate.h"
36 #include "query_helper.h"
37 #include "upgrade.h"
38 #include "utils/anonymous.h"
39 #include "utils/constant.h"
40 #include "utils/converter.h"
41 #include "utils/crypto.h"
42 namespace OHOS::DistributedKv {
43 using namespace OHOS::DistributedData;
44 using namespace OHOS::AppDistributedKv;
45 using namespace OHOS::Security::AccessToken;
46 using DMAdapter = DistributedData::DeviceManagerAdapter;
47 __attribute__((used)) KVDBServiceImpl::Factory KVDBServiceImpl::factory_;
Factory()48 KVDBServiceImpl::Factory::Factory()
49 {
50     FeatureSystem::GetInstance().RegisterCreator("kv_store", []() { return std::make_shared<KVDBServiceImpl>(); });
51 }
52 
~Factory()53 KVDBServiceImpl::Factory::~Factory()
54 {
55 }
56 
KVDBServiceImpl()57 KVDBServiceImpl::KVDBServiceImpl()
58 {
59     EventCenter::GetInstance().Subscribe(DeviceMatrix::MATRIX_META_FINISHED, [this](const Event &event) {
60         auto &matrixEvent = static_cast<const MatrixEvent &>(event);
61         auto deviceId = matrixEvent.GetDeviceId();
62         RefCount refCount([deviceId] { DMAdapter::GetInstance().NotifyReadyEvent(deviceId); });
63         std::vector<StoreMetaData> metaData;
64         auto prefix = StoreMetaData::GetPrefix({ DMAdapter::GetInstance().GetLocalDevice().uuid });
65         if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) {
66             ZLOGE("load meta failed!");
67             return;
68         }
69         auto mask = matrixEvent.GetMask();
70         for (const auto &data : metaData) {
71             StoreMetaDataLocal localMetaData;
72             MetaDataManager::GetInstance().LoadMeta(data.GetKeyLocal(), localMetaData, true);
73             if (!localMetaData.HasPolicy(PolicyType::IMMEDIATE_SYNC_ON_ONLINE)) {
74                 continue;
75             }
76 
77             auto code = DeviceMatrix::GetInstance().GetCode(data);
78             if ((mask & code) != code) {
79                 continue;
80             }
81 
82             auto policy = localMetaData.GetPolicy(PolicyType::IMMEDIATE_SYNC_ON_ONLINE);
83             SyncInfo syncInfo;
84             syncInfo.mode = PUSH_PULL;
85             syncInfo.delay = 0;
86             syncInfo.devices = { deviceId };
87             if (policy.IsValueEffect()) {
88                 syncInfo.delay = policy.valueUint;
89             }
90             ZLOGI("[online] appId:%{public}s, storeId:%{public}s", data.bundleName.c_str(), data.storeId.c_str());
91             auto delay = GetSyncDelayTime(syncInfo.delay, { data.storeId });
92             KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(data.tokenId), delay,
93                 std::bind(&KVDBServiceImpl::DoSync, this, data, syncInfo, std::placeholders::_1, ACTION_SYNC),
94                 std::bind(&KVDBServiceImpl::DoComplete, this, data, syncInfo, refCount, std::placeholders::_1));
95         }
96     });
97 }
98 
~KVDBServiceImpl()99 KVDBServiceImpl::~KVDBServiceImpl()
100 {
101 }
102 
GetStoreIds(const AppId & appId,std::vector<StoreId> & storeIds)103 Status KVDBServiceImpl::GetStoreIds(const AppId &appId, std::vector<StoreId> &storeIds)
104 {
105     std::vector<StoreMetaData> metaData;
106     auto user = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID());
107     auto deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
108     auto prefix = StoreMetaData::GetPrefix({ deviceId, std::to_string(user), "default", appId.appId });
109     auto instanceId = GetInstIndex(IPCSkeleton::GetCallingTokenID(), appId);
110     MetaDataManager::GetInstance().LoadMeta(prefix, metaData);
111     for (auto &item : metaData) {
112         if (item.storeType > KvStoreType::MULTI_VERSION || item.instanceId != instanceId) {
113             continue;
114         }
115         storeIds.push_back({ item.storeId });
116     }
117     ZLOGD("appId:%{public}s store size:%{public}zu", appId.appId.c_str(), storeIds.size());
118     return SUCCESS;
119 }
120 
Delete(const AppId & appId,const StoreId & storeId)121 Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId)
122 {
123     StoreMetaData metaData = GetStoreMetaData(appId, storeId);
124     if (metaData.instanceId < 0) {
125         return ILLEGAL_STATE;
126     }
127 
128     auto tokenId = IPCSkeleton::GetCallingTokenID();
129     syncAgents_.ComputeIfPresent(tokenId, [&appId, &storeId](auto &key, SyncAgent &syncAgent) {
130         if (syncAgent.pid_ != IPCSkeleton::GetCallingPid()) {
131             ZLOGW("agent already changed! old pid:%{public}d new pid:%{public}d appId:%{public}s",
132                 IPCSkeleton::GetCallingPid(), syncAgent.pid_, appId.appId.c_str());
133             return true;
134         }
135         syncAgent.delayTimes_.erase(storeId);
136         syncAgent.observers_.erase(storeId);
137         return true;
138     });
139     MetaDataManager::GetInstance().DelMeta(metaData.GetKey());
140     MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true);
141     MetaDataManager::GetInstance().DelMeta(metaData.GetStrategyKey());
142     MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true);
143     PermitDelegate::GetInstance().DelCache(metaData.GetKey());
144     storeCache_.CloseStore(tokenId, storeId);
145     ZLOGD("appId:%{public}s storeId:%{public}s instanceId:%{public}d", appId.appId.c_str(), storeId.storeId.c_str(),
146         metaData.instanceId);
147     return SUCCESS;
148 }
149 
Sync(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)150 Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo)
151 {
152     StoreMetaData metaData = GetStoreMetaData(appId, storeId);
153     MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData);
154     auto delay = GetSyncDelayTime(syncInfo.delay, storeId);
155     if (metaData.isAutoSync && syncInfo.seqId == std::numeric_limits<uint64_t>::max()) {
156         DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::GetInstance().GetCode(metaData));
157         StoreMetaDataLocal localMeta;
158         MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), localMeta, true);
159         if (!localMeta.HasPolicy(IMMEDIATE_SYNC_ON_CHANGE)) {
160             ZLOGW("appId:%{public}s storeId:%{public}s no IMMEDIATE_SYNC_ON_CHANGE ", appId.appId.c_str(),
161                 storeId.storeId.c_str());
162             return Status::SUCCESS;
163         }
164     }
165     return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay,
166         std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1, ACTION_SYNC),
167         std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1));
168 }
169 
RegisterSyncCallback(const AppId & appId,sptr<IKvStoreSyncCallback> callback)170 Status KVDBServiceImpl::RegisterSyncCallback(const AppId &appId, sptr<IKvStoreSyncCallback> callback)
171 {
172     auto tokenId = IPCSkeleton::GetCallingTokenID();
173     syncAgents_.Compute(tokenId, [&appId, callback](const auto &, SyncAgent &value) {
174         if (value.pid_ != IPCSkeleton::GetCallingPid()) {
175             value.ReInit(IPCSkeleton::GetCallingPid(), appId);
176         }
177         value.callback_ = callback;
178         return true;
179     });
180     return SUCCESS;
181 }
182 
UnregisterSyncCallback(const AppId & appId)183 Status KVDBServiceImpl::UnregisterSyncCallback(const AppId &appId)
184 {
185     syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [&appId](const auto &key, SyncAgent &value) {
186         if (value.pid_ != IPCSkeleton::GetCallingPid()) {
187             ZLOGW("agent already changed! old pid:%{public}d, new pid:%{public}d, appId:%{public}s",
188                 IPCSkeleton::GetCallingPid(), value.pid_, appId.appId.c_str());
189             return true;
190         }
191         value.callback_ = nullptr;
192         return true;
193     });
194     return SUCCESS;
195 }
196 
SetSyncParam(const AppId & appId,const StoreId & storeId,const KvSyncParam & syncParam)197 Status KVDBServiceImpl::SetSyncParam(const AppId &appId, const StoreId &storeId, const KvSyncParam &syncParam)
198 {
199     if (syncParam.allowedDelayMs > 0 && syncParam.allowedDelayMs < KvStoreSyncManager::SYNC_MIN_DELAY_MS) {
200         return Status::INVALID_ARGUMENT;
201     }
202     if (syncParam.allowedDelayMs > KvStoreSyncManager::SYNC_MAX_DELAY_MS) {
203         return Status::INVALID_ARGUMENT;
204     }
205     auto tokenId = IPCSkeleton::GetCallingTokenID();
206     syncAgents_.Compute(tokenId, [&appId, &storeId, &syncParam](auto &key, SyncAgent &value) {
207         if (value.pid_ != IPCSkeleton::GetCallingPid()) {
208             value.ReInit(IPCSkeleton::GetCallingPid(), appId);
209         }
210         value.delayTimes_[storeId] = syncParam.allowedDelayMs;
211         return true;
212     });
213     return SUCCESS;
214 }
215 
GetSyncParam(const AppId & appId,const StoreId & storeId,KvSyncParam & syncParam)216 Status KVDBServiceImpl::GetSyncParam(const AppId &appId, const StoreId &storeId, KvSyncParam &syncParam)
217 {
218     syncParam.allowedDelayMs = 0;
219     auto tokenId = IPCSkeleton::GetCallingTokenID();
220     syncAgents_.ComputeIfPresent(tokenId, [&appId, &storeId, &syncParam](auto &key, SyncAgent &value) {
221         if (value.pid_ != IPCSkeleton::GetCallingPid()) {
222             ZLOGW("agent already changed! old pid:%{public}d, new pid:%{public}d, appId:%{public}s",
223                 IPCSkeleton::GetCallingPid(), value.pid_, appId.appId.c_str());
224             return true;
225         }
226 
227         auto it = value.delayTimes_.find(storeId);
228         if (it != value.delayTimes_.end()) {
229             syncParam.allowedDelayMs = it->second;
230         }
231         return true;
232     });
233     return SUCCESS;
234 }
235 
EnableCapability(const AppId & appId,const StoreId & storeId)236 Status KVDBServiceImpl::EnableCapability(const AppId &appId, const StoreId &storeId)
237 {
238     StrategyMeta strategyMeta = GetStrategyMeta(appId, storeId);
239     if (strategyMeta.instanceId < 0) {
240         return ILLEGAL_STATE;
241     }
242     MetaDataManager::GetInstance().LoadMeta(strategyMeta.GetKey(), strategyMeta);
243     strategyMeta.capabilityEnabled = true;
244     MetaDataManager::GetInstance().SaveMeta(strategyMeta.GetKey(), strategyMeta);
245     return SUCCESS;
246 }
247 
DisableCapability(const AppId & appId,const StoreId & storeId)248 Status KVDBServiceImpl::DisableCapability(const AppId &appId, const StoreId &storeId)
249 {
250     StrategyMeta strategyMeta = GetStrategyMeta(appId, storeId);
251     if (strategyMeta.instanceId < 0) {
252         return ILLEGAL_STATE;
253     }
254     MetaDataManager::GetInstance().LoadMeta(strategyMeta.GetKey(), strategyMeta);
255     strategyMeta.capabilityEnabled = false;
256     MetaDataManager::GetInstance().SaveMeta(strategyMeta.GetKey(), strategyMeta);
257     return SUCCESS;
258 }
259 
SetCapability(const AppId & appId,const StoreId & storeId,const std::vector<std::string> & local,const std::vector<std::string> & remote)260 Status KVDBServiceImpl::SetCapability(const AppId &appId, const StoreId &storeId,
261     const std::vector<std::string> &local, const std::vector<std::string> &remote)
262 {
263     StrategyMeta strategy = GetStrategyMeta(appId, storeId);
264     if (strategy.instanceId < 0) {
265         return ILLEGAL_STATE;
266     }
267     MetaDataManager::GetInstance().LoadMeta(strategy.GetKey(), strategy);
268     strategy.capabilityRange.localLabel = local;
269     strategy.capabilityRange.remoteLabel = remote;
270     MetaDataManager::GetInstance().SaveMeta(strategy.GetKey(), strategy);
271     return SUCCESS;
272 }
273 
AddSubscribeInfo(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)274 Status KVDBServiceImpl::AddSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo)
275 {
276     StoreMetaData metaData = GetStoreMetaData(appId, storeId);
277     MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData);
278     auto delay = GetSyncDelayTime(syncInfo.delay, storeId);
279     return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay,
280         std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1, ACTION_SUBSCRIBE),
281         std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1));
282 }
283 
RmvSubscribeInfo(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)284 Status KVDBServiceImpl::RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo)
285 {
286     StoreMetaData metaData = GetStoreMetaData(appId, storeId);
287     MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData);
288     auto delay = GetSyncDelayTime(syncInfo.delay, storeId);
289     return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay,
290         std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1, ACTION_UNSUBSCRIBE),
291         std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1));
292 }
293 
Subscribe(const AppId & appId,const StoreId & storeId,sptr<IKvStoreObserver> observer)294 Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, sptr<IKvStoreObserver> observer)
295 {
296     auto tokenId = IPCSkeleton::GetCallingTokenID();
297     ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(), storeId.storeId.c_str(),
298         tokenId);
299     syncAgents_.Compute(tokenId, [&appId, &storeId, &observer](auto &key, SyncAgent &value) {
300         if (value.pid_ != IPCSkeleton::GetCallingPid()) {
301             value.ReInit(IPCSkeleton::GetCallingPid(), appId);
302         }
303         auto it = value.observers_.find(storeId);
304         if (it == value.observers_.end()) {
305             value.observers_[storeId] = std::make_shared<StoreCache::Observers>();
306         }
307         value.observers_[storeId]->insert(observer);
308         return true;
309     });
310     auto observers = GetObservers(tokenId, storeId);
311     storeCache_.SetObserver(tokenId, storeId, observers);
312     return SUCCESS;
313 }
314 
Unsubscribe(const AppId & appId,const StoreId & storeId,sptr<IKvStoreObserver> observer)315 Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, sptr<IKvStoreObserver> observer)
316 {
317     auto tokenId = IPCSkeleton::GetCallingTokenID();
318     ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(), storeId.storeId.c_str(),
319         tokenId);
320     syncAgents_.ComputeIfPresent(tokenId, [&appId, &storeId, &observer](auto &key, SyncAgent &value) {
321         if (value.pid_ != IPCSkeleton::GetCallingPid()) {
322             ZLOGW("agent already changed! old pid:%{public}d new pid:%{public}d appId:%{public}s",
323                 IPCSkeleton::GetCallingPid(), value.pid_, appId.appId.c_str());
324             return true;
325         }
326         auto it = value.observers_.find(storeId);
327         if (it != value.observers_.end()) {
328             it->second->erase(observer);
329         }
330         return true;
331     });
332     return SUCCESS;
333 }
334 
GetBackupPassword(const AppId & appId,const StoreId & storeId,std::vector<uint8_t> & password)335 Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector<uint8_t> &password)
336 {
337     StoreMetaData metaData = GetStoreMetaData(appId, storeId);
338     return (BackupManager::GetInstance().GetPassWord(metaData, password)) ? SUCCESS : ERROR;
339 }
340 
GetLocalDevice()341 KVDBService::DevBrief KVDBServiceImpl::GetLocalDevice()
342 {
343     DevBrief brief;
344     CheckerManager::StoreInfo storeInfo;
345     storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
346     storeInfo.uid = IPCSkeleton::GetCallingPid();
347     auto appId = CheckerManager::GetInstance().GetAppId(storeInfo);
348     auto device = DMAdapter::GetInstance().GetLocalDevice();
349     brief.networkId = std::move(device.networkId);
350     brief.uuid = Crypto::Sha256(appId + "_" + device.uuid);
351     return brief;
352 }
353 
GetRemoteDevices()354 std::vector<KVDBService::DevBrief> KVDBServiceImpl::GetRemoteDevices()
355 {
356     std::vector<DevBrief> briefs;
357     CheckerManager::StoreInfo storeInfo;
358     storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
359     storeInfo.uid = IPCSkeleton::GetCallingPid();
360     auto appId = CheckerManager::GetInstance().GetAppId(storeInfo);
361     auto devices = DMAdapter::GetInstance().GetRemoteDevices();
362     for (const auto &device : devices) {
363         DevBrief brief;
364         brief.networkId = std::move(device.networkId);
365         brief.uuid = Crypto::Sha256(appId + "_" + device.uuid);
366         briefs.push_back(std::move(brief));
367     }
368     return briefs;
369 }
370 
BeforeCreate(const AppId & appId,const StoreId & storeId,const Options & options)371 Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, const Options &options)
372 {
373     ZLOGD("appId:%{public}s storeId:%{public}s to export data", appId.appId.c_str(), storeId.storeId.c_str());
374     StoreMetaData meta = GetStoreMetaData(appId, storeId);
375     AddOptions(options, meta);
376 
377     StoreMetaData old;
378     auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old);
379     if (!isCreated) {
380         return SUCCESS;
381     }
382     if (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) ||
383         old.area != meta.area || !options.persistent) {
384         ZLOGE("meta appId:%{public}s storeId:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
385               "area:%{public}d->%{public}d persistent:%{public}d",
386             appId.appId.c_str(), storeId.storeId.c_str(), old.storeType, meta.storeType, old.isEncrypt, meta.isEncrypt,
387             old.area, meta.area, options.persistent);
388         return Status::STORE_META_CHANGED;
389     }
390 
391     auto dbStatus = DBStatus::OK;
392     if (old != meta) {
393         dbStatus = Upgrade::GetInstance().ExportStore(old, meta);
394     }
395     return dbStatus == DBStatus::OK ? SUCCESS : DB_ERROR;
396 }
397 
AfterCreate(const AppId & appId,const StoreId & storeId,const Options & options,const std::vector<uint8_t> & password)398 Status KVDBServiceImpl::AfterCreate(const AppId &appId, const StoreId &storeId, const Options &options,
399     const std::vector<uint8_t> &password)
400 {
401     if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) {
402         ZLOGE("failed please check type:%{public}d appId:%{public}s storeId:%{public}s", options.kvStoreType,
403             appId.appId.c_str(), storeId.storeId.c_str());
404         return INVALID_ARGUMENT;
405     }
406 
407     StoreMetaData metaData = GetStoreMetaData(appId, storeId);
408     AddOptions(options, metaData);
409 
410     StoreMetaData oldMeta;
411     auto isCreated = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta);
412     Status status = SUCCESS;
413     if (isCreated && oldMeta != metaData) {
414         auto dbStatus = Upgrade::GetInstance().UpdateStore(oldMeta, metaData, password);
415         ZLOGI("update status:%{public}d appId:%{public}s storeId:%{public}s inst:%{public}d "
416               "type:%{public}d->%{public}d dir:%{public}s",
417             dbStatus, appId.appId.c_str(), storeId.storeId.c_str(), metaData.instanceId, oldMeta.storeType,
418             metaData.storeType, metaData.dataDir.c_str());
419         if (dbStatus != DBStatus::OK) {
420             status = STORE_UPGRADE_FAILED;
421         }
422     }
423 
424     if (!isCreated || oldMeta != metaData) {
425         MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData);
426     }
427     AppIDMetaData appIdMeta;
428     appIdMeta.bundleName = metaData.bundleName;
429     appIdMeta.appId = metaData.appId;
430     MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true);
431     SaveLocalMetaData(options, metaData);
432     Upgrade::GetInstance().UpdatePassword(metaData, password);
433     ZLOGI("appId:%{public}s storeId:%{public}s instanceId:%{public}d type:%{public}d dir:%{public}s",
434         appId.appId.c_str(), storeId.storeId.c_str(), metaData.instanceId, metaData.storeType,
435         metaData.dataDir.c_str());
436     return status;
437 }
438 
OnAppExit(pid_t uid,pid_t pid,uint32_t tokenId,const std::string & appId)439 int32_t KVDBServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &appId)
440 {
441     ZLOGI("pid:%{public}d uid:%{public}d appId:%{public}s", pid, uid, appId.c_str());
442     std::vector<std::string> storeIds;
443     syncAgents_.ComputeIfPresent(tokenId, [pid, &storeIds](auto &, SyncAgent &value) {
444         if (value.pid_ != pid) {
445             return true;
446         }
447 
448         for (auto &[key, value] : value.observers_) {
449             storeIds.push_back(key);
450         }
451         return false;
452     });
453 
454     for (auto &storeId : storeIds) {
455         storeCache_.CloseStore(tokenId, storeId);
456     }
457     return SUCCESS;
458 }
459 
ResolveAutoLaunch(const std::string & identifier,DBLaunchParam & param)460 int32_t KVDBServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaunchParam &param)
461 {
462     ZLOGI("user:%{public}s appId:%{public}s storeId:%{public}s identifier:%{public}s", param.userId.c_str(),
463         param.appId.c_str(), param.storeId.c_str(), Anonymous::Change(identifier).c_str());
464     std::vector<StoreMetaData> metaData;
465     auto prefix = StoreMetaData::GetPrefix({ DMAdapter::GetInstance().GetLocalDevice().uuid, param.userId });
466     if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) {
467         ZLOGE("no store in user:%{public}s", param.userId.c_str());
468         return STORE_NOT_FOUND;
469     }
470 
471     for (const auto &storeMeta : metaData) {
472         auto identifierTag = DBManager::GetKvStoreIdentifier("", storeMeta.appId, storeMeta.storeId, true);
473         if (identifier != identifierTag) {
474             continue;
475         }
476 
477         auto observers = GetObservers(storeMeta.tokenId, storeMeta.storeId);
478         ZLOGD("user:%{public}s appId:%{public}s storeId:%{public}s observers:%{public}zu", storeMeta.user.c_str(),
479             storeMeta.bundleName.c_str(), storeMeta.storeId.c_str(), (observers) ? observers->size() : size_t(0));
480         DBStatus status;
481         storeCache_.GetStore(storeMeta, observers, status);
482     }
483     return SUCCESS;
484 }
OnUserChange(uint32_t code,const std::string & user,const std::string & account)485 int32_t KVDBServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account)
486 {
487     (void)code;
488     (void)user;
489     (void)account;
490     std::vector<int32_t> users;
491     AccountDelegate::GetInstance()->QueryUsers(users);
492     std::set<int32_t> userIds(users.begin(), users.end());
493     storeCache_.CloseExcept(userIds);
494     return SUCCESS;
495 }
496 
OnReady(const std::string & device)497 int32_t KVDBServiceImpl::OnReady(const std::string &device)
498 {
499     return SUCCESS;
500 }
501 
AddOptions(const Options & options,StoreMetaData & metaData)502 void KVDBServiceImpl::AddOptions(const Options &options, StoreMetaData &metaData)
503 {
504     metaData.isAutoSync = options.autoSync;
505     metaData.isBackup = options.backup;
506     metaData.isEncrypt = options.encrypt;
507     metaData.storeType = options.kvStoreType;
508     metaData.securityLevel = options.securityLevel;
509     metaData.area = options.area;
510     metaData.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(metaData));
511     metaData.appType = "harmony";
512     metaData.hapName = options.hapName;
513     metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData);
514     metaData.schema = options.schema;
515     metaData.account = AccountDelegate::GetInstance()->GetCurrentAccountId();
516 }
517 
SaveLocalMetaData(const Options & options,const StoreMetaData & metaData)518 void KVDBServiceImpl::SaveLocalMetaData(const Options &options, const StoreMetaData &metaData)
519 {
520     StoreMetaDataLocal localMetaData;
521     localMetaData.isAutoSync = options.autoSync;
522     localMetaData.isBackup = options.backup;
523     localMetaData.isEncrypt = options.encrypt;
524     localMetaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData);
525     localMetaData.schema = options.schema;
526     for (auto &policy : options.policies) {
527         OHOS::DistributedData::PolicyValue value;
528         value.type = policy.type;
529         value.index = policy.value.index();
530         if (const uint32_t *pval = std::get_if<uint32_t>(&policy.value)) {
531             value.valueUint = *pval;
532         }
533         localMetaData.policies.emplace_back(value);
534     }
535     MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocal(), localMetaData, true);
536 }
537 
GetStoreMetaData(const AppId & appId,const StoreId & storeId)538 StoreMetaData KVDBServiceImpl::GetStoreMetaData(const AppId &appId, const StoreId &storeId)
539 {
540     StoreMetaData metaData;
541     metaData.uid = IPCSkeleton::GetCallingUid();
542     metaData.tokenId = IPCSkeleton::GetCallingTokenID();
543     metaData.instanceId = GetInstIndex(metaData.tokenId, appId);
544     metaData.bundleName = appId.appId;
545     metaData.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
546     metaData.storeId = storeId.storeId;
547     metaData.user = AccountDelegate::GetInstance()->GetDeviceAccountIdByUID(metaData.uid);
548     return metaData;
549 }
550 
GetStrategyMeta(const AppId & appId,const StoreId & storeId)551 StrategyMeta KVDBServiceImpl::GetStrategyMeta(const AppId &appId, const StoreId &storeId)
552 {
553     auto deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid;
554     auto userId = AccountDelegate::GetInstance()->GetDeviceAccountIdByUID(IPCSkeleton::GetCallingUid());
555     auto tokenId = IPCSkeleton::GetCallingTokenID();
556     StrategyMeta strategyMeta(deviceId, userId, appId.appId, storeId.storeId);
557     strategyMeta.instanceId = GetInstIndex(tokenId, appId);
558     return strategyMeta;
559 }
560 
GetInstIndex(uint32_t tokenId,const AppId & appId)561 int32_t KVDBServiceImpl::GetInstIndex(uint32_t tokenId, const AppId &appId)
562 {
563     if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
564         return 0;
565     }
566 
567     HapTokenInfo tokenInfo;
568     tokenInfo.instIndex = -1;
569     int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
570     if (errCode != RET_SUCCESS) {
571         ZLOGE("GetHapTokenInfo error:%{public}d, tokenId:0x%{public}x appId:%{public}s", errCode, tokenId,
572             appId.appId.c_str());
573         return -1;
574     }
575     return tokenInfo.instIndex;
576 }
577 
DoSync(const StoreMetaData & meta,const SyncInfo & info,const SyncEnd & complete,int32_t type)578 Status KVDBServiceImpl::DoSync(const StoreMetaData &meta, const SyncInfo &info, const SyncEnd &complete, int32_t type)
579 {
580     ZLOGD("seqId:0x%{public}" PRIx64 " type:%{public}d remote:%{public}zu appId:%{public}s storeId:%{public}s",
581         info.seqId, type, info.devices.size(), meta.bundleName.c_str(), meta.storeId.c_str());
582     auto uuids = ConvertDevices(info.devices);
583     if (uuids.empty()) {
584         ZLOGW("no device online seqId:0x%{public}" PRIx64 " remote:%{public}zu appId:%{public}s storeId:%{public}s",
585             info.seqId, info.devices.size(), meta.bundleName.c_str(), meta.storeId.c_str());
586         return Status::ERROR;
587     }
588 
589     DistributedDB::DBStatus status;
590     auto observers = GetObservers(meta.tokenId, meta.storeId);
591     auto store = storeCache_.GetStore(meta, observers, status);
592     if (store == nullptr) {
593         ZLOGE("failed! status:%{public}d appId:%{public}s storeId:%{public}s dir:%{public}s", status,
594             meta.bundleName.c_str(), meta.storeId.c_str(), meta.dataDir.c_str());
595         return ConvertDbStatus(status);
596     }
597     bool isSuccess = false;
598     auto dbQuery = QueryHelper::StringToDbQuery(info.query, isSuccess);
599     if (!isSuccess && !info.query.empty()) {
600         ZLOGE("failed DBQuery:%{public}s", Anonymous::Change(info.query).c_str());
601         return Status::INVALID_ARGUMENT;
602     }
603 
604     switch (type) {
605         case ACTION_SYNC:
606             status = store->Sync(uuids, ConvertDBMode(SyncMode(info.mode)), complete, dbQuery, false);
607             break;
608         case ACTION_SUBSCRIBE:
609             status = store->SubscribeRemoteQuery(uuids, complete, dbQuery, false);
610             break;
611         case ACTION_UNSUBSCRIBE:
612             status = store->UnSubscribeRemoteQuery(uuids, complete, dbQuery, false);
613             break;
614         default:
615             status = DBStatus::INVALID_ARGS;
616             break;
617     }
618     return ConvertDbStatus(status);
619 }
620 
DoComplete(const StoreMetaData & meta,const SyncInfo & info,RefCount refCount,const DBResult & dbResult)621 Status KVDBServiceImpl::DoComplete(const StoreMetaData &meta, const SyncInfo &info, RefCount refCount,
622     const DBResult &dbResult)
623 {
624     ZLOGD("seqId:0x%{public}" PRIx64 " tokenId:0x%{public}x remote:%{public}zu", info.seqId, meta.tokenId,
625         dbResult.size());
626     if (refCount) {
627         DeviceMatrix::GetInstance().OnExchanged(info.devices[0], DeviceMatrix::GetInstance().GetCode(meta));
628     }
629     if (info.seqId == std::numeric_limits<uint64_t>::max()) {
630         return SUCCESS;
631     }
632     sptr<IKvStoreSyncCallback> callback;
633     syncAgents_.ComputeIfPresent(meta.tokenId, [&callback](auto &key, SyncAgent &agent) {
634         callback = agent.callback_;
635         return true;
636     });
637     if (callback == nullptr) {
638         return SUCCESS;
639     }
640 
641     std::map<std::string, Status> result;
642     for (auto &[key, status] : dbResult) {
643         result[key] = ConvertDbStatus(status);
644     }
645     callback->SyncCompleted(result, info.seqId);
646     return SUCCESS;
647 }
648 
GetSyncDelayTime(uint32_t delay,const StoreId & storeId)649 uint32_t KVDBServiceImpl::GetSyncDelayTime(uint32_t delay, const StoreId &storeId)
650 {
651     if (delay != 0) {
652         return std::min(std::max(delay, KvStoreSyncManager::SYNC_MIN_DELAY_MS), KvStoreSyncManager::SYNC_MAX_DELAY_MS);
653     }
654 
655     bool isBackground = Constant::IsBackground(IPCSkeleton::GetCallingPid());
656     if (!isBackground) {
657         return delay;
658     }
659     delay = KvStoreSyncManager::SYNC_DEFAULT_DELAY_MS;
660     syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [&delay, &storeId](auto &, SyncAgent &agent) {
661         auto it = agent.delayTimes_.find(storeId);
662         if (it != agent.delayTimes_.end() && it->second != 0) {
663             delay = it->second;
664         }
665         return true;
666     });
667     return delay;
668 }
669 
ConvertDbStatus(DBStatus status) const670 Status KVDBServiceImpl::ConvertDbStatus(DBStatus status) const
671 {
672     switch (status) {
673         case DBStatus::BUSY: // fallthrough
674         case DBStatus::DB_ERROR:
675             return Status::DB_ERROR;
676         case DBStatus::OK:
677             return Status::SUCCESS;
678         case DBStatus::INVALID_ARGS:
679             return Status::INVALID_ARGUMENT;
680         case DBStatus::NOT_FOUND:
681             return Status::KEY_NOT_FOUND;
682         case DBStatus::INVALID_VALUE_FIELDS:
683             return Status::INVALID_VALUE_FIELDS;
684         case DBStatus::INVALID_FIELD_TYPE:
685             return Status::INVALID_FIELD_TYPE;
686         case DBStatus::CONSTRAIN_VIOLATION:
687             return Status::CONSTRAIN_VIOLATION;
688         case DBStatus::INVALID_FORMAT:
689             return Status::INVALID_FORMAT;
690         case DBStatus::INVALID_QUERY_FORMAT:
691             return Status::INVALID_QUERY_FORMAT;
692         case DBStatus::INVALID_QUERY_FIELD:
693             return Status::INVALID_QUERY_FIELD;
694         case DBStatus::NOT_SUPPORT:
695             return Status::NOT_SUPPORT;
696         case DBStatus::TIME_OUT:
697             return Status::TIME_OUT;
698         case DBStatus::OVER_MAX_LIMITS:
699             return Status::OVER_MAX_SUBSCRIBE_LIMITS;
700         case DBStatus::EKEYREVOKED_ERROR: // fallthrough
701         case DBStatus::SECURITY_OPTION_CHECK_ERROR:
702             return Status::SECURITY_LEVEL_ERROR;
703         default:
704             break;
705     }
706     return Status::ERROR;
707 }
708 
ConvertDBMode(SyncMode syncMode) const709 KVDBServiceImpl::DBMode KVDBServiceImpl::ConvertDBMode(SyncMode syncMode) const
710 {
711     DBMode dbMode;
712     if (syncMode == SyncMode::PUSH) {
713         dbMode = DBMode::SYNC_MODE_PUSH_ONLY;
714     } else if (syncMode == SyncMode::PULL) {
715         dbMode = DBMode::SYNC_MODE_PULL_ONLY;
716     } else {
717         dbMode = DBMode::SYNC_MODE_PUSH_PULL;
718     }
719     return dbMode;
720 }
721 
ConvertDevices(const std::vector<std::string> & deviceIds) const722 std::vector<std::string> KVDBServiceImpl::ConvertDevices(const std::vector<std::string> &deviceIds) const
723 {
724     if (deviceIds.empty()) {
725         return DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices());
726     }
727     return DMAdapter::ToUUID(deviceIds);
728 }
729 
GetObservers(uint32_t tokenId,const std::string & storeId)730 std::shared_ptr<StoreCache::Observers> KVDBServiceImpl::GetObservers(uint32_t tokenId, const std::string &storeId)
731 {
732     std::shared_ptr<StoreCache::Observers> observers;
733     syncAgents_.ComputeIfPresent(tokenId, [&storeId, &observers](auto, SyncAgent &agent) {
734         auto it = agent.observers_.find(storeId);
735         if (it != agent.observers_.end()) {
736             observers = it->second;
737         }
738         return true;
739     });
740     return observers;
741 }
742 
ReInit(pid_t pid,const AppId & appId)743 void KVDBServiceImpl::SyncAgent::ReInit(pid_t pid, const AppId &appId)
744 {
745     ZLOGW("pid:%{public}d->%{public}d appId:%{public}s callback:%{public}d observer:%{public}zu", pid, pid_,
746         appId_.appId.c_str(), callback_ == nullptr, observers_.size());
747     pid_ = pid;
748     appId_ = appId;
749     callback_ = nullptr;
750     delayTimes_.clear();
751     observers_.clear();
752 }
753 } // namespace OHOS::DistributedKv