/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "meta_info_manager.h" #include "anonymous_string.h" #include "capability_utils.h" #include "constants.h" #include "dh_context.h" #include "dh_utils_tool.h" #include "distributed_hardware_errno.h" #include "distributed_hardware_log.h" #include "distributed_hardware_manager.h" #include "task_executor.h" #include "task_factory.h" #include "task_board.h" namespace OHOS { namespace DistributedHardware { #undef DH_LOG_TAG #define DH_LOG_TAG "MetaInfoManager" MetaInfoManager::MetaInfoManager() : dbAdapterPtr_(nullptr) { DHLOGI("MetaInfoManager construction!"); } MetaInfoManager::~MetaInfoManager() { DHLOGI("MetaInfoManager destruction!"); } std::shared_ptr<MetaInfoManager> MetaInfoManager::GetInstance() { static std::shared_ptr<MetaInfoManager> instance = std::make_shared<MetaInfoManager>(); return instance; } MetaInfoManager::MetaInfoManagerEventHandler::MetaInfoManagerEventHandler( const std::shared_ptr<AppExecFwk::EventRunner> runner, std::shared_ptr<MetaInfoManager> metaInfoMgrPtr) : AppExecFwk::EventHandler(runner), metaInfoMgrWPtr_(metaInfoMgrPtr) { DHLOGI("Ctor MetaInfoManagerEventHandler"); } void MetaInfoManager::MetaInfoManagerEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) { uint32_t eventId = event->GetInnerEventId(); auto selfPtr = metaInfoMgrWPtr_.lock(); if (!selfPtr) { DHLOGE("Can not get strong self ptr"); return; } switch (eventId) { case EVENT_META_INFO_DB_RECOVER: selfPtr->SyncRemoteMetaInfos(); break; default: DHLOGE("event is undefined, id is %{public}d", eventId); break; } } std::shared_ptr<MetaInfoManager::MetaInfoManagerEventHandler> MetaInfoManager::GetEventHandler() { return this->eventHandler_; } int32_t MetaInfoManager::Init() { DHLOGI("MetaInfoManager instance init!"); std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); dbAdapterPtr_ = std::make_shared<DBAdapter>(APP_ID, GLOBAL_META_INFO, shared_from_this()); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } if (dbAdapterPtr_->Init(false, DistributedKv::DataType::TYPE_STATICS) != DH_FWK_SUCCESS) { DHLOGE("Init dbAdapterPtr_ failed"); return ERR_DH_FWK_RESOURCE_INIT_DB_FAILED; } std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true); eventHandler_ = std::make_shared<MetaInfoManager::MetaInfoManagerEventHandler>(runner, shared_from_this()); DHLOGI("MetaInfoManager instance init success"); return DH_FWK_SUCCESS; } int32_t MetaInfoManager::UnInit() { DHLOGI("MetaInfoManager UnInit"); std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return ERR_DH_FWK_RESOURCE_UNINIT_DB_FAILED; } dbAdapterPtr_->UnInit(); dbAdapterPtr_.reset(); return DH_FWK_SUCCESS; } int32_t MetaInfoManager::AddMetaCapInfos(const std::vector<std::shared_ptr<MetaCapabilityInfo>> &metaCapInfos) { if (metaCapInfos.empty() || metaCapInfos.size() > MAX_DB_RECORD_SIZE) { DHLOGE("MetaCapInfos is empty or too large!"); return ERR_DH_FWK_RESOURCE_RES_DB_DATA_INVALID; } std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } std::vector<std::string> keys; std::vector<std::string> values; std::string key; std::string data; for (auto &metaCapInfo : metaCapInfos) { if (metaCapInfo == nullptr) { continue; } key = metaCapInfo->GetKey(); globalMetaInfoMap_[key] = metaCapInfo; if (dbAdapterPtr_->GetDataByKey(key, data) == DH_FWK_SUCCESS && data == metaCapInfo->ToJsonString()) { DHLOGI("this record is exist, Key: %{public}s", metaCapInfo->GetAnonymousKey().c_str()); continue; } DHLOGI("AddMetaCapability, Key: %{public}s", metaCapInfo->GetAnonymousKey().c_str()); keys.push_back(key); values.push_back(metaCapInfo->ToJsonString()); } if (keys.empty() || values.empty()) { DHLOGD("Records are empty, No need add data to db!"); return DH_FWK_SUCCESS; } if (dbAdapterPtr_->PutDataBatch(keys, values) != DH_FWK_SUCCESS) { DHLOGE("Fail to storage batch to kv"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL; } return DH_FWK_SUCCESS; } int32_t MetaInfoManager::SyncMetaInfoFromDB(const std::string &udidHash) { if (!IsHashSizeValid(udidHash)) { return ERR_DH_FWK_PARA_INVALID; } DHLOGI("Sync MetaInfo from DB, udidHash: %{public}s", GetAnonyString(udidHash).c_str()); std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } std::vector<std::string> dataVector; if (dbAdapterPtr_->GetDataByKeyPrefix(udidHash, dataVector) != DH_FWK_SUCCESS) { DHLOGE("Query Metadata from DB by udidHash failed, udidHash: %{public}s", GetAnonyString(udidHash).c_str()); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL; } if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) { DHLOGE("dataVector size: %{public}zu is invalid, maybe empty or too large.", dataVector.size()); return ERR_DH_FWK_RESOURCE_RES_DB_DATA_INVALID; } for (const auto &data : dataVector) { std::shared_ptr<MetaCapabilityInfo> metaCapInfo; if (GetMetaCapByValue(data, metaCapInfo) != DH_FWK_SUCCESS) { DHLOGE("Get capability ptr by value failed"); continue; } globalMetaInfoMap_[metaCapInfo->GetKey()] = metaCapInfo; } return DH_FWK_SUCCESS; } int32_t MetaInfoManager::SyncRemoteMetaInfos() { DHLOGI("Sync full remote device Metainfo from DB"); std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } std::vector<std::string> udidHashVec; DHContext::GetInstance().GetOnlineDeviceUdidHash(udidHashVec); for (const auto &udidHash : udidHashVec) { std::vector<std::string> dataVector; if (dbAdapterPtr_->GetDataByKeyPrefix(udidHash, dataVector) != DH_FWK_SUCCESS) { DHLOGE("Query the udidHash: %{public}s data from DB failed", GetAnonyString(udidHash).c_str()); continue; } if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) { DHLOGE("dataVector size: %{public}zu is invalid, maybe empty or too large.", dataVector.size()); continue; } for (const auto &data : dataVector) { std::shared_ptr<MetaCapabilityInfo> metaCapInfo; if (GetMetaCapByValue(data, metaCapInfo) != DH_FWK_SUCCESS) { DHLOGE("Get Metainfo ptr by value failed"); continue; } const std::string &udidHash = metaCapInfo->GetUdidHash(); const std::string &localUdidHash = DHContext::GetInstance().GetDeviceInfo().udidHash; if (udidHash.compare(localUdidHash) == 0) { DHLOGE("device MetaInfo not need sync from db"); continue; } globalMetaInfoMap_[metaCapInfo->GetKey()] = metaCapInfo; } } return DH_FWK_SUCCESS; } int32_t MetaInfoManager::GetDataByKeyPrefix(const std::string &keyPrefix, MetaCapInfoMap &metaCapMap) { if (!IsKeySizeValid(keyPrefix)) { return ERR_DH_FWK_PARA_INVALID; } std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } std::vector<std::string> dataVector; if (dbAdapterPtr_->GetDataByKeyPrefix(keyPrefix, dataVector) != DH_FWK_SUCCESS) { DHLOGE("Query metaInfo from db failed, keyPrefix: %{public}s", GetAnonyString(keyPrefix).c_str()); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL; } if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) { DHLOGE("On dataVector error, maybe empty or too large."); return ERR_DH_FWK_RESOURCE_RES_DB_DATA_INVALID; } for (const auto &data : dataVector) { std::shared_ptr<MetaCapabilityInfo> metaCapInfo; if (GetMetaCapByValue(data, metaCapInfo) != DH_FWK_SUCCESS) { DHLOGE("Get Metainfo ptr by value failed"); continue; } metaCapMap[metaCapInfo->GetKey()] = metaCapInfo; } return DH_FWK_SUCCESS; } int32_t MetaInfoManager::RemoveMetaInfoByKey(const std::string &key) { if (!IsKeySizeValid(key)) { return ERR_DH_FWK_PARA_INVALID; } DHLOGI("Remove device metaInfo, key: %{public}s", GetAnonyString(key).c_str()); std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } globalMetaInfoMap_.erase(key); if (dbAdapterPtr_->RemoveDataByKey(key) != DH_FWK_SUCCESS) { DHLOGE("Remove device metaData failed, key: %{public}s", GetAnonyString(key).c_str()); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL; } return DH_FWK_SUCCESS; } int32_t MetaInfoManager::GetMetaCapInfo(const std::string &udidHash, const std::string &dhId, std::shared_ptr<MetaCapabilityInfo> &metaCapPtr) { if (!IsHashSizeValid(udidHash) || !IsIdLengthValid(dhId)) { return ERR_DH_FWK_PARA_INVALID; } std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); std::string key = GetCapabilityKey(udidHash, dhId); if (globalMetaInfoMap_.find(key) == globalMetaInfoMap_.end()) { DHLOGE("Can not find capability In globalMetaInfoMap_: %{public}s", GetAnonyString(udidHash).c_str()); return ERR_DH_FWK_RESOURCE_CAPABILITY_MAP_NOT_FOUND; } metaCapPtr = globalMetaInfoMap_[key]; return DH_FWK_SUCCESS; } void MetaInfoManager::GetMetaCapInfosByUdidHash(const std::string &udidHash, std::vector<std::shared_ptr<MetaCapabilityInfo>> &metaCapInfos) { if (!IsHashSizeValid(udidHash)) { return; } std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); for (auto &metaCapInfo : globalMetaInfoMap_) { if (IsCapKeyMatchDeviceId(metaCapInfo.first, udidHash)) { metaCapInfos.emplace_back(metaCapInfo.second); } } } int32_t MetaInfoManager::GetMetaCapByValue(const std::string &value, std::shared_ptr<MetaCapabilityInfo> &metaCapPtr) { if (!IsMessageLengthValid(value)) { return ERR_DH_FWK_PARA_INVALID; } if (metaCapPtr == nullptr) { metaCapPtr = std::make_shared<MetaCapabilityInfo>(); } return metaCapPtr->FromJsonString(value); } int32_t MetaInfoManager::GetMetaDataByDHType(const DHType dhType, MetaCapInfoMap &metaInfoMap) { std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); for (const auto &metaCapInfo : globalMetaInfoMap_) { if (metaCapInfo.second->GetDHType() != dhType) { continue; } metaInfoMap[metaCapInfo.first] = metaCapInfo.second; } return DH_FWK_SUCCESS; } int32_t MetaInfoManager::SyncDataByNetworkId(const std::string &networkId) { if (!IsIdLengthValid(networkId)) { DHLOGE("networId: %{public}s is invalid", GetAnonyString(networkId).c_str()); return ERR_DH_FWK_PARA_INVALID; } if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr is null"); return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL; } dbAdapterPtr_->SyncDataByNetworkId(networkId); return DH_FWK_SUCCESS; } void MetaInfoManager::OnChange(const DistributedKv::ChangeNotification &changeNotification) { DHLOGI("MetaInfoManager: DB data OnChange"); if (!changeNotification.GetInsertEntries().empty() && changeNotification.GetInsertEntries().size() <= MAX_DB_RECORD_SIZE) { DHLOGI("MetaInfoManager Handle capability data add change"); HandleMetaCapabilityAddChange(changeNotification.GetInsertEntries()); } if (!changeNotification.GetUpdateEntries().empty() && changeNotification.GetUpdateEntries().size() <= MAX_DB_RECORD_SIZE) { DHLOGI("MetaInfoManager Handle capability data update change"); HandleMetaCapabilityUpdateChange(changeNotification.GetUpdateEntries()); } if (!changeNotification.GetDeleteEntries().empty() && changeNotification.GetDeleteEntries().size() <= MAX_DB_RECORD_SIZE) { DHLOGI("MetaInfoManager Handle capability data delete change"); HandleMetaCapabilityDeleteChange(changeNotification.GetDeleteEntries()); } } void MetaInfoManager::OnChange(const DistributedKv::DataOrigin &origin, Keys &&keys) { DHLOGI("MetaInfoManager: Cloud data OnChange."); std::vector<DistributedKv::Entry> insertRecords = GetEntriesByKeys(keys[ChangeOp::OP_INSERT]); if (!insertRecords.empty() && insertRecords.size() <= MAX_DB_RECORD_SIZE) { DHLOGI("MetaInfoManager Handle capability data add change"); HandleMetaCapabilityAddChange(insertRecords); } std::vector<DistributedKv::Entry> updateRecords = GetEntriesByKeys(keys[ChangeOp::OP_UPDATE]); if (!updateRecords.empty() && updateRecords.size() <= MAX_DB_RECORD_SIZE) { DHLOGI("MetaInfoManager Handle capability data update change"); HandleMetaCapabilityUpdateChange(updateRecords); } std::vector<std::string> delKeys = keys[ChangeOp::OP_DELETE]; if (!delKeys.empty() && delKeys.size() <= MAX_DB_RECORD_SIZE) { std::vector<DistributedKv::Entry> deleteRecords; for (const auto &key : delKeys) { DistributedKv::Entry entry; DistributedKv::Key kvKey(key); entry.key = kvKey; deleteRecords.emplace_back(entry); } DHLOGI("MetaInfoManager Handle capability data delete change"); HandleMetaCapabilityDeleteChange(deleteRecords); } } void MetaInfoManager::HandleMetaCapabilityAddChange(const std::vector<DistributedKv::Entry> &insertRecords) { std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); for (const auto &item : insertRecords) { const std::string value = item.value.ToString(); std::shared_ptr<MetaCapabilityInfo> capPtr; if (GetCapabilityByValue<MetaCapabilityInfo>(value, capPtr) != DH_FWK_SUCCESS) { DHLOGE("Get Meta capability by value failed"); continue; } std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(capPtr->GetDeviceId()); if (uuid.empty()) { DHLOGE("Find uuid failed and never enable, deviceId: %{public}s", GetAnonyString(capPtr->GetDeviceId()).c_str()); continue; } std::string networkId = DHContext::GetInstance().GetNetworkIdByUUID(uuid); if (networkId.empty()) { DHLOGE("Find network failed and never enable, uuid: %{public}s", GetAnonyString(uuid).c_str()); continue; } const auto keyString = capPtr->GetKey(); DHLOGI("Add MetaCapability key: %{public}s", capPtr->GetAnonymousKey().c_str()); globalMetaInfoMap_[keyString] = capPtr; TaskParam taskParam = { .networkId = networkId, .uuid = uuid, .dhId = capPtr->GetDHId(), .dhType = capPtr->GetDHType() }; auto task = TaskFactory::GetInstance().CreateTask(TaskType::ENABLE, taskParam, nullptr); TaskExecutor::GetInstance().PushTask(task); } } void MetaInfoManager::HandleMetaCapabilityUpdateChange(const std::vector<DistributedKv::Entry> &updateRecords) { std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); for (const auto &item : updateRecords) { const std::string value = item.value.ToString(); std::shared_ptr<MetaCapabilityInfo> capPtr; if (GetCapabilityByValue<MetaCapabilityInfo>(value, capPtr) != DH_FWK_SUCCESS) { DHLOGE("Get Meta capability by value failed"); continue; } std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(capPtr->GetDeviceId()); if (uuid.empty()) { DHLOGE("Find uuid failed and never enable, deviceId: %{public}s", GetAnonyString(capPtr->GetDeviceId()).c_str()); continue; } std::string networkId = DHContext::GetInstance().GetNetworkIdByUUID(uuid); if (networkId.empty()) { DHLOGE("Find network failed and never enable, uuid: %{public}s", GetAnonyString(uuid).c_str()); continue; } std::string enabledDeviceKey = GetCapabilityKey(capPtr->GetDeviceId(), capPtr->GetDHId()); if (TaskBoard::GetInstance().IsEnabledDevice(enabledDeviceKey)) { DHLOGI("The deviceKey: %{public}s is enabled.", GetAnonyString(enabledDeviceKey).c_str()); continue; } const auto keyString = capPtr->GetKey(); DHLOGI("Update MetaCapability key: %{public}s", capPtr->GetAnonymousKey().c_str()); globalMetaInfoMap_[keyString] = capPtr; TaskParam taskParam = { .networkId = networkId, .uuid = uuid, .dhId = capPtr->GetDHId(), .dhType = capPtr->GetDHType() }; auto task = TaskFactory::GetInstance().CreateTask(TaskType::ENABLE, taskParam, nullptr); TaskExecutor::GetInstance().PushTask(task); } } void MetaInfoManager::HandleMetaCapabilityDeleteChange(const std::vector<DistributedKv::Entry> &deleteRecords) { std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); for (const auto &item : deleteRecords) { const std::string value = item.value.ToString(); std::shared_ptr<MetaCapabilityInfo> capPtr; if (GetCapabilityByValue<MetaCapabilityInfo>(value, capPtr) != DH_FWK_SUCCESS) { DHLOGE("Get Meta capability by value failed"); continue; } const auto keyString = capPtr->GetKey(); DHLOGI("Delete MetaCapability key: %{public}s", capPtr->GetAnonymousKey().c_str()); globalMetaInfoMap_.erase(keyString); } } std::vector<DistributedKv::Entry> MetaInfoManager::GetEntriesByKeys(const std::vector<std::string> &keys) { if (!IsArrayLengthValid(keys)) { return {}; } DHLOGI("call"); if (keys.empty()) { DHLOGE("keys empty."); return {}; } std::lock_guard<std::mutex> lock(metaInfoMgrMutex_); if (dbAdapterPtr_ == nullptr) { DHLOGE("dbAdapterPtr_ is null"); return {}; } return dbAdapterPtr_->GetEntriesByKeys(keys); } } }