• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "accesstoken_kit.h"
18 #include "account/account_delegate.h"
19 #include "checker/checker_manager.h"
20 #include "cloud/cloud_event.h"
21 #include "cloud/change_event.h"
22 #include "communicator/device_manager_adapter.h"
23 #include "crypto_manager.h"
24 #include "directory/directory_manager.h"
25 #include "eventcenter/event_center.h"
26 #include "ipc_skeleton.h"
27 #include "log_print.h"
28 #include "metadata/appid_meta_data.h"
29 #include "metadata/meta_data_manager.h"
30 #include "metadata/store_meta_data.h"
31 #include "rdb_watcher.h"
32 #include "rdb_notifier_proxy.h"
33 #include "rdb_query.h"
34 #include "store/general_store.h"
35 #include "types_export.h"
36 #include "utils/anonymous.h"
37 #include "utils/constant.h"
38 #include "utils/converter.h"
39 #include "cloud/schema_meta.h"
40 #include "rdb_general_store.h"
41 #include "rdb_result_set_impl.h"
42 using OHOS::DistributedKv::AccountDelegate;
43 using OHOS::DistributedData::CheckerManager;
44 using OHOS::DistributedData::MetaDataManager;
45 using OHOS::DistributedData::StoreMetaData;
46 using OHOS::DistributedData::Anonymous;
47 using namespace OHOS::DistributedData;
48 using namespace OHOS::Security::AccessToken;
49 using DistributedDB::RelationalStoreManager;
50 using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter;
51 using system_clock = std::chrono::system_clock;
52 
53 constexpr uint32_t ITERATE_TIMES = 10000;
54 namespace OHOS::DistributedRdb {
55 __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_;
Factory()56 RdbServiceImpl::Factory::Factory()
57 {
58     FeatureSystem::GetInstance().RegisterCreator(RdbServiceImpl::SERVICE_NAME, [this]() {
59         if (product_ == nullptr) {
60             product_ = std::make_shared<RdbServiceImpl>();
61         }
62         return product_;
63     });
64     AutoCache::GetInstance().RegCreator(RDB_DEVICE_COLLABORATION, [](const StoreMetaData &metaData) -> GeneralStore* {
65         return new (std::nothrow) RdbGeneralStore(metaData);
66     });
67 }
68 
~Factory()69 RdbServiceImpl::Factory::~Factory()
70 {
71 }
72 
RdbServiceImpl()73 RdbServiceImpl::RdbServiceImpl()
74 {
75     ZLOGI("construct");
76     DistributedDB::RelationalStoreManager::SetAutoLaunchRequestCallback(
77         [this](const std::string& identifier, DistributedDB::AutoLaunchParam &param) {
78             return ResolveAutoLaunch(identifier, param);
79         });
80     auto process = [this](const Event &event) {
81         auto &evt = static_cast<const CloudEvent &>(event);
82         auto storeInfo = evt.GetStoreInfo();
83         StoreMetaData meta;
84         meta.storeId = storeInfo.storeName;
85         meta.bundleName = storeInfo.bundleName;
86         meta.user = std::to_string(storeInfo.user);
87         meta.instanceId = storeInfo.instanceId;
88         meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
89         if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) {
90             ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(),
91                 meta.GetStoreAlias().c_str());
92             return;
93         }
94         auto watchers = GetWatchers(meta.tokenId, meta.storeId);
95         auto store = AutoCache::GetInstance().GetStore(meta, watchers);
96         if (store == nullptr) {
97             ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str());
98             return;
99         }
100     };
101     EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC, process);
102 }
103 
ResolveAutoLaunch(const std::string & identifier,DistributedDB::AutoLaunchParam & param)104 int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam &param)
105 {
106     std::string identifierHex = TransferStringToHex(identifier);
107     ZLOGI("%{public}.6s", identifierHex.c_str());
108     std::vector<StoreMetaData> entries;
109     auto localId = DmAdapter::GetInstance().GetLocalDevice().uuid;
110     if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ localId }), entries)) {
111         ZLOGE("get meta failed");
112         return false;
113     }
114     ZLOGI("size=%{public}d", static_cast<int32_t>(entries.size()));
115     for (const auto& entry : entries) {
116         if (entry.storeType != RDB_DEVICE_COLLABORATION) {
117             continue;
118         }
119 
120         auto aIdentifier = DistributedDB::RelationalStoreManager::GetRelationalStoreIdentifier(
121             entry.user, entry.appId, entry.storeId);
122         ZLOGI("%{public}s %{public}s %{public}s",
123             entry.user.c_str(), entry.appId.c_str(), Anonymous::Change(entry.storeId).c_str());
124         if (aIdentifier != identifier) {
125             continue;
126         }
127         ZLOGI("find identifier %{public}s", Anonymous::Change(entry.storeId).c_str());
128         param.userId = entry.user;
129         param.appId = entry.appId;
130         param.storeId = entry.storeId;
131         param.path = entry.dataDir;
132         param.option.storeObserver = nullptr;
133         param.option.isEncryptedDb = entry.isEncrypt;
134         if (entry.isEncrypt) {
135             param.option.iterateTimes = ITERATE_TIMES;
136             param.option.cipher = DistributedDB::CipherType::AES_256_GCM;
137             GetPassword(entry, param.option.passwd);
138         }
139         AutoCache::GetInstance().GetStore(entry, GetWatchers(entry.tokenId, entry.storeId));
140         return true;
141     }
142     ZLOGE("not find identifier");
143     return false;
144 }
145 
OnAppExit(pid_t uid,pid_t pid,uint32_t tokenId,const std::string & bundleName)146 int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName)
147 {
148     OnClientDied(pid);
149     return E_OK;
150 }
151 
OnClientDied(pid_t pid)152 void RdbServiceImpl::OnClientDied(pid_t pid)
153 {
154     ZLOGI("client dead pid=%{public}d", pid);
155     syncAgents_.EraseIf([pid](auto &key, SyncAgent &agent) { return agent.pid_ == pid; });
156 }
157 
CheckAccess(const std::string & bundleName,const std::string & storeName)158 bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::string& storeName)
159 {
160     CheckerManager::StoreInfo storeInfo;
161     storeInfo.uid = IPCSkeleton::GetCallingUid();
162     storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
163     storeInfo.bundleName = bundleName;
164     storeInfo.storeId = RemoveSuffix(storeName);
165     auto [instanceId, user] = GetInstIndexAndUser(storeInfo.tokenId, storeInfo.bundleName);
166     if (instanceId != 0) {
167         return false;
168     }
169     return !CheckerManager::GetInstance().GetAppId(storeInfo).empty();
170 }
171 
ObtainDistributedTableName(const std::string & device,const std::string & table)172 std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table)
173 {
174     ZLOGI("device=%{public}s table=%{public}s", Anonymous::Change(device).c_str(), table.c_str());
175     auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(device);
176     if (uuid.empty()) {
177         ZLOGE("get uuid failed");
178         return "";
179     }
180     return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table);
181 }
182 
InitNotifier(const RdbSyncerParam & param,const sptr<IRemoteObject> notifier)183 int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam &param, const sptr<IRemoteObject> notifier)
184 {
185     if (!CheckAccess(param.bundleName_, "")) {
186         ZLOGE("permission error");
187         return RDB_ERROR;
188     }
189     if (notifier == nullptr) {
190         ZLOGE("notifier is null");
191         return RDB_ERROR;
192     }
193 
194     auto notifierProxy = iface_cast<RdbNotifierProxy>(notifier);
195     pid_t pid = IPCSkeleton::GetCallingPid();
196     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
197     syncAgents_.Compute(tokenId, [&param, notifierProxy, pid](auto, SyncAgent &agent) {
198         if (pid != agent.pid_) {
199             agent.ReInit(pid, param.bundleName_);
200         }
201         agent.SetNotifier(notifierProxy);
202         return true;
203     });
204     ZLOGI("success tokenId:%{public}x, pid=%{public}d", tokenId, pid);
205 
206     return RDB_OK;
207 }
208 
GetStore(const RdbSyncerParam & param)209 std::shared_ptr<DistributedData::GeneralStore> RdbServiceImpl::GetStore(const RdbSyncerParam &param)
210 {
211     StoreMetaData storeMetaData = GetStoreMetaData(param);
212     MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData);
213     auto watchers = GetWatchers(storeMetaData.tokenId, storeMetaData.storeId);
214     auto store = AutoCache::GetInstance().GetStore(storeMetaData, watchers);
215     if (store == nullptr) {
216         ZLOGE("store null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str());
217     }
218     return store;
219 }
220 
SetDistributedTables(const RdbSyncerParam & param,const std::vector<std::string> & tables,int32_t type)221 int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam &param, const std::vector<std::string> &tables,
222     int32_t type)
223 {
224     if (!CheckAccess(param.bundleName_, param.storeName_)) {
225         ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(),
226             Anonymous::Change(param.storeName_).c_str());
227         return RDB_ERROR;
228     }
229     auto store = GetStore(param);
230     if (store == nullptr) {
231         ZLOGE("bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(),
232             Anonymous::Change(param.storeName_).c_str());
233         return RDB_ERROR;
234     }
235     return store->SetDistributedTables(tables, type);
236 }
237 
OnAsyncComplete(uint32_t tokenId,uint32_t seqNum,Details && result)238 void RdbServiceImpl::OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result)
239 {
240     ZLOGI("tokenId=%{public}x seqnum=%{public}u", tokenId, seqNum);
241     auto [success, agent] = syncAgents_.Find(tokenId);
242     if (success && agent.notifier_ != nullptr) {
243         agent.notifier_->OnComplete(seqNum, std::move(result));
244     }
245 }
246 
TransferStringToHex(const std::string & origStr)247 std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr)
248 {
249     if (origStr.empty()) {
250         return "";
251     }
252     const char *hex = "0123456789abcdef";
253     std::string tmp;
254     for (auto item : origStr) {
255         auto currentByte = static_cast<uint8_t>(item);
256         tmp.push_back(hex[currentByte >> 4]); // high 4 bit to one hex.
257         tmp.push_back(hex[currentByte & 0x0F]); // low 4 bit to one hex.
258     }
259     return tmp;
260 }
261 
GetWatchers(uint32_t tokenId,const std::string & storeName)262 AutoCache::Watchers RdbServiceImpl::GetWatchers(uint32_t tokenId, const std::string &storeName)
263 {
264     auto [success, agent] = syncAgents_.Find(tokenId);
265     if (agent.watcher_ == nullptr) {
266         return {};
267     }
268     return { agent.watcher_ };
269 }
270 
RemoteQuery(const RdbSyncerParam & param,const std::string & device,const std::string & sql,const std::vector<std::string> & selectionArgs,sptr<IRemoteObject> & resultSet)271 int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql,
272                                     const std::vector<std::string>& selectionArgs, sptr<IRemoteObject>& resultSet)
273 {
274     if (!CheckAccess(param.bundleName_, param.storeName_)) {
275         ZLOGE("permission error");
276         return RDB_ERROR;
277     }
278     auto store = GetStore(param);
279     if (store == nullptr) {
280         ZLOGE("store is null");
281         return RDB_ERROR;
282     }
283     auto values = ValueProxy::Convert(selectionArgs);
284     RdbQuery rdbQuery(true);
285     rdbQuery.SetDevices({ device });
286     rdbQuery.SetSql(sql, std::move(values));
287     auto cursor = store->Query("", rdbQuery);
288     if (cursor == nullptr) {
289         ZLOGE("Query failed, cursor is null");
290         return RDB_ERROR;
291     }
292     resultSet = new (std::nothrow) RdbResultSetImpl(cursor);
293     if (resultSet == nullptr) {
294         ZLOGE("new resultSet failed");
295         return RDB_ERROR;
296     }
297     return RDB_OK;
298 }
299 
Sync(const RdbSyncerParam & param,const Option & option,const PredicatesMemo & predicates,const AsyncDetail & async)300 int32_t RdbServiceImpl::Sync(const RdbSyncerParam &param, const Option &option, const PredicatesMemo &predicates,
301                              const AsyncDetail &async)
302 {
303     if (!CheckAccess(param.bundleName_, param.storeName_)) {
304         ZLOGE("permission error");
305         return RDB_ERROR;
306     }
307     if (option.mode < DistributedData::GeneralStore::CLOUD_END &&
308         option.mode >= DistributedData::GeneralStore::CLOUD_BEGIN) {
309         DoCloudSync(param, option, predicates, async);
310         return RDB_OK;
311     }
312     return DoSync(param, option, predicates, async);
313 }
314 
DoSync(const RdbSyncerParam & param,const RdbService::Option & option,const PredicatesMemo & predicates,const AsyncDetail & async)315 int RdbServiceImpl::DoSync(const RdbSyncerParam &param, const RdbService::Option &option,
316     const PredicatesMemo &predicates, const AsyncDetail &async)
317 {
318     auto store = GetStore(param);
319     if (store == nullptr) {
320         return RDB_ERROR;
321     }
322     RdbQuery rdbQuery;
323     rdbQuery.MakeQuery(predicates);
324     if (!option.isAsync) {
325         Details details = {};
326         auto status = store->Sync(
327             DmAdapter::ToUUID(DmAdapter::GetInstance().GetRemoteDevices()), option.mode, rdbQuery,
328             [&details, &param](const GenDetails &result) mutable {
329                 ZLOGD("Sync complete, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(),
330                     Anonymous::Change(param.storeName_).c_str());
331                 details = HandleGenDetails(result);
332             },
333             true);
334         if (async != nullptr) {
335             async(std::move(details));
336         }
337         return status;
338     }
339     ZLOGD("seqNum=%{public}u", option.seqNum);
340     auto tokenId = IPCSkeleton::GetCallingTokenID();
341     return store->Sync(
342         DmAdapter::ToUUID(DmAdapter::GetInstance().GetRemoteDevices()), option.mode, rdbQuery,
343         [this, tokenId, seqNum = option.seqNum](const GenDetails &result) mutable {
344             OnAsyncComplete(tokenId, seqNum, HandleGenDetails(result));
345         },
346         false);
347 }
348 
DoCloudSync(const RdbSyncerParam & param,const RdbService::Option & option,const PredicatesMemo & predicates,const AsyncDetail & async)349 void RdbServiceImpl::DoCloudSync(const RdbSyncerParam &param, const RdbService::Option &option,
350     const PredicatesMemo &predicates, const AsyncDetail &async)
351 {
352     CloudEvent::StoreInfo storeInfo;
353     storeInfo.bundleName = param.bundleName_;
354     storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
355     storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId);
356     storeInfo.storeName = param.storeName_;
357     std::shared_ptr<RdbQuery> query = nullptr;
358     if (!predicates.tables_.empty()) {
359         query = std::make_shared<RdbQuery>();
360         query->FromTable(predicates.tables_);
361     }
362     GenAsync asyncCallback = [this, tokenId = storeInfo.tokenId, seqNum = option.seqNum](
363                                  const GenDetails &result) mutable {
364         OnAsyncComplete(tokenId, seqNum, HandleGenDetails(result));
365     };
366     GenAsync syncCallback = [async, &param](const GenDetails &details) {
367         ZLOGD("Cloud Sync complete, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(),
368             Anonymous::Change(param.storeName_).c_str());
369         if (async != nullptr) {
370             async(HandleGenDetails(details));
371         }
372     };
373 
374     auto info = ChangeEvent::EventInfo(option.mode, (option.isAsync ? 0 : WAIT_TIME),
375         (option.isAsync && option.seqNum == 0), query, (option.isAsync ? asyncCallback : syncCallback));
376     auto evt = std::make_unique<ChangeEvent>(std::move(storeInfo), std::move(info));
377     EventCenter::GetInstance().PostEvent(std::move(evt));
378 }
379 
Subscribe(const RdbSyncerParam & param,const SubscribeOption & option,RdbStoreObserver * observer)380 int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam &param, const SubscribeOption &option,
381     RdbStoreObserver *observer)
382 {
383     if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) {
384         ZLOGE("mode:%{public}d error", option.mode);
385         return RDB_ERROR;
386     }
387     pid_t pid = IPCSkeleton::GetCallingPid();
388     auto tokenId = IPCSkeleton::GetCallingTokenID();
389     bool isCreate = false;
390     syncAgents_.Compute(tokenId, [pid, &param, &isCreate](auto &key, SyncAgent &agent) {
391         if (pid != agent.pid_) {
392             agent.ReInit(pid, param.bundleName_);
393         }
394         if (agent.watcher_ == nullptr) {
395             isCreate = true;
396             agent.SetWatcher(std::make_shared<RdbWatcher>());
397         }
398         agent.count_++;
399         return true;
400     });
401     if (isCreate) {
402         AutoCache::GetInstance().SetObserver(tokenId, param.storeName_, GetWatchers(tokenId, param.storeName_));
403     }
404     return RDB_OK;
405 }
406 
UnSubscribe(const RdbSyncerParam & param,const SubscribeOption & option,RdbStoreObserver * observer)407 int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam &param, const SubscribeOption &option,
408     RdbStoreObserver *observer)
409 {
410     if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) {
411         ZLOGE("mode:%{public}d error", option.mode);
412         return RDB_ERROR;
413     }
414     bool destroyed = false;
415     auto tokenId = IPCSkeleton::GetCallingTokenID();
416     syncAgents_.ComputeIfPresent(tokenId, [&destroyed](auto &key, SyncAgent &agent) {
417         if (agent.count_ > 0) {
418             agent.count_--;
419         }
420         if (agent.count_ == 0) {
421             destroyed = true;
422             agent.SetWatcher(nullptr);
423         }
424         return true;
425     });
426     if (destroyed) {
427         AutoCache::GetInstance().SetObserver(tokenId, param.storeName_, GetWatchers(tokenId, param.storeName_));
428     }
429     return RDB_OK;
430 }
431 
OnInitialize()432 int32_t RdbServiceImpl::OnInitialize()
433 {
434     return RDB_OK;
435 }
436 
Delete(const RdbSyncerParam & param)437 int32_t RdbServiceImpl::Delete(const RdbSyncerParam &param)
438 {
439     auto tokenId = IPCSkeleton::GetCallingTokenID();
440     AutoCache::GetInstance().CloseStore(tokenId, param.storeName_);
441     RdbSyncerParam tmpParam = param;
442     HapTokenInfo hapTokenInfo;
443     AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo);
444     tmpParam.bundleName_ = hapTokenInfo.bundleName;
445     auto storeMeta = GetStoreMetaData(tmpParam);
446     MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey());
447     MetaDataManager::GetInstance().DelMeta(storeMeta.GetSecretKey(), true);
448     MetaDataManager::GetInstance().DelMeta(storeMeta.GetStrategyKey());
449     MetaDataManager::GetInstance().DelMeta(storeMeta.GetKeyLocal(), true);
450     return RDB_OK;
451 }
452 
GetSchema(const RdbSyncerParam & param)453 int32_t RdbServiceImpl::GetSchema(const RdbSyncerParam &param)
454 {
455     if (!CheckAccess(param.bundleName_, param.storeName_)) {
456         ZLOGE("permission error");
457         return RDB_ERROR;
458     }
459     StoreMetaData storeMeta;
460     if (CreateMetaData(param, storeMeta) != RDB_OK) {
461         return RDB_ERROR;
462     }
463 
464     if (executors_ != nullptr) {
465         CloudEvent::StoreInfo storeInfo;
466         storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
467         storeInfo.bundleName = param.bundleName_;
468         storeInfo.storeName = RemoveSuffix(param.storeName_);
469         auto [instanceId,  user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_);
470         storeInfo.instanceId = instanceId;
471         storeInfo.user = user;
472         executors_->Execute([storeInfo]() {
473             auto event = std::make_unique<CloudEvent>(CloudEvent::GET_SCHEMA, std::move(storeInfo));
474             EventCenter::GetInstance().PostEvent(move(event));
475             return;
476         });
477     }
478     return RDB_OK;
479 }
480 
GetStoreMetaData(const RdbSyncerParam & param)481 StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam &param)
482 {
483     StoreMetaData metaData;
484     metaData.uid = IPCSkeleton::GetCallingUid();
485     metaData.tokenId = IPCSkeleton::GetCallingTokenID();
486     auto [instanceId, user] = GetInstIndexAndUser(metaData.tokenId, param.bundleName_);
487     metaData.instanceId = instanceId;
488     metaData.bundleName = param.bundleName_;
489     metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid;
490     metaData.storeId = RemoveSuffix(param.storeName_);
491     metaData.user = std::to_string(user);
492     metaData.storeType = param.type_;
493     metaData.securityLevel = param.level_;
494     metaData.area = param.area_;
495     metaData.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(metaData));
496     metaData.appType = "harmony";
497     metaData.hapName = param.hapName_;
498     metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_;
499     metaData.account = AccountDelegate::GetInstance()->GetCurrentAccountId();
500     metaData.isEncrypt = param.isEncrypt_;
501     return metaData;
502 }
503 
CreateMetaData(const RdbSyncerParam & param,StoreMetaData & old)504 int32_t RdbServiceImpl::CreateMetaData(const RdbSyncerParam &param, StoreMetaData &old)
505 {
506     auto meta = GetStoreMetaData(param);
507     bool isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old);
508     if (isCreated && (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) ||
509                          old.area != meta.area)) {
510         ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
511               "area:%{public}d->%{public}d",
512             meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType,
513             old.isEncrypt, meta.isEncrypt, old.area, meta.area);
514         return RDB_ERROR;
515     }
516     if (!isCreated || meta != old) {
517         Upgrade(param, old);
518         ZLOGD("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
519               "area:%{public}d->%{public}d",
520             meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType,
521             old.isEncrypt, meta.isEncrypt, old.area, meta.area);
522         MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta);
523     }
524     AppIDMetaData appIdMeta;
525     appIdMeta.bundleName = meta.bundleName;
526     appIdMeta.appId = meta.appId;
527     if (!MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true)) {
528         ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d "
529               "area:%{public}d->%{public}d",
530             meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType,
531             old.isEncrypt, meta.isEncrypt, old.area, meta.area);
532         return RDB_ERROR;
533     }
534     if (!param.isEncrypt_ || param.password_.empty()) {
535         return RDB_OK;
536     }
537     return SetSecretKey(param, meta);
538 }
539 
SetSecretKey(const RdbSyncerParam & param,const StoreMetaData & meta)540 int32_t RdbServiceImpl::SetSecretKey(const RdbSyncerParam &param, const StoreMetaData &meta)
541 {
542     SecretKeyMetaData newSecretKey;
543     newSecretKey.storeType = meta.storeType;
544     newSecretKey.sKey = CryptoManager::GetInstance().Encrypt(param.password_);
545     if (newSecretKey.sKey.empty()) {
546         ZLOGE("encrypt work key error.");
547         return RDB_ERROR;
548     }
549     auto time = system_clock::to_time_t(system_clock::now());
550     newSecretKey.time = { reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time) };
551     return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), newSecretKey, true) ? RDB_OK : RDB_ERROR;
552 }
553 
Upgrade(const RdbSyncerParam & param,const StoreMetaData & old)554 int32_t RdbServiceImpl::Upgrade(const RdbSyncerParam &param, const StoreMetaData &old)
555 {
556     if (old.storeType == RDB_DEVICE_COLLABORATION && old.version < StoreMetaData::UUID_CHANGED_TAG) {
557         auto store = GetStore(param);
558         if (store == nullptr) {
559             ZLOGE("store is null, bundleName:%{public}s storeName:%{public}s", param.bundleName_.c_str(),
560                 Anonymous::Change(param.storeName_).c_str());
561             return RDB_ERROR;
562         }
563         return store->Clean({}, GeneralStore::CleanMode::NEARBY_DATA, "") == GeneralError::E_OK ? RDB_OK : RDB_ERROR;
564     }
565     return RDB_OK;
566 }
567 
HandleGenDetails(const GenDetails & details)568 Details RdbServiceImpl::HandleGenDetails(const GenDetails &details)
569 {
570     Details dbDetails;
571     for (const auto& [id, detail] : details) {
572         auto &dbDetail = dbDetails[id];
573         dbDetail.progress = detail.progress;
574         dbDetail.code = detail.code;
575         for (auto &[name, table] : detail.details) {
576             auto &dbTable = dbDetail.details[name];
577             Constant::Copy(&dbTable, &table);
578         }
579     }
580     return dbDetails;
581 }
582 
GetPassword(const StoreMetaData & metaData,DistributedDB::CipherPassword & password)583 bool RdbServiceImpl::GetPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password)
584 {
585     if (!metaData.isEncrypt) {
586         return true;
587     }
588 
589     std::string key = metaData.GetSecretKey();
590     DistributedData::SecretKeyMetaData secretKeyMeta;
591     MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true);
592     std::vector<uint8_t> decryptKey;
593     CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptKey);
594     if (password.SetValue(decryptKey.data(), decryptKey.size()) != DistributedDB::CipherPassword::OK) {
595         std::fill(decryptKey.begin(), decryptKey.end(), 0);
596         ZLOGE("Set secret key value failed. len is (%{public}d)", int32_t(decryptKey.size()));
597         return false;
598     }
599     std::fill(decryptKey.begin(), decryptKey.end(), 0);
600     return true;
601 }
602 
RemoveSuffix(const std::string & name)603 std::string RdbServiceImpl::RemoveSuffix(const std::string& name)
604 {
605     std::string suffix(".db");
606     auto pos = name.rfind(suffix);
607     if (pos == std::string::npos || pos < name.length() - suffix.length()) {
608         return name;
609     }
610     return std::string(name, 0, pos);
611 }
612 
GetInstIndexAndUser(uint32_t tokenId,const std::string & bundleName)613 std::pair<int32_t, int32_t> RdbServiceImpl::GetInstIndexAndUser(uint32_t tokenId, const std::string &bundleName)
614 {
615     if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
616         return { 0, 0 };
617     }
618 
619     HapTokenInfo tokenInfo;
620     tokenInfo.instIndex = -1;
621     int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
622     if (errCode != RET_SUCCESS) {
623         ZLOGE("GetHapTokenInfo error:%{public}d, tokenId:0x%{public}x appId:%{public}s", errCode, tokenId,
624             bundleName.c_str());
625         return { -1, -1 };
626     }
627     return { tokenInfo.instIndex, tokenInfo.userID };
628 }
629 
OnBind(const BindInfo & bindInfo)630 int32_t RdbServiceImpl::OnBind(const BindInfo &bindInfo)
631 {
632     executors_ = bindInfo.executors;
633     return 0;
634 }
635 
OnAppUninstall(const std::string & bundleName,int32_t user,int32_t index)636 int32_t RdbServiceImpl::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index)
637 {
638     return CloseStore(bundleName, user, index);
639 }
640 
OnAppUpdate(const std::string & bundleName,int32_t user,int32_t index)641 int32_t RdbServiceImpl::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index)
642 {
643     return CloseStore(bundleName, user, index);
644 }
645 
CloseStore(const std::string & bundleName,int32_t user,int32_t index) const646 int32_t RdbServiceImpl::CloseStore(const std::string &bundleName, int32_t user, int32_t index) const
647 {
648     std::string prefix = StoreMetaData::GetPrefix(
649         { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(user), "default", bundleName });
650     std::vector<StoreMetaData> storeMetaData;
651     if (!MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData)) {
652         ZLOGE("load meta failed! bundleName:%{public}s, user:%{public}d, index:%{public}d",
653             bundleName.c_str(), user, index);
654         return E_ERROR;
655     }
656     for (const auto &meta : storeMetaData) {
657         if (meta.storeType < StoreMetaData::STORE_RELATIONAL_BEGIN ||
658             meta.storeType > StoreMetaData::STORE_RELATIONAL_END) {
659             continue;
660         }
661         if (meta.instanceId == index && !meta.appId.empty() && !meta.storeId.empty()) {
662             AutoCache::GetInstance().CloseStore(meta.tokenId);
663             break;
664         }
665     }
666     return E_OK;
667 }
668 
ReInit(pid_t pid,const std::string & bundleName)669 void RdbServiceImpl::SyncAgent::ReInit(pid_t pid, const std::string &bundleName)
670 {
671     pid_ = pid;
672     count_ = 0;
673     bundleName_ = bundleName;
674     notifier_ = nullptr;
675     if (watcher_ != nullptr) {
676         watcher_->SetNotifier(nullptr);
677     }
678 }
679 
SetNotifier(sptr<RdbNotifierProxy> notifier)680 void RdbServiceImpl::SyncAgent::SetNotifier(sptr<RdbNotifierProxy> notifier)
681 {
682     notifier_ = notifier;
683     if (watcher_ != nullptr) {
684         watcher_->SetNotifier(notifier);
685     }
686 }
687 
SetWatcher(std::shared_ptr<RdbWatcher> watcher)688 void RdbServiceImpl::SyncAgent::SetWatcher(std::shared_ptr<RdbWatcher> watcher)
689 {
690     if (watcher_ != watcher) {
691         watcher_ = watcher;
692         if (watcher_ != nullptr) {
693             watcher_->SetNotifier(notifier_);
694         }
695     }
696 }
697 } // namespace OHOS::DistributedRdb
698