1 /*
2  * Copyright (c) 2022-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 "version_info_manager.h"
17 
18 #include "anonymous_string.h"
19 #include "constants.h"
20 #include "dh_context.h"
21 #include "dh_utils_tool.h"
22 #include "distributed_hardware_errno.h"
23 #include "distributed_hardware_log.h"
24 #include "task_executor.h"
25 #include "task_factory.h"
26 #include "version_manager.h"
27 
28 class DBAdapter;
29 namespace OHOS {
30 namespace DistributedHardware {
31 #undef DH_LOG_TAG
32 #define DH_LOG_TAG "VersionInfoManager"
33 
VersionInfoManager()34 VersionInfoManager::VersionInfoManager() : dbAdapterPtr_(nullptr)
35 {}
36 
~VersionInfoManager()37 VersionInfoManager::~VersionInfoManager()
38 {
39     DHLOGI("VersionInfoManager Destruction!");
40 }
41 
VersionInfoManagerEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,std::shared_ptr<VersionInfoManager> versionInfoMgrPtr)42 VersionInfoManager::VersionInfoManagerEventHandler::VersionInfoManagerEventHandler(
43     const std::shared_ptr<AppExecFwk::EventRunner> runner, std::shared_ptr<VersionInfoManager> versionInfoMgrPtr)
44     : AppExecFwk::EventHandler(runner)
45 {
46     DHLOGI("Ctor VersionInfoManagerEventHandler");
47     versionInfoMgrWPtr_ = versionInfoMgrPtr;
48 }
49 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)50 void VersionInfoManager::VersionInfoManagerEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
51 {
52     uint32_t eventId = event->GetInnerEventId();
53     auto selfPtr = versionInfoMgrWPtr_.lock();
54     if (!selfPtr) {
55         DHLOGE("Can not get strong self ptr");
56         return;
57     }
58     switch (eventId) {
59         case EVENT_VERSION_INFO_DB_RECOVER:
60             selfPtr->SyncRemoteVersionInfos();
61             break;
62         default:
63             DHLOGE("event is undefined, id is %{public}d", eventId);
64             break;
65     }
66 }
67 
GetEventHandler()68 std::shared_ptr<VersionInfoManager::VersionInfoManagerEventHandler> VersionInfoManager::GetEventHandler()
69 {
70     return this->eventHandler_;
71 }
72 
GetInstance()73 std::shared_ptr<VersionInfoManager> VersionInfoManager::GetInstance()
74 {
75     static std::shared_ptr<VersionInfoManager> instance = std::make_shared<VersionInfoManager>();
76     return instance;
77 }
78 
Init()79 int32_t VersionInfoManager::Init()
80 {
81     DHLOGI("VersionInfoManager instance init!");
82     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
83     dbAdapterPtr_ = std::make_shared<DBAdapter>(APP_ID, GLOBAL_VERSION_ID, shared_from_this());
84     if (dbAdapterPtr_->Init(false, DistributedKv::DataType::TYPE_DYNAMICAL) != DH_FWK_SUCCESS) {
85         DHLOGE("Init dbAdapterPtr_ failed");
86         return ERR_DH_FWK_RESOURCE_INIT_DB_FAILED;
87     }
88 
89     std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true);
90     eventHandler_ = std::make_shared<VersionInfoManager::VersionInfoManagerEventHandler>(
91         runner, shared_from_this());
92     DHLOGI("VersionInfoManager instance init success");
93     return DH_FWK_SUCCESS;
94 }
95 
UnInit()96 int32_t VersionInfoManager::UnInit()
97 {
98     DHLOGI("VersionInfoManager UnInit");
99     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
100     if (dbAdapterPtr_ == nullptr) {
101         DHLOGE("dbAdapterPtr_ is null");
102         return ERR_DH_FWK_RESOURCE_UNINIT_DB_FAILED;
103     }
104     dbAdapterPtr_->UnInit();
105     dbAdapterPtr_.reset();
106     return DH_FWK_SUCCESS;
107 }
108 
AddVersion(const VersionInfo & versionInfo)109 int32_t VersionInfoManager::AddVersion(const VersionInfo &versionInfo)
110 {
111     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
112     if (dbAdapterPtr_ == nullptr) {
113         DHLOGE("dbAdapterPtr_ is null");
114         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
115     }
116 
117     std::string data("");
118     dbAdapterPtr_->GetDataByKey(versionInfo.deviceId, data);
119     if (data.compare(versionInfo.ToJsonString()) == 0) {
120         DHLOGI("dhversion already stored, Key: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
121         return DH_FWK_SUCCESS;
122     }
123 
124     std::string key = versionInfo.deviceId;
125     std::string value = versionInfo.ToJsonString();
126     DHLOGI("AddVersion, Key: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
127     if (dbAdapterPtr_->PutData(key, value) != DH_FWK_SUCCESS) {
128         DHLOGE("Fail to storage to kv");
129         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
130     }
131     return DH_FWK_SUCCESS;
132 }
133 
GetVersionInfoByDeviceId(const std::string & deviceId,VersionInfo & versionInfo)134 int32_t VersionInfoManager::GetVersionInfoByDeviceId(const std::string &deviceId, VersionInfo &versionInfo)
135 {
136     if (!IsIdLengthValid(deviceId)) {
137         return ERR_DH_FWK_PARA_INVALID;
138     }
139     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
140     if (dbAdapterPtr_ == nullptr) {
141         DHLOGE("dbAdapterPtr_ is null");
142         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
143     }
144     std::string data("");
145     if (dbAdapterPtr_->GetDataByKey(deviceId, data) != DH_FWK_SUCCESS) {
146         DHLOGE("Query data from DB by deviceId failed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
147         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
148     }
149     return versionInfo.FromJsonString(data);
150 }
151 
UpdateVersionCache(const VersionInfo & versionInfo)152 void VersionInfoManager::UpdateVersionCache(const VersionInfo &versionInfo)
153 {
154     std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(versionInfo.deviceId);
155     if (uuid.empty()) {
156         DHLOGI("Find uuid failed, deviceId: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
157         return;
158     }
159     DHVersion dhVersion;
160     dhVersion.uuid = uuid;
161     dhVersion.dhVersion = versionInfo.dhVersion;
162     dhVersion.compVersions = versionInfo.compVersions;
163     VersionManager::GetInstance().AddDHVersion(uuid, dhVersion);
164 }
165 
RemoveVersionInfoByDeviceId(const std::string & deviceId)166 int32_t VersionInfoManager::RemoveVersionInfoByDeviceId(const std::string &deviceId)
167 {
168     if (!IsIdLengthValid(deviceId)) {
169         return ERR_DH_FWK_PARA_INVALID;
170     }
171     DHLOGI("Remove version device info, key: %{public}s", GetAnonyString(deviceId).c_str());
172     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
173     if (dbAdapterPtr_ == nullptr) {
174         DHLOGE("dbAdapterPtr_ is null");
175         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
176     }
177 
178     if (dbAdapterPtr_->RemoveDataByKey(deviceId) != DH_FWK_SUCCESS) {
179         DHLOGE("Remove version info failed, key: %{public}s", GetAnonyString(deviceId).c_str());
180         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
181     }
182 
183     std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(deviceId);
184     if (uuid.empty()) {
185         DHLOGI("Find uuid failed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
186         return ERR_DH_FWK_RESOURCE_UUID_NOT_FOUND;
187     }
188     DHLOGI("Delete version ,uuid: %{public}s", GetAnonyString(uuid).c_str());
189     VersionManager::GetInstance().RemoveDHVersion(uuid);
190 
191     return DH_FWK_SUCCESS;
192 }
193 
SyncVersionInfoFromDB(const std::string & deviceId)194 int32_t VersionInfoManager::SyncVersionInfoFromDB(const std::string &deviceId)
195 {
196     if (!IsIdLengthValid(deviceId)) {
197         return ERR_DH_FWK_PARA_INVALID;
198     }
199     DHLOGI("Sync versionInfo from DB, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
200     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
201     if (dbAdapterPtr_ == nullptr) {
202         DHLOGE("dbAdapterPtr_ is null");
203         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
204     }
205     std::string data("");
206     if (dbAdapterPtr_->GetDataByKey(deviceId, data) != DH_FWK_SUCCESS) {
207         DHLOGE("Query data from DB by deviceId failed, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
208         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_OPERATION_FAIL;
209     }
210 
211     DHLOGI("Query data from DB by deviceId success, deviceId: %{public}s", GetAnonyString(deviceId).c_str());
212     VersionInfo versionInfo;
213     int32_t ret = versionInfo.FromJsonString(data);
214     if (ret != DH_FWK_SUCCESS) {
215         return ret;
216     }
217     UpdateVersionCache(versionInfo);
218     return DH_FWK_SUCCESS;
219 }
220 
SyncRemoteVersionInfos()221 int32_t VersionInfoManager::SyncRemoteVersionInfos()
222 {
223     DHLOGI("Sync full remote version info from DB");
224     std::lock_guard<std::mutex> lock(verInfoMgrMutex_);
225     if (dbAdapterPtr_ == nullptr) {
226         DHLOGE("dbAdapterPtr_ is null");
227         return ERR_DH_FWK_RESOURCE_DB_ADAPTER_POINTER_NULL;
228     }
229     std::vector<std::string> deviceIdVec;
230     DHContext::GetInstance().GetOnlineDeviceDeviceId(deviceIdVec);
231     for (const auto &deviceId : deviceIdVec) {
232         std::vector<std::string> dataVector;
233         if (dbAdapterPtr_->GetDataByKeyPrefix(deviceId, dataVector) != DH_FWK_SUCCESS) {
234             DHLOGE("Query the deviceId: %{public}s data from DB failed", GetAnonyString(deviceId).c_str());
235             continue;
236         }
237         if (dataVector.empty() || dataVector.size() > MAX_DB_RECORD_SIZE) {
238             DHLOGE("dataVector size: %{public}zu is invalid, maybe empty or too large.", dataVector.size());
239             continue;
240         }
241         for (const auto &data : dataVector) {
242             VersionInfo versionInfo;
243             if (versionInfo.FromJsonString(data) != DH_FWK_SUCCESS) {
244                 continue;
245             }
246             const std::string &deviceId = versionInfo.deviceId;
247             const std::string &localDeviceId = DHContext::GetInstance().GetDeviceInfo().deviceId;
248             if (deviceId.compare(localDeviceId) == 0) {
249                 DHLOGE("Local device info not need sync from db");
250                 continue;
251             }
252             UpdateVersionCache(versionInfo);
253         }
254     }
255     return DH_FWK_SUCCESS;
256 }
257 
OnChange(const DistributedKv::ChangeNotification & changeNotification)258 void VersionInfoManager::OnChange(const DistributedKv::ChangeNotification &changeNotification)
259 {
260     DHLOGI("DB data OnChange");
261     if (!changeNotification.GetInsertEntries().empty() &&
262         changeNotification.GetInsertEntries().size() <= MAX_DB_RECORD_SIZE) {
263         DHLOGI("Handle version data add change");
264         HandleVersionAddChange(changeNotification.GetInsertEntries());
265     }
266     if (!changeNotification.GetUpdateEntries().empty() &&
267         changeNotification.GetUpdateEntries().size() <= MAX_DB_RECORD_SIZE) {
268         DHLOGI("Handle version data update change");
269         HandleVersionUpdateChange(changeNotification.GetUpdateEntries());
270     }
271     if (!changeNotification.GetDeleteEntries().empty() &&
272         changeNotification.GetDeleteEntries().size() <= MAX_DB_RECORD_SIZE) {
273         DHLOGI("Handle version data delete change");
274         HandleVersionDeleteChange(changeNotification.GetDeleteEntries());
275     }
276 }
277 
HandleVersionAddChange(const std::vector<DistributedKv::Entry> & insertRecords)278 void VersionInfoManager::HandleVersionAddChange(const std::vector<DistributedKv::Entry> &insertRecords)
279 {
280     DHLOGI("Version add change");
281     for (const auto &item : insertRecords) {
282         const std::string value = item.value.ToString();
283         VersionInfo versionInfo;
284         if (versionInfo.FromJsonString(value) != DH_FWK_SUCCESS) {
285             continue;
286         }
287         UpdateVersionCache(versionInfo);
288     }
289 }
290 
HandleVersionUpdateChange(const std::vector<DistributedKv::Entry> & updateRecords)291 void VersionInfoManager::HandleVersionUpdateChange(const std::vector<DistributedKv::Entry> &updateRecords)
292 {
293     DHLOGI("Version update change");
294     for (const auto &item : updateRecords) {
295         const std::string value = item.value.ToString();
296         VersionInfo versionInfo;
297         if (versionInfo.FromJsonString(value) != DH_FWK_SUCCESS) {
298             continue;
299         }
300         UpdateVersionCache(versionInfo);
301     }
302 }
303 
HandleVersionDeleteChange(const std::vector<DistributedKv::Entry> & deleteRecords)304 void VersionInfoManager::HandleVersionDeleteChange(const std::vector<DistributedKv::Entry> &deleteRecords)
305 {
306     DHLOGI("Version delete change");
307     for (const auto &item : deleteRecords) {
308         const std::string value = item.value.ToString();
309         VersionInfo versionInfo;
310         if (versionInfo.FromJsonString(value) != DH_FWK_SUCCESS) {
311             continue;
312         }
313         std::string uuid = DHContext::GetInstance().GetUUIDByDeviceId(versionInfo.deviceId);
314         if (uuid.empty()) {
315             DHLOGI("Find uuid failed, deviceId: %{public}s", GetAnonyString(versionInfo.deviceId).c_str());
316             continue;
317         }
318         DHLOGI("Delete version ,uuid: %{public}s", GetAnonyString(uuid).c_str());
319         VersionManager::GetInstance().RemoveDHVersion(uuid);
320     }
321 }
322 } // namespace DistributedHardware
323 } // namespace OHOS
324