1 /*
2  * Copyright (c) 2024 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 
16 #include "local_capability_info_manager.h"
17 
18 #include "anonymous_string.h"
19 #include "capability_utils.h"
20 #include "constants.h"
21 #include "dh_context.h"
22 #include "dh_utils_tool.h"
23 #include "distributed_hardware_errno.h"
24 #include "distributed_hardware_log.h"
25 #include "distributed_hardware_manager.h"
26 #include "task_executor.h"
27 #include "task_factory.h"
28 
29 namespace OHOS {
30 namespace DistributedHardware {
31 #undef DH_LOG_TAG
32 #define DH_LOG_TAG "LocalCapabilityInfoManager"
33 
LocalCapabilityInfoManager()34 LocalCapabilityInfoManager::LocalCapabilityInfoManager() : dbAdapterPtr_(nullptr)
35 {
36     DHLOGI("LocalCapabilityInfoManager construction!");
37 }
38 
~LocalCapabilityInfoManager()39 LocalCapabilityInfoManager::~LocalCapabilityInfoManager()
40 {
41     DHLOGI("LocalCapabilityInfoManager destruction!");
42 }
43 
GetInstance()44 std::shared_ptr<LocalCapabilityInfoManager> LocalCapabilityInfoManager::GetInstance()
45 {
46     static std::shared_ptr<LocalCapabilityInfoManager> instance = std::make_shared<LocalCapabilityInfoManager>();
47     return instance;
48 }
49 
Init()50 int32_t LocalCapabilityInfoManager::Init()
51 {
52     DHLOGI("LocalCapabilityInfoManager instance init!");
53     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
54     dbAdapterPtr_ = std::make_shared<DBAdapter>(APP_ID, LOCAL_CAPABILITY_ID, shared_from_this());
55     if (dbAdapterPtr_ == nullptr) {
56         DHLOGE("dbAdapterPtr_ is null");
57         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
58     }
59     if (dbAdapterPtr_->InitLocal() != DH_FWK_SUCCESS) {
60         DHLOGE("Init dbAdapterPtr_ failed");
61         return ERR_DH_FWK_RESOURCE_INIT_DB_FAILED;
62     }
63     DHLOGI("LocalCapabilityInfoManager instance init success");
64     return DH_FWK_SUCCESS;
65 }
66 
UnInit()67 int32_t LocalCapabilityInfoManager::UnInit()
68 {
69     DHLOGI("LocalCapabilityInfoManager UnInit");
70     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
71     if (dbAdapterPtr_ == nullptr) {
72         DHLOGE("dbAdapterPtr_ is null");
73         return ERR_DH_FWK_RESOURCE_UNINIT_DB_FAILED;
74     }
75     dbAdapterPtr_->UnInit();
76     dbAdapterPtr_.reset();
77     return DH_FWK_SUCCESS;
78 }
79 
SyncDeviceInfoFromDB(const std::string & deviceId)80 int32_t LocalCapabilityInfoManager::SyncDeviceInfoFromDB(const std::string &deviceId)
81 {
82     if (!IsIdLengthValid(deviceId)) {
83         return ERR_DH_FWK_PARA_INVALID;
84     }
85     DHLOGI("Sync DeviceInfo from DB, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
86     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
87     if (dbAdapterPtr_ == nullptr) {
88         DHLOGE("dbAdapterPtr_ is null");
89         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
90     }
91     std::vector<std::string> dataVector;
92     if (dbAdapterPtr_->GetDataByKeyPrefix(deviceId, dataVector) != DH_FWK_SUCCESS) {
93         DHLOGE("Query data from DB by deviceId failed, id: %{public}s", GetAnonyString(deviceId).c_str());
94         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
95     }
96     if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) {
97         DHLOGE("On dataVector error, maybe empty or too large.");
98         return ERR_DH_FWK_RESOURCE_RES_DB_DATA_INVALID;
99     }
100     for (const auto &data : dataVector) {
101         std::shared_ptr<CapabilityInfo> capabilityInfo;
102         if (GetCapabilityByValue<CapabilityInfo>(data, capabilityInfo) != DH_FWK_SUCCESS) {
103             DHLOGE("Get capability ptr by value failed");
104             continue;
105         }
106         globalCapInfoMap_[capabilityInfo->GetKey()] = capabilityInfo;
107     }
108     return DH_FWK_SUCCESS;
109 }
110 
AddCapability(const std::vector<std::shared_ptr<CapabilityInfo>> & resInfos)111 int32_t LocalCapabilityInfoManager::AddCapability(const std::vector<std::shared_ptr<CapabilityInfo>> &resInfos)
112 {
113     if (resInfos.empty() || resInfos.size() > MAX_DB_RECORD_SIZE) {
114         DHLOGE("resInfo is empty or too large!");
115         return ERR_DH_FWK_RESOURCE_RES_DB_DATA_INVALID;
116     }
117     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
118     if (dbAdapterPtr_ == nullptr) {
119         DHLOGE("dbAdapterPtr_ is null");
120         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
121     }
122     std::vector<std::string> keys;
123     std::vector<std::string> values;
124     std::string key;
125     for (auto &resInfo : resInfos) {
126         if (resInfo == nullptr) {
127             continue;
128         }
129         key = resInfo->GetKey();
130         globalCapInfoMap_[key] = resInfo;
131         DHLOGI("AddCapability, Key: %{public}s", resInfo->GetAnonymousKey().c_str());
132         keys.push_back(key);
133         values.push_back(resInfo->ToJsonString());
134     }
135     if (keys.empty() || values.empty()) {
136         DHLOGD("Records are empty, No need add data to db!");
137         return DH_FWK_SUCCESS;
138     }
139     if (dbAdapterPtr_->PutDataBatch(keys, values) != DH_FWK_SUCCESS) {
140         DHLOGE("Fail to storage batch to kv");
141         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
142     }
143     return DH_FWK_SUCCESS;
144 }
145 
RemoveCapabilityInfoByKey(const std::string & key)146 int32_t LocalCapabilityInfoManager::RemoveCapabilityInfoByKey(const std::string &key)
147 {
148     if (!IsKeySizeValid(key)) {
149         return ERR_DH_FWK_PARA_INVALID;
150     }
151     DHLOGI("Remove capability device info, key: %{public}s", GetAnonyString(key).c_str());
152     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
153     if (dbAdapterPtr_ == nullptr) {
154         DHLOGE("dbAdapterPtr_ is null");
155         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
156     }
157     // 1. Clear the cache in the memory.
158     globalCapInfoMap_.erase(key);
159 
160     // 2. Delete the corresponding record from the database.(use key)
161     if (dbAdapterPtr_->RemoveDataByKey(key) != DH_FWK_SUCCESS) {
162         DHLOGE("Remove capability Device Data failed, key: %{public}s", GetAnonyString(key).c_str());
163         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
164     }
165     return DH_FWK_SUCCESS;
166 }
167 
GetCapabilitiesByDeviceId(const std::string & deviceId,std::vector<std::shared_ptr<CapabilityInfo>> & resInfos)168 void LocalCapabilityInfoManager::GetCapabilitiesByDeviceId(const std::string &deviceId,
169     std::vector<std::shared_ptr<CapabilityInfo>> &resInfos)
170 {
171     if (!IsIdLengthValid(deviceId) || resInfos.empty() || resInfos.size() > MAX_DB_RECORD_SIZE) {
172         DHLOGE("On parameter error, maybe empty or too large!");
173         return;
174     }
175     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
176     for (auto &capabilityInfo : globalCapInfoMap_) {
177         if (IsCapKeyMatchDeviceId(capabilityInfo.first, deviceId)) {
178             resInfos.emplace_back(capabilityInfo.second);
179         }
180     }
181 }
182 
GetCapability(const std::string & deviceId,const std::string & dhId,std::shared_ptr<CapabilityInfo> & capPtr)183 int32_t LocalCapabilityInfoManager::GetCapability(const std::string &deviceId, const std::string &dhId,
184     std::shared_ptr<CapabilityInfo> &capPtr)
185 {
186     if (!IsIdLengthValid(deviceId) || !IsIdLengthValid(dhId)) {
187         return ERR_DH_FWK_PARA_INVALID;
188     }
189     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
190     std::string key = GetCapabilityKey(deviceId, dhId);
191     if (globalCapInfoMap_.find(key) == globalCapInfoMap_.end()) {
192         DHLOGE("Can not find capability In globalCapInfoMap_: %{public}s", GetAnonyString(deviceId).c_str());
193         return ERR_DH_FWK_RESOURCE_CAPABILITY_MAP_NOT_FOUND;
194     }
195     capPtr = globalCapInfoMap_[key];
196     return DH_FWK_SUCCESS;
197 }
198 
GetDataByKey(const std::string & key,std::shared_ptr<CapabilityInfo> & capInfoPtr)199 int32_t LocalCapabilityInfoManager::GetDataByKey(const std::string &key, std::shared_ptr<CapabilityInfo> &capInfoPtr)
200 {
201     if (!IsIdLengthValid(key)) {
202         return ERR_DH_FWK_PARA_INVALID;
203     }
204     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
205     if (dbAdapterPtr_ == nullptr) {
206         DHLOGI("dbAdapterPtr_ is null");
207         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
208     }
209     std::string data;
210     if (dbAdapterPtr_->GetDataByKey(key, data) != DH_FWK_SUCCESS) {
211         DHLOGE("Query capability info from db failed, key: %{public}s", GetAnonyString(key).c_str());
212         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
213     }
214     return GetCapabilityByValue<CapabilityInfo>(data, capInfoPtr);
215 }
216 
GetDataByDHType(const DHType dhType,CapabilityInfoMap & capabilityMap)217 int32_t LocalCapabilityInfoManager::GetDataByDHType(const DHType dhType, CapabilityInfoMap &capabilityMap)
218 {
219     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
220     for (const auto &capInfo : globalCapInfoMap_) {
221         if (capInfo.second->GetDHType() != dhType) {
222             continue;
223         }
224         capabilityMap[capInfo.first] = capInfo.second;
225     }
226     return DH_FWK_SUCCESS;
227 }
228 
GetDataByKeyPrefix(const std::string & keyPrefix,CapabilityInfoMap & capabilityMap)229 int32_t LocalCapabilityInfoManager::GetDataByKeyPrefix(const std::string &keyPrefix, CapabilityInfoMap &capabilityMap)
230 {
231     if (!IsKeySizeValid(keyPrefix)) {
232         return ERR_DH_FWK_PARA_INVALID;
233     }
234     std::lock_guard<std::mutex> lock(capInfoMgrMutex_);
235     if (dbAdapterPtr_ == nullptr) {
236         DHLOGE("dbAdapterPtr is null");
237         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
238     }
239     std::vector<std::string> dataVector;
240     if (dbAdapterPtr_->GetDataByKeyPrefix(keyPrefix, dataVector) != DH_FWK_SUCCESS) {
241         DHLOGE("Query capability info from db failed, key: %{public}s", GetAnonyString(keyPrefix).c_str());
242         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
243     }
244     if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) {
245         DHLOGE("On dataVector error, maybe empty or too large!");
246         return ERR_DH_FWK_RESOURCE_RES_DB_DATA_INVALID;
247     }
248     for (const auto &data : dataVector) {
249         std::shared_ptr<CapabilityInfo> capabilityInfo;
250         if (GetCapabilityByValue<CapabilityInfo>(data, capabilityInfo) != DH_FWK_SUCCESS) {
251             DHLOGE("Get capability ptr by value failed");
252             continue;
253         }
254         if (capabilityInfo->FromJsonString(data) != DH_FWK_SUCCESS) {
255             DHLOGE("Wrong data: %{public}s", GetAnonyString(data).c_str());
256             continue;
257         }
258         capabilityMap[capabilityInfo->GetKey()] = capabilityInfo;
259     }
260     return DH_FWK_SUCCESS;
261 }
262 } // namespace DistributedHardware
263 } // namespace OHOS
264