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