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 ¶m)
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