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 "RdbServiceImpl"
16 #include "rdb_service_impl.h"
17
18 #include "abs_rdb_predicates.h"
19 #include "accesstoken_kit.h"
20 #include "account/account_delegate.h"
21 #include "changeevent/remote_change_event.h"
22 #include "checker/checker_manager.h"
23 #include "cloud/change_event.h"
24 #include "cloud/cloud_lock_event.h"
25 #include "cloud/cloud_share_event.h"
26 #include "cloud/make_query_event.h"
27 #include "cloud/schema_meta.h"
28 #include "communicator/device_manager_adapter.h"
29 #include "crypto_manager.h"
30 #include "device_matrix.h"
31 #include "directory/directory_manager.h"
32 #include "dump/dump_manager.h"
33 #include "eventcenter/event_center.h"
34 #include "ipc_skeleton.h"
35 #include "log_print.h"
36 #include "metadata/appid_meta_data.h"
37 #include "metadata/auto_launch_meta_data.h"
38 #include "metadata/capability_meta_data.h"
39 #include "metadata/meta_data_manager.h"
40 #include "metadata/store_debug_info.h"
41 #include "metadata/store_meta_data.h"
42 #include "rdb_general_store.h"
43 #include "rdb_notifier_proxy.h"
44 #include "rdb_query.h"
45 #include "rdb_result_set_impl.h"
46 #include "rdb_watcher.h"
47 #include "store/general_store.h"
48 #include "tokenid_kit.h"
49 #include "types_export.h"
50 #include "utils/anonymous.h"
51 #include "utils/constant.h"
52 #include "utils/converter.h"
53 #include "xcollie.h"
54 using OHOS::DistributedKv::AccountDelegate;
55 using OHOS::DistributedData::CheckerManager;
56 using OHOS::DistributedData::MetaDataManager;
57 using OHOS::DistributedData::StoreMetaData;
58 using OHOS::DistributedData::Anonymous;
59 using namespace OHOS::DistributedData;
60 using namespace OHOS::Security::AccessToken;
61 using DistributedDB::RelationalStoreManager;
62 using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter;
63 using DumpManager = OHOS::DistributedData::DumpManager;
64 using system_clock = std::chrono::system_clock;
65
66 constexpr uint32_t ITERATE_TIMES = 10000;
67 namespace OHOS::DistributedRdb {
68 __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_;
Factory()69 RdbServiceImpl::Factory::Factory()
70 {
71 FeatureSystem::GetInstance().RegisterCreator(RdbServiceImpl::SERVICE_NAME, [this]() {
72 if (product_ == nullptr) {
73 product_ = std::make_shared<RdbServiceImpl>();
74 }
75 return product_;
76 });
77 AutoCache::GetInstance().RegCreator(RDB_DEVICE_COLLABORATION, [](const StoreMetaData& metaData) -> GeneralStore* {
78 auto store = new (std::nothrow) RdbGeneralStore(metaData);
79 if (store != nullptr && !store->IsValid()) {
80 delete store;
81 store = nullptr;
82 }
83 return store;
84 });
85 staticActs_ = std::make_shared<RdbStatic>();
86 FeatureSystem::GetInstance().RegisterStaticActs(RdbServiceImpl::SERVICE_NAME, staticActs_);
87 }
88
~Factory()89 RdbServiceImpl::Factory::~Factory()
90 {
91 }
92
RdbServiceImpl()93 RdbServiceImpl::RdbServiceImpl()
94 {
95 ZLOGI("construct");
96 DistributedDB::RelationalStoreManager::SetAutoLaunchRequestCallback(
97 [this](const std::string& identifier, DistributedDB::AutoLaunchParam ¶m) {
98 return ResolveAutoLaunch(identifier, param);
99 });
100 auto process = [this](const Event &event) {
101 auto &evt = static_cast<const CloudEvent &>(event);
102 auto &storeInfo = evt.GetStoreInfo();
103 StoreMetaData meta(storeInfo);
104 meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
105 if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) {
106 ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
107 meta.GetStoreAlias().c_str());
108 return;
109 }
110 if (meta.storeType < StoreMetaData::STORE_RELATIONAL_BEGIN ||
111 meta.storeType > StoreMetaData::STORE_RELATIONAL_END) {
112 return;
113 }
114 auto watchers = GetWatchers(meta.tokenId, meta.storeId);
115 auto store = AutoCache::GetInstance().GetStore(meta, watchers);
116 if (store == nullptr) {
117 ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str());
118 return;
119 }
120 store->RegisterDetailProgressObserver(GetCallbacks(meta.tokenId, storeInfo.storeName));
121 };
122 EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC, process);
123 EventCenter::GetInstance().Subscribe(CloudEvent::CLEAN_DATA, process);
124
125 EventCenter::GetInstance().Subscribe(CloudEvent::MAKE_QUERY, [](const Event& event) {
126 auto& evt = static_cast<const MakeQueryEvent&>(event);
127 auto callback = evt.GetCallback();
128 if (!callback) {
129 return;
130 }
131 auto predicate = evt.GetPredicates();
132 auto rdbQuery = std::make_shared<RdbQuery>();
133 rdbQuery->MakeQuery(*predicate);
134 rdbQuery->SetColumns(evt.GetColumns());
135 callback(rdbQuery);
136 });
137 auto compensateSyncProcess = [this] (const Event &event) {
138 auto &evt = static_cast<const BindEvent &>(event);
139 DoCompensateSync(evt);
140 };
141 EventCenter::GetInstance().Subscribe(BindEvent::COMPENSATE_SYNC, compensateSyncProcess);
142 EventCenter::GetInstance().Subscribe(BindEvent::RECOVER_SYNC, compensateSyncProcess);
143 }
144
ResolveAutoLaunch(const std::string & identifier,DistributedDB::AutoLaunchParam & param)145 int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m)
146 {
147 std::string identifierHex = TransferStringToHex(identifier);
148 ZLOGI("%{public}.6s", identifierHex.c_str());
149 std::vector<StoreMetaData> entries;
150 auto localId = DmAdapter::GetInstance().GetLocalDevice().uuid;
151 if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ localId }), entries)) {
152 ZLOGE("get meta failed");
153 return false;
154 }
155 ZLOGI("size=%{public}d", static_cast<int32_t>(entries.size()));
156 for (const auto& entry : entries) {
157 if (entry.storeType != RDB_DEVICE_COLLABORATION) {
158 continue;
159 }
160
161 auto aIdentifier = DistributedDB::RelationalStoreManager::GetRelationalStoreIdentifier(
162 entry.user, entry.appId, entry.storeId);
163 ZLOGD("%{public}s %{public}s %{public}s",
164 entry.user.c_str(), entry.appId.c_str(), Anonymous::Change(entry.storeId).c_str());
165 if (aIdentifier != identifier) {
166 continue;
167 }
168 ZLOGI("find identifier %{public}s", Anonymous::Change(entry.storeId).c_str());
169 param.userId = entry.user;
170 param.appId = entry.appId;
171 param.storeId = entry.storeId;
172 param.path = entry.dataDir;
173 param.option.storeObserver = nullptr;
174 param.option.isEncryptedDb = entry.isEncrypt;
175 if (entry.isEncrypt) {
176 param.option.iterateTimes = ITERATE_TIMES;
177 param.option.cipher = DistributedDB::CipherType::AES_256_GCM;
178 GetDBPassword(entry, param.option.passwd);
179 }
180 AutoCache::GetInstance().GetStore(entry, GetWatchers(entry.tokenId, entry.storeId));
181 return true;
182 }
183 ZLOGE("not find identifier");
184 return false;
185 }
186
OnAppExit(pid_t uid,pid_t pid,uint32_t tokenId,const std::string & bundleName)187 int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName)
188 {
189 ZLOGI("client dead, tokenId:%{public}d, pid:%{public}d ", tokenId, pid);
190 bool destroyed = false;
191 syncAgents_.ComputeIfPresent(tokenId, [pid, &destroyed](auto &key, SyncAgents &agents) {
192 auto it = agents.find(pid);
193 if (it != agents.end()) {
194 it->second.SetNotifier(nullptr);
195 agents.erase(it);
196 }
197 if (!agents.empty()) {
198 return true;
199 }
200 destroyed = true;
201 return false;
202 });
203 if (destroyed) {
204 auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId);
205 for (auto store : stores) {
206 if (store != nullptr) {
207 store->UnregisterDetailProgressObserver();
208 }
209 }
210 AutoCache::GetInstance().Enable(tokenId);
211 }
212 heartbeatTaskIds_.Erase(pid);
213 return E_OK;
214 }
215
CheckAccess(const std::string & bundleName,const std::string & storeName)216 bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::string& storeName)
217 {
218 CheckerManager::StoreInfo storeInfo;
219 storeInfo.uid = IPCSkeleton::GetCallingUid();
220 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
221 storeInfo.bundleName = bundleName;
222 storeInfo.storeId = RemoveSuffix(storeName);
223 auto [instanceId, user] = GetInstIndexAndUser(storeInfo.tokenId, storeInfo.bundleName);
224 if (instanceId != 0) {
225 return false;
226 }
227 return !CheckerManager::GetInstance().GetAppId(storeInfo).empty();
228 }
229
ObtainDistributedTableName(const std::string & device,const std::string & table)230 std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table)
231 {
232 ZLOGI("device=%{public}s table=%{public}s", Anonymous::Change(device).c_str(), table.c_str());
233 auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(device);
234 if (uuid.empty()) {
235 ZLOGE("get uuid failed");
236 return "";
237 }
238 return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table);
239 }
240
InitNotifier(const RdbSyncerParam & param,const sptr<IRemoteObject> notifier)241 int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam ¶m, const sptr<IRemoteObject> notifier)
242 {
243 XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
244 if (!CheckAccess(param.bundleName_, "")) {
245 ZLOGE("bundleName:%{public}s. Permission error", param.bundleName_.c_str());
246 return RDB_ERROR;
247 }
248 if (notifier == nullptr) {
249 ZLOGE("notifier is null");
250 return RDB_ERROR;
251 }
252
253 auto notifierProxy = iface_cast<RdbNotifierProxy>(notifier);
254 pid_t pid = IPCSkeleton::GetCallingPid();
255 uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
256 syncAgents_.Compute(tokenId, [bundleName = param.bundleName_, notifierProxy, pid](auto, SyncAgents &agents) {
257 auto [it, success] = agents.try_emplace(pid, SyncAgent(bundleName));
258 if (it == agents.end()) {
259 return true;
260 }
261 it->second.SetNotifier(notifierProxy);
262 return true;
263 });
264 ZLOGI("success tokenId:%{public}x, pid=%{public}d", tokenId, pid);
265 return RDB_OK;
266 }
267
GetStore(const RdbSyncerParam & param)268 std::shared_ptr<DistributedData::GeneralStore> RdbServiceImpl::GetStore(const RdbSyncerParam ¶m)
269 {
270 StoreMetaData storeMetaData = GetStoreMetaData(param);
271 MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData, true);
272 auto watchers = GetWatchers(storeMetaData.tokenId, storeMetaData.storeId);
273 auto store = AutoCache::GetInstance().GetStore(storeMetaData, watchers);
274 if (store == nullptr) {
275 ZLOGE("store null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str());
276 }
277 return store;
278 }
279
SetDistributedTables(const RdbSyncerParam & param,const std::vector<std::string> & tables,const std::vector<Reference> & references,bool isRebuild,int32_t type)280 int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector<std::string> &tables,
281 const std::vector<Reference> &references, bool isRebuild, int32_t type)
282 {
283 if (!CheckAccess(param.bundleName_, param.storeName_)) {
284 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
285 Anonymous::Change(param.storeName_).c_str());
286 return RDB_ERROR;
287 }
288 if (type == DistributedRdb::DistributedTableType::DISTRIBUTED_SEARCH) {
289 DistributedData::SetSearchableEvent::EventInfo eventInfo;
290 eventInfo.isRebuild = isRebuild;
291 return PostSearchEvent(CloudEvent::SET_SEARCH_TRIGGER, param, eventInfo);
292 }
293 auto meta = GetStoreMetaData(param);
294
295 if (type == DistributedRdb::DistributedTableType::DISTRIBUTED_DEVICE) {
296 StoreMetaData localMeta;
297 bool isCreatedLocal = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), localMeta, true);
298 if (!isCreatedLocal) {
299 ZLOGE("no meta. bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(),
300 Anonymous::Change(param.storeName_).c_str());
301 return RDB_ERROR;
302 }
303 StoreMetaData syncMeta;
304 bool isCreatedSync = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta);
305 if (!isCreatedSync || localMeta != syncMeta) {
306 ZLOGI("save sync meta. bundle:%{public}s store:%{public}s type:%{public}d->%{public}d "
307 "encrypt:%{public}d->%{public}d , area:%{public}d->%{public}d",
308 meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), syncMeta.storeType, meta.storeType,
309 syncMeta.isEncrypt, meta.isEncrypt, syncMeta.area, meta.area);
310 MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), localMeta);
311 }
312 }
313 auto store = GetStore(param);
314 if (store == nullptr) {
315 ZLOGE("bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(),
316 Anonymous::Change(param.storeName_).c_str());
317 return RDB_ERROR;
318 }
319 std::vector<DistributedData::Reference> relationships;
320 for (const auto &reference : references) {
321 DistributedData::Reference relationship = { reference.sourceTable, reference.targetTable, reference.refFields };
322 relationships.emplace_back(relationship);
323 }
324 return store->SetDistributedTables(tables, type, relationships);
325 }
326
OnAsyncComplete(uint32_t tokenId,pid_t pid,uint32_t seqNum,Details && result)327 void RdbServiceImpl::OnAsyncComplete(uint32_t tokenId, pid_t pid, uint32_t seqNum, Details &&result)
328 {
329 ZLOGI("tokenId=%{public}x, pid=%{public}d, seqnum=%{public}u", tokenId, pid, seqNum);
330 sptr<RdbNotifierProxy> notifier = nullptr;
331 syncAgents_.ComputeIfPresent(tokenId, [¬ifier, pid](auto, SyncAgents &syncAgents) {
332 auto it = syncAgents.find(pid);
333 if (it != syncAgents.end()) {
334 notifier = it->second.notifier_;
335 }
336 return true;
337 });
338 if (notifier != nullptr) {
339 notifier->OnComplete(seqNum, std::move(result));
340 }
341 }
342
TransferStringToHex(const std::string & origStr)343 std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr)
344 {
345 if (origStr.empty()) {
346 return "";
347 }
348 const char *hex = "0123456789abcdef";
349 std::string tmp;
350 for (auto item : origStr) {
351 auto currentByte = static_cast<uint8_t>(item);
352 tmp.push_back(hex[currentByte >> 4]); // high 4 bit to one hex.
353 tmp.push_back(hex[currentByte & 0x0F]); // low 4 bit to one hex.
354 }
355 return tmp;
356 }
357
GetWatchers(uint32_t tokenId,const std::string & storeName)358 AutoCache::Watchers RdbServiceImpl::GetWatchers(uint32_t tokenId, const std::string &storeName)
359 {
360 AutoCache::Watchers watchers;
361 syncAgents_.ComputeIfPresent(tokenId, [&watchers](auto, SyncAgents &syncAgents) {
362 std::for_each(syncAgents.begin(), syncAgents.end(), [&watchers](const auto &item) {
363 if (item.second.watcher_ != nullptr) {
364 watchers.insert(item.second.watcher_);
365 }
366 });
367 return true;
368 });
369 return watchers;
370 }
371
GetCallbacks(uint32_t tokenId,const std::string & storeName)372 RdbServiceImpl::DetailAsync RdbServiceImpl::GetCallbacks(uint32_t tokenId, const std::string &storeName)
373 {
374 std::list<sptr<RdbNotifierProxy>> notifiers;
375 syncAgents_.ComputeIfPresent(tokenId, [&storeName, ¬ifiers](auto, SyncAgents &syncAgents) {
376 std::for_each(syncAgents.begin(), syncAgents.end(), [&storeName, ¬ifiers](const auto &item) {
377 if (item.second.callBackStores_.count(storeName) != 0) {
378 notifiers.push_back(item.second.notifier_);
379 }
380 });
381 return true;
382 });
383 if (notifiers.empty()) {
384 return nullptr;
385 }
386 return [notifiers, storeName](const GenDetails &details) {
387 for (const auto ¬ifier : notifiers) {
388 if (notifier != nullptr) {
389 notifier->OnComplete(storeName, HandleGenDetails(details));
390 }
391 }
392 };
393 }
394
RemoteQuery(const RdbSyncerParam & param,const std::string & device,const std::string & sql,const std::vector<std::string> & selectionArgs)395 std::pair<int32_t, std::shared_ptr<RdbServiceImpl::ResultSet>> RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param,
396 const std::string& device, const std::string& sql, const std::vector<std::string>& selectionArgs)
397 {
398 if (!CheckAccess(param.bundleName_, param.storeName_)) {
399 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
400 Anonymous::Change(param.storeName_).c_str());
401 return { RDB_ERROR, nullptr };
402 }
403 auto store = GetStore(param);
404 if (store == nullptr) {
405 ZLOGE("store is null");
406 return { RDB_ERROR, nullptr };
407 }
408 RdbQuery rdbQuery;
409 rdbQuery.MakeRemoteQuery(DmAdapter::GetInstance().ToUUID(device), sql, ValueProxy::Convert(selectionArgs));
410 auto [errCode, cursor] = store->Query("", rdbQuery);
411 if (errCode != GeneralError::E_OK) {
412 return { RDB_ERROR, nullptr };
413 }
414 return { RDB_OK, std::make_shared<RdbResultSetImpl>(cursor) };
415 }
416
Sync(const RdbSyncerParam & param,const Option & option,const PredicatesMemo & predicates,const AsyncDetail & async)417 int32_t RdbServiceImpl::Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates,
418 const AsyncDetail &async)
419 {
420 if (!CheckAccess(param.bundleName_, param.storeName_)) {
421 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
422 Anonymous::Change(param.storeName_).c_str());
423 return RDB_ERROR;
424 }
425 if (option.mode < DistributedData::GeneralStore::CLOUD_END &&
426 option.mode >= DistributedData::GeneralStore::CLOUD_BEGIN) {
427 DoCloudSync(param, option, predicates, async);
428 return RDB_OK;
429 }
430 return DoSync(param, option, predicates, async);
431 }
432
DoSync(const RdbSyncerParam & param,const RdbService::Option & option,const PredicatesMemo & predicates,const AsyncDetail & async)433 int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option &option,
434 const PredicatesMemo &predicates, const AsyncDetail &async)
435 {
436 auto store = GetStore(param);
437 if (store == nullptr) {
438 return RDB_ERROR;
439 }
440 RdbQuery rdbQuery;
441 rdbQuery.MakeQuery(predicates);
442 auto devices = rdbQuery.GetDevices().empty() ? DmAdapter::ToUUID(DmAdapter::GetInstance().GetRemoteDevices())
443 : DmAdapter::ToUUID(rdbQuery.GetDevices());
444 auto pid = IPCSkeleton::GetCallingPid();
445 SyncParam syncParam = { option.mode, 0, option.isCompensation };
446 StoreMetaData meta = GetStoreMetaData(param);
447 auto tokenId = IPCSkeleton::GetCallingTokenID();
448 ZLOGD("seqNum=%{public}u", option.seqNum);
449 auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, async, seq = option.seqNum](
450 const auto &results) mutable {
451 auto ret = ProcessResult(results);
452 store->Sync(
453 ret.first, rdbQuery,
454 [this, tokenId, seq, pid](const GenDetails &result) mutable {
455 OnAsyncComplete(tokenId, pid, seq, HandleGenDetails(result));
456 },
457 syncParam);
458 };
459 if (IsNeedMetaSync(meta, devices)) {
460 auto result = MetaDataManager::GetInstance().Sync(devices, complete);
461 return result ? GeneralError::E_OK : GeneralError::E_ERROR;
462 }
463 return store->Sync(
464 devices, rdbQuery,
465 [this, tokenId, pid, seqNum = option.seqNum](const GenDetails &result) mutable {
466 OnAsyncComplete(tokenId, pid, seqNum, HandleGenDetails(result));
467 },
468 syncParam);
469 }
470
IsNeedMetaSync(const StoreMetaData & meta,const std::vector<std::string> & uuids)471 bool RdbServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vector<std::string> &uuids)
472 {
473 bool isAfterMeta = false;
474 for (const auto &uuid : uuids) {
475 auto metaData = meta;
476 metaData.deviceId = uuid;
477 CapMetaData capMeta;
478 auto capKey = CapMetaRow::GetKeyFor(uuid);
479 if (!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) ||
480 !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) {
481 isAfterMeta = true;
482 break;
483 }
484 auto [exist, mask] = DeviceMatrix::GetInstance().GetRemoteMask(uuid);
485 if ((mask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) {
486 isAfterMeta = true;
487 break;
488 }
489 }
490 return isAfterMeta;
491 }
492
ProcessResult(const std::map<std::string,int32_t> & results)493 RdbServiceImpl::SyncResult RdbServiceImpl::ProcessResult(const std::map<std::string, int32_t> &results)
494 {
495 std::map<std::string, DBStatus> dbResults;
496 std::vector<std::string> devices;
497 for (const auto &[uuid, status] : results) {
498 dbResults.insert_or_assign(uuid, static_cast<DBStatus>(status));
499 if (static_cast<DBStatus>(status) != DBStatus::OK) {
500 continue;
501 }
502 DeviceMatrix::GetInstance().OnExchanged(uuid, DeviceMatrix::META_STORE_MASK);
503 devices.emplace_back(uuid);
504 }
505 ZLOGD("meta sync finish, total size:%{public}zu, success size:%{public}zu", dbResults.size(), devices.size());
506 return { devices, dbResults };
507 }
508
DoCompensateSync(const BindEvent & event)509 void RdbServiceImpl::DoCompensateSync(const BindEvent& event)
510 {
511 auto bindInfo = event.GetBindInfo();
512 StoreInfo storeInfo;
513 storeInfo.bundleName = bindInfo.bundleName;
514 storeInfo.tokenId = bindInfo.tokenId;
515 storeInfo.user = bindInfo.user;
516 storeInfo.storeName = bindInfo.storeName;
517 OHOS::NativeRdb::AbsRdbPredicates predicates(bindInfo.tableName);
518 for (auto& [key, value] : bindInfo.primaryKey) {
519 predicates.In(key, std::vector<NativeRdb::ValueObject>({ ValueProxy::Convert(std::move(value)) }));
520 }
521 auto memo = predicates.GetDistributedPredicates();
522 std::shared_ptr<RdbQuery> query = nullptr;
523 if (!memo.tables_.empty()) {
524 query = std::make_shared<RdbQuery>();
525 query->MakeCloudQuery(memo);
526 }
527 auto mixMode = event.GetEventId() == BindEvent::COMPENSATE_SYNC
528 ? GeneralStore::MixMode(TIME_FIRST, GeneralStore::AUTO_SYNC_MODE)
529 : GeneralStore::MixMode(CLOUD_FIRST, GeneralStore::AUTO_SYNC_MODE);
530 auto info = ChangeEvent::EventInfo(mixMode, 0, false, query, nullptr);
531 auto evt = std::make_unique<ChangeEvent>(std::move(storeInfo), std::move(info));
532 EventCenter::GetInstance().PostEvent(std::move(evt));
533 }
534
DoCloudSync(const RdbSyncerParam & param,const RdbService::Option & option,const PredicatesMemo & predicates,const AsyncDetail & async)535 void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService::Option &option,
536 const PredicatesMemo &predicates, const AsyncDetail &async)
537 {
538 StoreInfo storeInfo;
539 storeInfo.bundleName = param.bundleName_;
540 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
541 storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId);
542 storeInfo.storeName = RemoveSuffix(param.storeName_);
543 std::shared_ptr<RdbQuery> query = nullptr;
544 if (!predicates.tables_.empty()) {
545 query = std::make_shared<RdbQuery>();
546 query->MakeCloudQuery(predicates);
547 }
548 auto pid = IPCSkeleton::GetCallingPid();
549 GenAsync asyncCallback = [this, tokenId = storeInfo.tokenId, seqNum = option.seqNum, pid](
550 const GenDetails &result) mutable {
551 OnAsyncComplete(tokenId, pid, seqNum, HandleGenDetails(result));
552 };
553 GenAsync syncCallback = [async, ¶m](const GenDetails &details) {
554 ZLOGD("Cloud Sync complete, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(),
555 Anonymous::Change(param.storeName_).c_str());
556 if (async != nullptr) {
557 async(HandleGenDetails(details));
558 }
559 };
560 auto mixMode = static_cast<int32_t>(GeneralStore::MixMode(option.mode,
561 option.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE));
562 SyncParam syncParam = { mixMode, (option.isAsync ? 0 : WAIT_TIME), option.isCompensation };
563 auto info = ChangeEvent::EventInfo(syncParam, option.isAutoSync, query,
564 option.isAutoSync ? nullptr
565 : option.isAsync ? asyncCallback
566 : syncCallback);
567 auto evt = std::make_unique<ChangeEvent>(std::move(storeInfo), std::move(info));
568 EventCenter::GetInstance().PostEvent(std::move(evt));
569 }
570
Subscribe(const RdbSyncerParam & param,const SubscribeOption & option,RdbStoreObserver * observer)571 int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option,
572 RdbStoreObserver *observer)
573 {
574 if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) {
575 ZLOGE("mode:%{public}d error", option.mode);
576 return RDB_ERROR;
577 }
578 pid_t pid = IPCSkeleton::GetCallingPid();
579 auto tokenId = IPCSkeleton::GetCallingTokenID();
580 bool isCreate = false;
581 syncAgents_.Compute(tokenId, [pid, ¶m, &isCreate](auto &key, SyncAgents &agents) {
582 auto [it, _] = agents.try_emplace(pid, param.bundleName_);
583 if (it == agents.end()) {
584 return !agents.empty();
585 }
586 if (it->second.watcher_ == nullptr) {
587 isCreate = true;
588 it->second.SetWatcher(std::make_shared<RdbWatcher>());
589 }
590 it->second.count_++;
591 return true;
592 });
593 if (isCreate) {
594 AutoCache::GetInstance().SetObserver(tokenId, RemoveSuffix(param.storeName_),
595 GetWatchers(tokenId, param.storeName_));
596 }
597 return RDB_OK;
598 }
599
UnSubscribe(const RdbSyncerParam & param,const SubscribeOption & option,RdbStoreObserver * observer)600 int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option,
601 RdbStoreObserver *observer)
602 {
603 if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) {
604 ZLOGE("mode:%{public}d error", option.mode);
605 return RDB_ERROR;
606 }
607 bool destroyed = false;
608 auto tokenId = IPCSkeleton::GetCallingTokenID();
609 auto pid = IPCSkeleton::GetCallingPid();
610 syncAgents_.ComputeIfPresent(tokenId, [pid, &destroyed](auto, SyncAgents &agents) {
611 auto it = agents.find(pid);
612 if (it == agents.end()) {
613 return !agents.empty();
614 }
615 it->second.count_--;
616 if (it->second.count_ <= 0) {
617 destroyed = true;
618 it->second.SetWatcher(nullptr);
619 }
620 return true;
621 });
622 if (destroyed) {
623 AutoCache::GetInstance().SetObserver(tokenId, RemoveSuffix(param.storeName_),
624 GetWatchers(tokenId, param.storeName_));
625 }
626 return RDB_OK;
627 }
628
RegisterAutoSyncCallback(const RdbSyncerParam & param,std::shared_ptr<DetailProgressObserver> observer)629 int32_t RdbServiceImpl::RegisterAutoSyncCallback(const RdbSyncerParam& param,
630 std::shared_ptr<DetailProgressObserver> observer)
631 {
632 pid_t pid = IPCSkeleton::GetCallingPid();
633 auto tokenId = IPCSkeleton::GetCallingTokenID();
634 auto storeName = RemoveSuffix(param.storeName_);
635 syncAgents_.Compute(tokenId, [pid, ¶m, &storeName](auto, SyncAgents &agents) {
636 auto [it, success] = agents.try_emplace(pid, param.bundleName_);
637 if (it == agents.end()) {
638 return !agents.empty();
639 }
640 if (success) {
641 it->second.callBackStores_.insert(std::make_pair(storeName, 0));
642 }
643 it->second.callBackStores_[storeName]++;
644 return true;
645 });
646 return RDB_OK;
647 }
648
UnregisterAutoSyncCallback(const RdbSyncerParam & param,std::shared_ptr<DetailProgressObserver> observer)649 int32_t RdbServiceImpl::UnregisterAutoSyncCallback(const RdbSyncerParam& param,
650 std::shared_ptr<DetailProgressObserver> observer)
651 {
652 auto tokenId = IPCSkeleton::GetCallingTokenID();
653 auto pid = IPCSkeleton::GetCallingPid();
654 auto storeName = RemoveSuffix(param.storeName_);
655 syncAgents_.ComputeIfPresent(tokenId, [pid, &storeName](auto, SyncAgents &agents) {
656 auto agent = agents.find(pid);
657 if (agent == agents.end()) {
658 return !agents.empty();
659 }
660 auto it = agent->second.callBackStores_.find(storeName);
661 if (it == agent->second.callBackStores_.end()) {
662 return !agents.empty();
663 }
664 it->second--;
665 if (it->second <= 0) {
666 agent->second.callBackStores_.erase(it);
667 }
668 return !agents.empty();
669 });
670 return RDB_OK;
671 }
672
Delete(const RdbSyncerParam & param)673 int32_t RdbServiceImpl::Delete(const RdbSyncerParam ¶m)
674 {
675 XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
676 auto tokenId = IPCSkeleton::GetCallingTokenID();
677 AutoCache::GetInstance().CloseStore(tokenId, RemoveSuffix(param.storeName_));
678 RdbSyncerParam tmpParam = param;
679 HapTokenInfo hapTokenInfo;
680 AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo);
681 tmpParam.bundleName_ = hapTokenInfo.bundleName;
682 auto storeMeta = GetStoreMetaData(tmpParam);
683 MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey());
684 MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey(), true);
685 MetaDataManager::GetInstance().DelMeta(storeMeta.GetKeyLocal(), true);
686 MetaDataManager::GetInstance().DelMeta(storeMeta.GetSecretKey(), true);
687 MetaDataManager::GetInstance().DelMeta(storeMeta.GetStrategyKey());
688 MetaDataManager::GetInstance().DelMeta(storeMeta.GetBackupSecretKey(), true);
689 MetaDataManager::GetInstance().DelMeta(storeMeta.GetAutoLaunchKey(), true);
690 MetaDataManager::GetInstance().DelMeta(storeMeta.GetDebugInfoKey(), true);
691 return RDB_OK;
692 }
693
QuerySharingResource(const RdbSyncerParam & param,const PredicatesMemo & predicates,const std::vector<std::string> & columns)694 std::pair<int32_t, std::shared_ptr<RdbService::ResultSet>> RdbServiceImpl::QuerySharingResource(
695 const RdbSyncerParam& param, const PredicatesMemo& predicates, const std::vector<std::string>& columns)
696 {
697 if (!CheckAccess(param.bundleName_, param.storeName_) ||
698 !TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) {
699 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
700 Anonymous::Change(param.storeName_).c_str());
701 return { RDB_ERROR, {} };
702 }
703 if (predicates.tables_.empty()) {
704 ZLOGE("tables is empty, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(),
705 Anonymous::Change(param.storeName_).c_str());
706 return { RDB_ERROR, {} };
707 }
708 auto rdbQuery = std::make_shared<RdbQuery>();
709 rdbQuery->MakeQuery(predicates);
710 rdbQuery->SetColumns(columns);
711 StoreInfo storeInfo;
712 storeInfo.bundleName = param.bundleName_;
713 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
714 storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId);
715 storeInfo.storeName = RemoveSuffix(param.storeName_);
716 auto [status, cursor] = AllocResource(storeInfo, rdbQuery);
717 if (cursor == nullptr) {
718 ZLOGE("cursor is null, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(),
719 Anonymous::Change(param.storeName_).c_str());
720 return { RDB_ERROR, {} };
721 }
722 return { RDB_OK, std::make_shared<RdbResultSetImpl>(cursor) };
723 }
724
AllocResource(StoreInfo & storeInfo,std::shared_ptr<RdbQuery> rdbQuery)725 std::pair<int32_t, std::shared_ptr<Cursor>> RdbServiceImpl::AllocResource(StoreInfo& storeInfo,
726 std::shared_ptr<RdbQuery> rdbQuery)
727 {
728 std::pair<int32_t, std::shared_ptr<Cursor>> result;
729 CloudShareEvent::Callback asyncCallback = [&result](int32_t status, std::shared_ptr<Cursor> cursor) {
730 result.first = status;
731 result.second = cursor;
732 };
733 auto evt = std::make_unique<CloudShareEvent>(std::move(storeInfo), rdbQuery, asyncCallback);
734 EventCenter::GetInstance().PostEvent(std::move(evt));
735 return result;
736 }
737
BeforeOpen(RdbSyncerParam & param)738 int32_t RdbServiceImpl::BeforeOpen(RdbSyncerParam ¶m)
739 {
740 XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
741 auto meta = GetStoreMetaData(param);
742 auto isCreated =
743 MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true);
744 if (!isCreated) {
745 return RDB_OK;
746 }
747 SetReturnParam(meta, param);
748 return RDB_OK;
749 }
750
SetReturnParam(StoreMetaData & metadata,RdbSyncerParam & param)751 void RdbServiceImpl::SetReturnParam(StoreMetaData &metadata, RdbSyncerParam ¶m)
752 {
753 param.bundleName_ = metadata.bundleName;
754 param.type_ = metadata.storeType;
755 param.level_ = metadata.securityLevel;
756 param.area_ = metadata.area;
757 param.hapName_ = metadata.hapName;
758 param.customDir_ = metadata.customDir;
759 param.isEncrypt_ = metadata.isEncrypt;
760 param.isAutoClean_ = !metadata.isManualClean;
761 param.isSearchable_ = metadata.isSearchable;
762 param.haMode_ = metadata.haMode;
763 }
764
AfterOpen(const RdbSyncerParam & param)765 int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m)
766 {
767 XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
768 if (!CheckAccess(param.bundleName_, param.storeName_)) {
769 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
770 Anonymous::Change(param.storeName_).c_str());
771 return RDB_ERROR;
772 }
773 auto meta = GetStoreMetaData(param);
774 StoreMetaData old;
775 auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old, true);
776 if (!isCreated || meta != old) {
777 Upgrade(param, old);
778 ZLOGD("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
779 "area:%{public}d->%{public}d",
780 meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType,
781 old.isEncrypt, meta.isEncrypt, old.area, meta.area);
782 MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true);
783 AutoLaunchMetaData launchData;
784 if (!MetaDataManager::GetInstance().LoadMeta(meta.GetAutoLaunchKey(), launchData, true)) {
785 RemoteChangeEvent::DataInfo info;
786 info.bundleName = meta.bundleName;
787 info.deviceId = meta.deviceId;
788 info.userId = meta.user;
789 auto evt = std::make_unique<RemoteChangeEvent>(RemoteChangeEvent::RDB_META_SAVE, std::move(info));
790 EventCenter::GetInstance().PostEvent(std::move(evt));
791 }
792 }
793
794 SaveDebugInfo(meta, param);
795
796 AppIDMetaData appIdMeta;
797 appIdMeta.bundleName = meta.bundleName;
798 appIdMeta.appId = meta.appId;
799 if (!MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true)) {
800 ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
801 "area:%{public}d->%{public}d",
802 meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType,
803 old.isEncrypt, meta.isEncrypt, old.area, meta.area);
804 return RDB_ERROR;
805 }
806 if (param.isEncrypt_ && !param.password_.empty()) {
807 auto ret = SetSecretKey(param, meta);
808 if (ret != RDB_OK) {
809 ZLOGE("Set secret key failed, bundle:%{public}s store:%{public}s",
810 meta.bundleName.c_str(), meta.GetStoreAlias().c_str());
811 return RDB_ERROR;
812 }
813 }
814 GetCloudSchema(param);
815 return RDB_OK;
816 }
817
GetCloudSchema(const RdbSyncerParam & param)818 void RdbServiceImpl::GetCloudSchema(const RdbSyncerParam ¶m)
819 {
820 if (executors_ != nullptr) {
821 StoreInfo storeInfo;
822 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
823 storeInfo.bundleName = param.bundleName_;
824 storeInfo.storeName = RemoveSuffix(param.storeName_);
825 auto [instanceId, user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_);
826 storeInfo.instanceId = instanceId;
827 storeInfo.user = user;
828 storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
829 executors_->Execute([storeInfo]() {
830 auto event = std::make_unique<CloudEvent>(CloudEvent::GET_SCHEMA, std::move(storeInfo));
831 EventCenter::GetInstance().PostEvent(move(event));
832 return;
833 });
834 }
835 }
836
GetStoreMetaData(const RdbSyncerParam & param)837 StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m)
838 {
839 StoreMetaData metaData;
840 metaData.uid = IPCSkeleton::GetCallingUid();
841 metaData.tokenId = IPCSkeleton::GetCallingTokenID();
842 auto [instanceId, user] = GetInstIndexAndUser(metaData.tokenId, param.bundleName_);
843 metaData.instanceId = instanceId;
844 metaData.bundleName = param.bundleName_;
845 metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
846 metaData.storeId = RemoveSuffix(param.storeName_);
847 metaData.user = std::to_string(user);
848 metaData.storeType = param.type_;
849 metaData.securityLevel = param.level_;
850 metaData.area = param.area_;
851 metaData.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(metaData));
852 metaData.appType = "harmony";
853 metaData.hapName = param.hapName_;
854 metaData.customDir = param.customDir_;
855 metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_;
856 metaData.account = AccountDelegate::GetInstance()->GetCurrentAccountId();
857 metaData.isEncrypt = param.isEncrypt_;
858 metaData.isManualClean = !param.isAutoClean_;
859 metaData.isSearchable = param.isSearchable_;
860 metaData.haMode = param.haMode_;
861 return metaData;
862 }
863
SetSecretKey(const RdbSyncerParam & param,const StoreMetaData & meta)864 int32_t RdbServiceImpl::SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta)
865 {
866 SecretKeyMetaData newSecretKey;
867 newSecretKey.storeType = meta.storeType;
868 newSecretKey.sKey = CryptoManager::GetInstance().Encrypt(param.password_);
869 if (newSecretKey.sKey.empty()) {
870 ZLOGE("encrypt work key error.");
871 return RDB_ERROR;
872 }
873 auto time = system_clock::to_time_t(system_clock::now());
874 newSecretKey.time = { reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time) };
875 return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), newSecretKey, true) ? RDB_OK : RDB_ERROR;
876 }
877
Upgrade(const RdbSyncerParam & param,const StoreMetaData & old)878 int32_t RdbServiceImpl::Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old)
879 {
880 if (old.storeType == RDB_DEVICE_COLLABORATION && old.version < StoreMetaData::UUID_CHANGED_TAG) {
881 auto store = GetStore(param);
882 if (store == nullptr) {
883 ZLOGE("store is null, bundleName:%{public}s storeName:%{public}s", param.bundleName_.c_str(),
884 Anonymous::Change(param.storeName_).c_str());
885 return RDB_ERROR;
886 }
887 return store->Clean({}, GeneralStore::CleanMode::NEARBY_DATA, "") == GeneralError::E_OK ? RDB_OK : RDB_ERROR;
888 }
889 return RDB_OK;
890 }
891
HandleGenDetails(const GenDetails & details)892 Details RdbServiceImpl::HandleGenDetails(const GenDetails &details)
893 {
894 Details dbDetails;
895 for (const auto& [id, detail] : details) {
896 auto &dbDetail = dbDetails[id];
897 dbDetail.progress = detail.progress;
898 dbDetail.code = detail.code;
899 for (auto &[name, table] : detail.details) {
900 auto &dbTable = dbDetail.details[name];
901 Constant::Copy(&dbTable, &table);
902 }
903 }
904 return dbDetails;
905 }
906
GetDBPassword(const StoreMetaData & metaData,DistributedDB::CipherPassword & password)907 bool RdbServiceImpl::GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password)
908 {
909 if (!metaData.isEncrypt) {
910 return true;
911 }
912
913 std::string key = metaData.GetSecretKey();
914 DistributedData::SecretKeyMetaData secretKeyMeta;
915 MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true);
916 std::vector<uint8_t> decryptKey;
917 CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptKey);
918 if (password.SetValue(decryptKey.data(), decryptKey.size()) != DistributedDB::CipherPassword::OK) {
919 std::fill(decryptKey.begin(), decryptKey.end(), 0);
920 ZLOGE("Set secret key value failed. len is (%{public}d)", int32_t(decryptKey.size()));
921 return false;
922 }
923 std::fill(decryptKey.begin(), decryptKey.end(), 0);
924 return true;
925 }
926
RemoveSuffix(const std::string & name)927 std::string RdbServiceImpl::RemoveSuffix(const std::string& name)
928 {
929 std::string suffix(".db");
930 auto pos = name.rfind(suffix);
931 if (pos == std::string::npos || pos < name.length() - suffix.length()) {
932 return name;
933 }
934 return std::string(name, 0, pos);
935 }
936
GetInstIndexAndUser(uint32_t tokenId,const std::string & bundleName)937 std::pair<int32_t, int32_t> RdbServiceImpl::GetInstIndexAndUser(uint32_t tokenId, const std::string &bundleName)
938 {
939 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
940 return { 0, 0 };
941 }
942
943 HapTokenInfo tokenInfo;
944 tokenInfo.instIndex = -1;
945 int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
946 if (errCode != RET_SUCCESS) {
947 ZLOGE("GetHapTokenInfo error:%{public}d, tokenId:0x%{public}x appId:%{public}s", errCode, tokenId,
948 bundleName.c_str());
949 return { -1, -1 };
950 }
951 return { tokenInfo.instIndex, tokenInfo.userID };
952 }
953
OnBind(const BindInfo & bindInfo)954 int32_t RdbServiceImpl::OnBind(const BindInfo &bindInfo)
955 {
956 executors_ = bindInfo.executors;
957 return 0;
958 }
959
SetNotifier(sptr<RdbNotifierProxy> notifier)960 void RdbServiceImpl::SyncAgent::SetNotifier(sptr<RdbNotifierProxy> notifier)
961 {
962 notifier_ = notifier;
963 if (watcher_ != nullptr) {
964 watcher_->SetNotifier(notifier);
965 }
966 }
967
SetWatcher(std::shared_ptr<RdbWatcher> watcher)968 void RdbServiceImpl::SyncAgent::SetWatcher(std::shared_ptr<RdbWatcher> watcher)
969 {
970 if (watcher_ != watcher) {
971 watcher_ = watcher;
972 if (watcher_ != nullptr) {
973 watcher_->SetNotifier(notifier_);
974 }
975 }
976 }
977
SyncAgent(const std::string & bundleName)978 RdbServiceImpl::SyncAgent::SyncAgent(const std::string &bundleName) : bundleName_(bundleName)
979 {
980 notifier_ = nullptr;
981 watcher_ = nullptr;
982 count_ = 0;
983 callBackStores_.clear();
984 }
985
CloseStore(const std::string & bundleName,int32_t user,int32_t index,int32_t tokenId) const986 int32_t RdbServiceImpl::RdbStatic::CloseStore(const std::string &bundleName, int32_t user, int32_t index,
987 int32_t tokenId) const
988 {
989 if (tokenId != RdbServiceImpl::RdbStatic::INVALID_TOKENID) {
990 AutoCache::GetInstance().CloseStore(tokenId);
991 return E_OK;
992 }
993 std::string prefix = StoreMetaData::GetPrefix(
994 { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(user), "default", bundleName });
995 std::vector<StoreMetaData> storeMetaData;
996 if (!MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData, true)) {
997 ZLOGE("load meta failed! bundleName:%{public}s, user:%{public}d, index:%{public}d",
998 bundleName.c_str(), user, index);
999 return E_ERROR;
1000 }
1001 for (const auto &meta : storeMetaData) {
1002 if (meta.storeType < StoreMetaData::STORE_RELATIONAL_BEGIN ||
1003 meta.storeType > StoreMetaData::STORE_RELATIONAL_END) {
1004 continue;
1005 }
1006 if (meta.instanceId == index && !meta.appId.empty() && !meta.storeId.empty()) {
1007 AutoCache::GetInstance().CloseStore(meta.tokenId);
1008 break;
1009 }
1010 }
1011 return E_OK;
1012 }
1013
OnAppUninstall(const std::string & bundleName,int32_t user,int32_t index)1014 int32_t RdbServiceImpl::RdbStatic::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index)
1015 {
1016 return CloseStore(bundleName, user, index);
1017 }
1018
OnAppUpdate(const std::string & bundleName,int32_t user,int32_t index)1019 int32_t RdbServiceImpl::RdbStatic::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index)
1020 {
1021 return CloseStore(bundleName, user, index);
1022 }
1023
OnClearAppStorage(const std::string & bundleName,int32_t user,int32_t index,int32_t tokenId)1024 int32_t RdbServiceImpl::RdbStatic::OnClearAppStorage(const std::string &bundleName, int32_t user, int32_t index,
1025 int32_t tokenId)
1026 {
1027 return CloseStore(bundleName, user, index, tokenId);
1028 }
1029
RegisterRdbServiceInfo()1030 void RdbServiceImpl::RegisterRdbServiceInfo()
1031 {
1032 DumpManager::Config serviceInfoConfig;
1033 serviceInfoConfig.fullCmd = "--feature-info";
1034 serviceInfoConfig.abbrCmd = "-f";
1035 serviceInfoConfig.dumpName = "FEATURE_INFO";
1036 serviceInfoConfig.dumpCaption = { "| Display all the service statistics" };
1037 DumpManager::GetInstance().AddConfig("FEATURE_INFO", serviceInfoConfig);
1038 }
1039
RegisterHandler()1040 void RdbServiceImpl::RegisterHandler()
1041 {
1042 Handler handler =
1043 std::bind(&RdbServiceImpl::DumpRdbServiceInfo, this, std::placeholders::_1, std::placeholders::_2);
1044 DumpManager::GetInstance().AddHandler("FEATURE_INFO", uintptr_t(this), handler);
1045 }
DumpRdbServiceInfo(int fd,std::map<std::string,std::vector<std::string>> & params)1046 void RdbServiceImpl::DumpRdbServiceInfo(int fd, std::map<std::string, std::vector<std::string>> ¶ms)
1047 {
1048 (void)params;
1049 std::string info;
1050 dprintf(fd, "-------------------------------------RdbServiceInfo------------------------------\n%s\n",
1051 info.c_str());
1052 }
OnInitialize()1053 int32_t RdbServiceImpl::OnInitialize()
1054 {
1055 RegisterRdbServiceInfo();
1056 RegisterHandler();
1057 return RDB_OK;
1058 }
1059
~RdbServiceImpl()1060 RdbServiceImpl::~RdbServiceImpl()
1061 {
1062 DumpManager::GetInstance().RemoveHandler("FEATURE_INFO", uintptr_t(this));
1063 }
1064
NotifyDataChange(const RdbSyncerParam & param,const RdbChangedData & rdbChangedData,const RdbNotifyConfig & rdbNotifyConfig)1065 int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData,
1066 const RdbNotifyConfig &rdbNotifyConfig)
1067 {
1068 XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
1069 if (!CheckAccess(param.bundleName_, param.storeName_)) {
1070 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
1071 Anonymous::Change(param.storeName_).c_str());
1072 return RDB_ERROR;
1073 }
1074 StoreInfo storeInfo;
1075 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
1076 storeInfo.bundleName = param.bundleName_;
1077 storeInfo.storeName = RemoveSuffix(param.storeName_);
1078 auto [instanceId, user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_);
1079 storeInfo.instanceId = instanceId;
1080 storeInfo.user = user;
1081 storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
1082
1083 DataChangeEvent::EventInfo eventInfo;
1084 eventInfo.isFull = rdbNotifyConfig.isFull_;
1085 for (const auto& [key, value] : rdbChangedData.tableData) {
1086 DataChangeEvent::TableChangeProperties tableChangeProperties = {value.isTrackedDataChange};
1087 eventInfo.tableProperties.insert_or_assign(key, std::move(tableChangeProperties));
1088 }
1089
1090 if (IsPostImmediately(IPCSkeleton::GetCallingPid(), rdbNotifyConfig, storeInfo, eventInfo, param.storeName_)) {
1091 auto evt = std::make_unique<DataChangeEvent>(std::move(storeInfo), std::move(eventInfo));
1092 EventCenter::GetInstance().PostEvent(std::move(evt));
1093 }
1094
1095 return RDB_OK;
1096 }
1097
IsPostImmediately(const int32_t callingPid,const RdbNotifyConfig & rdbNotifyConfig,StoreInfo & storeInfo,DataChangeEvent::EventInfo & eventInfo,const std::string & storeName)1098 bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig,
1099 StoreInfo &storeInfo, DataChangeEvent::EventInfo &eventInfo, const std::string &storeName)
1100 {
1101 bool postImmediately = false;
1102 heartbeatTaskIds_.Compute(callingPid, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo,
1103 &storeName](const int32_t &key, std::map<std::string, ExecutorPool::TaskId> &tasks) {
1104 auto iter = tasks.find(storeName);
1105 ExecutorPool::TaskId taskId = ExecutorPool::INVALID_TASK_ID;
1106 if (iter != tasks.end()) {
1107 taskId = iter->second;
1108 }
1109 if (rdbNotifyConfig.delay_ == 0) {
1110 if (taskId != ExecutorPool::INVALID_TASK_ID && executors_ != nullptr) {
1111 executors_->Remove(taskId);
1112 }
1113 postImmediately = true;
1114 tasks.erase(storeName);
1115 return !tasks.empty();
1116 }
1117
1118 if (executors_ != nullptr) {
1119 auto task = [storeInfoInner = storeInfo, eventInfoInner = eventInfo]() {
1120 auto evt = std::make_unique<DataChangeEvent>(std::move(storeInfoInner), std::move(eventInfoInner));
1121 EventCenter::GetInstance().PostEvent(std::move(evt));
1122 };
1123 if (taskId == ExecutorPool::INVALID_TASK_ID) {
1124 taskId = executors_->Schedule(std::chrono::milliseconds(rdbNotifyConfig.delay_), task);
1125 } else {
1126 taskId = executors_->Reset(taskId, std::chrono::milliseconds(rdbNotifyConfig.delay_));
1127 }
1128 }
1129 tasks.insert_or_assign(storeName, taskId);
1130 return true;
1131 });
1132 return postImmediately;
1133 }
1134
SetSearchable(const RdbSyncerParam & param,bool isSearchable)1135 int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearchable)
1136 {
1137 XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
1138 if (!CheckAccess(param.bundleName_, param.storeName_)) {
1139 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
1140 Anonymous::Change(param.storeName_).c_str());
1141 return RDB_ERROR;
1142 }
1143 SetSearchableEvent::EventInfo eventInfo;
1144 eventInfo.isSearchable = isSearchable;
1145 return PostSearchEvent(CloudEvent::SET_SEARCHABLE, param, eventInfo);
1146 }
1147
PostSearchEvent(int32_t evtId,const RdbSyncerParam & param,SetSearchableEvent::EventInfo & eventInfo)1148 int32_t RdbServiceImpl::PostSearchEvent(int32_t evtId, const RdbSyncerParam& param,
1149 SetSearchableEvent::EventInfo &eventInfo)
1150 {
1151 StoreInfo storeInfo;
1152 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
1153 storeInfo.bundleName = param.bundleName_;
1154 storeInfo.storeName = RemoveSuffix(param.storeName_);
1155 auto [instanceId, user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_);
1156 storeInfo.instanceId = instanceId;
1157 storeInfo.user = user;
1158 storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
1159
1160 auto evt = std::make_unique<SetSearchableEvent>(std::move(storeInfo), std::move(eventInfo), evtId);
1161 EventCenter::GetInstance().PostEvent(std::move(evt));
1162 return RDB_OK;
1163 }
1164
Disable(const RdbSyncerParam & param)1165 int32_t RdbServiceImpl::Disable(const RdbSyncerParam& param)
1166 {
1167 auto tokenId = IPCSkeleton::GetCallingTokenID();
1168 auto storeId = RemoveSuffix(param.storeName_);
1169 AutoCache::GetInstance().Disable(tokenId, storeId);
1170 return RDB_OK;
1171 }
1172
Enable(const RdbSyncerParam & param)1173 int32_t RdbServiceImpl::Enable(const RdbSyncerParam& param)
1174 {
1175 auto tokenId = IPCSkeleton::GetCallingTokenID();
1176 auto storeId = RemoveSuffix(param.storeName_);
1177 AutoCache::GetInstance().Enable(tokenId, storeId);
1178 return RDB_OK;
1179 }
1180
GetPassword(const RdbSyncerParam & param,std::vector<uint8_t> & password)1181 int32_t RdbServiceImpl::GetPassword(const RdbSyncerParam ¶m, std::vector<uint8_t> &password)
1182 {
1183 if (!CheckAccess(param.bundleName_, param.storeName_)) {
1184 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
1185 Anonymous::Change(param.storeName_).c_str());
1186 return RDB_ERROR;
1187 }
1188 auto meta = GetStoreMetaData(param);
1189 SecretKeyMetaData secretKey;
1190 if (!MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKey, true)) {
1191 ZLOGE("bundleName:%{public}s, storeName:%{public}s. no meta", param.bundleName_.c_str(),
1192 Anonymous::Change(param.storeName_).c_str());
1193 return RDB_NO_META;
1194 }
1195
1196 if (!CryptoManager::GetInstance().Decrypt(secretKey.sKey, password)) {
1197 ZLOGE("bundleName:%{public}s, storeName:%{public}s. decrypt err", param.bundleName_.c_str(),
1198 Anonymous::Change(param.storeName_).c_str());
1199 return RDB_ERROR;
1200 }
1201 return RDB_OK;
1202 }
1203
GetStoreInfo(const RdbSyncerParam & param)1204 StoreInfo RdbServiceImpl::GetStoreInfo(const RdbSyncerParam ¶m)
1205 {
1206 StoreInfo storeInfo;
1207 storeInfo.bundleName = param.bundleName_;
1208 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
1209 storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId);
1210 storeInfo.storeName = RemoveSuffix(param.storeName_);
1211 return storeInfo;
1212 }
1213
LockCloudContainer(const RdbSyncerParam & param)1214 std::pair<int32_t, uint32_t> RdbServiceImpl::LockCloudContainer(const RdbSyncerParam ¶m)
1215 {
1216 std::pair<int32_t, uint32_t> result { RDB_ERROR, 0 };
1217 if (!CheckAccess(param.bundleName_, param.storeName_)) {
1218 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
1219 Anonymous::Change(param.storeName_).c_str());
1220 return result;
1221 }
1222
1223 auto storeInfo = GetStoreInfo(param);
1224
1225 CloudLockEvent::Callback callback = [&result](int32_t status, uint32_t expiredTime) {
1226 result.first = status;
1227 result.second = expiredTime;
1228 };
1229 auto evt = std::make_unique<CloudLockEvent>(CloudEvent::LOCK_CLOUD_CONTAINER, std::move(storeInfo), callback);
1230 EventCenter::GetInstance().PostEvent(std::move(evt));
1231 return result;
1232 }
1233
UnlockCloudContainer(const RdbSyncerParam & param)1234 int32_t RdbServiceImpl::UnlockCloudContainer(const RdbSyncerParam ¶m)
1235 {
1236 int32_t result = RDB_ERROR;
1237 if (!CheckAccess(param.bundleName_, param.storeName_)) {
1238 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
1239 Anonymous::Change(param.storeName_).c_str());
1240 return result;
1241 }
1242
1243 auto storeInfo = GetStoreInfo(param);
1244
1245 CloudLockEvent::Callback callback = [&result](int32_t status, uint32_t expiredTime) {
1246 (void)expiredTime;
1247 result = status;
1248 };
1249 auto evt = std::make_unique<CloudLockEvent>(CloudEvent::UNLOCK_CLOUD_CONTAINER, std::move(storeInfo), callback);
1250 EventCenter::GetInstance().PostEvent(std::move(evt));
1251 return result;
1252 }
1253
GetDebugInfo(const RdbSyncerParam & param,std::map<std::string,RdbDebugInfo> & debugInfo)1254 int32_t RdbServiceImpl::GetDebugInfo(const RdbSyncerParam ¶m, std::map<std::string, RdbDebugInfo> &debugInfo)
1255 {
1256 if (!CheckAccess(param.bundleName_, param.storeName_)) {
1257 ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
1258 Anonymous::Change(param.storeName_).c_str());
1259 return RDB_ERROR;
1260 }
1261 auto metaData = GetStoreMetaData(param);
1262 auto isCreated = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true);
1263 if (!isCreated) {
1264 ZLOGE("bundleName:%{public}s, storeName:%{public}s. no meta data", param.bundleName_.c_str(),
1265 Anonymous::Change(param.storeName_).c_str());
1266 return RDB_OK;
1267 }
1268 DistributedData::StoreDebugInfo debugMeta;
1269 isCreated = MetaDataManager::GetInstance().LoadMeta(metaData.GetDebugInfoKey(), debugMeta, true);
1270 if (!isCreated) {
1271 return RDB_OK;
1272 }
1273
1274 for (auto &[name, fileDebug] : debugMeta.fileInfos) {
1275 RdbDebugInfo rdbInfo;
1276 rdbInfo.inode_ = fileDebug.inode;
1277 rdbInfo.size_ = fileDebug.size;
1278 rdbInfo.dev_ = fileDebug.dev;
1279 rdbInfo.mode_ = fileDebug.mode;
1280 rdbInfo.uid_ = fileDebug.uid;
1281 rdbInfo.gid_ = fileDebug.gid;
1282 debugInfo.insert(std::pair{ name, rdbInfo });
1283 }
1284 return RDB_OK;
1285 }
1286
SaveDebugInfo(const StoreMetaData & metaData,const RdbSyncerParam & param)1287 int32_t RdbServiceImpl::SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m)
1288 {
1289 if (param.infos_.empty()) {
1290 return RDB_OK;
1291 }
1292 DistributedData::StoreDebugInfo debugMeta;
1293 for (auto &[name, info] : param.infos_) {
1294 DistributedData::StoreDebugInfo::FileInfo fileInfo;
1295 fileInfo.inode = info.inode_;
1296 fileInfo.size = info.size_;
1297 fileInfo.dev = info.dev_;
1298 fileInfo.mode = info.mode_;
1299 fileInfo.uid = info.uid_;
1300 fileInfo.gid = info.gid_;
1301 debugMeta.fileInfos.insert(std::pair{name, fileInfo});
1302 }
1303 MetaDataManager::GetInstance().SaveMeta(metaData.GetDebugInfoKey(), debugMeta, true);
1304 return RDB_OK;
1305 }
1306 } // namespace OHOS::DistributedRdb