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