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 &param) {
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 &param)
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 &param, 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 &param)
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 &param, 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, [&notifier, 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, &notifiers](auto, SyncAgents &syncAgents) {
372         std::for_each(syncAgents.begin(), syncAgents.end(), [&storeName, &notifiers](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 &notifier : 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 &param, 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 &param, 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 &param, 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, &param](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 &param, 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, &param, &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 &param, 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, &param, &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 &param)
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 &param)
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 &param)
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 &param)
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 &param)
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 &param)
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 &param, 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 &param, 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>> &params)
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 &param, 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 &param, 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 &param)
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 &param)
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 &param)
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 &param, 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 &param)
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