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