1 /*
2 * Copyright (c) 2022-2023 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 "dm_device_state_manager.h"
17
18 #include "dm_adapter_manager.h"
19 #include "dm_anonymous.h"
20 #include "dm_constants.h"
21 #include "dm_distributed_hardware_load.h"
22 #include "dm_log.h"
23
24 namespace OHOS {
25 namespace DistributedHardware {
26 const uint32_t DM_EVENT_QUEUE_CAPACITY = 20;
27 const uint32_t DM_EVENT_WAIT_TIMEOUT = 2;
DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,std::shared_ptr<IDeviceManagerServiceListener> listener,std::shared_ptr<HiChainConnector> hiChainConnector)28 DmDeviceStateManager::DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,
29 std::shared_ptr<IDeviceManagerServiceListener> listener, std::shared_ptr<HiChainConnector> hiChainConnector)
30 : softbusConnector_(softbusConnector), listener_(listener), hiChainConnector_(hiChainConnector)
31 {
32 decisionSoName_ = "libdevicemanagerext_decision.z.so";
33 StartEventThread();
34 LOGI("DmDeviceStateManager constructor");
35 }
36
~DmDeviceStateManager()37 DmDeviceStateManager::~DmDeviceStateManager()
38 {
39 LOGI("DmDeviceStateManager destructor");
40 if (softbusConnector_ != nullptr) {
41 softbusConnector_->UnRegisterSoftbusStateCallback("DM_PKG_NAME");
42 }
43 StopEventThread();
44 }
45
SaveOnlineDeviceInfo(const std::string & pkgName,const DmDeviceInfo & info)46 void DmDeviceStateManager::SaveOnlineDeviceInfo(const std::string &pkgName, const DmDeviceInfo &info)
47 {
48 LOGI("SaveOnlineDeviceInfo begin, deviceId = %s", GetAnonyString(std::string(info.deviceId)).c_str());
49 std::string udid;
50 if (SoftbusConnector::GetUdidByNetworkId(info.networkId, udid) == DM_OK) {
51 std::string uuid;
52 DmDeviceInfo saveInfo = info;
53 SoftbusConnector::GetUuidByNetworkId(info.networkId, uuid);
54 {
55 #if defined(__LITEOS_M__)
56 DmMutex mutexLock;
57 #else
58 std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
59 #endif
60 remoteDeviceInfos_[uuid] = saveInfo;
61 }
62 LOGI("SaveOnlineDeviceInfo complete, networkId = %s, udid = %s, uuid = %s", GetAnonyString(
63 std::string(info.networkId)).c_str(), GetAnonyString(udid).c_str(), GetAnonyString(uuid).c_str());
64 }
65 }
66
DeleteOfflineDeviceInfo(const std::string & pkgName,const DmDeviceInfo & info)67 void DmDeviceStateManager::DeleteOfflineDeviceInfo(const std::string &pkgName, const DmDeviceInfo &info)
68 {
69 LOGI("DeleteOfflineDeviceInfo begin, deviceId = %s", GetAnonyString(std::string(info.deviceId)).c_str());
70 #if defined(__LITEOS_M__)
71 DmMutex mutexLock;
72 #else
73 std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
74 #endif
75 for (auto iter: remoteDeviceInfos_) {
76 if (iter.second.deviceId == info.deviceId) {
77 remoteDeviceInfos_.erase(iter.first);
78 LOGI("DeleteOfflineDeviceInfo complete");
79 break;
80 }
81 }
82 }
83
PostDeviceOnline(const std::string & pkgName,const DmDeviceInfo & info)84 void DmDeviceStateManager::PostDeviceOnline(const std::string &pkgName, const DmDeviceInfo &info)
85 {
86 LOGI("DmDeviceStateManager::PostDeviceOnline in");
87 if (listener_ != nullptr) {
88 DmDeviceState state = DEVICE_STATE_ONLINE;
89 listener_->OnDeviceStateChange(pkgName, state, info);
90 }
91 LOGI("DmDeviceStateManager::PostDeviceOnline out");
92 }
93
PostDeviceOffline(const std::string & pkgName,const DmDeviceInfo & info)94 void DmDeviceStateManager::PostDeviceOffline(const std::string &pkgName, const DmDeviceInfo &info)
95 {
96 LOGI("DmDeviceStateManager::PostDeviceOffline in");
97 if (listener_ != nullptr) {
98 DmDeviceState state = DEVICE_STATE_OFFLINE;
99 listener_->OnDeviceStateChange(pkgName, state, info);
100 }
101 LOGI("DmDeviceStateManager::PostDeviceOffline out");
102 }
103
OnDeviceOnline(const std::string & pkgName,const DmDeviceInfo & info)104 void DmDeviceStateManager::OnDeviceOnline(const std::string &pkgName, const DmDeviceInfo &info)
105 {
106 LOGI("OnDeviceOnline function is called with pkgName: %s", pkgName.c_str());
107 RegisterOffLineTimer(info);
108 SaveOnlineDeviceInfo(pkgName, info);
109
110 DmAdapterManager &adapterMgrPtr = DmAdapterManager::GetInstance();
111 std::shared_ptr<IDecisionAdapter> decisionAdapter = adapterMgrPtr.GetDecisionAdapter(decisionSoName_);
112 if (decisionAdapter == nullptr) {
113 LOGE("OnDeviceOnline decision adapter is null");
114 PostDeviceOnline(pkgName, info);
115 } else if (decisionInfos_.size() == 0) {
116 PostDeviceOnline(pkgName, info);
117 } else {
118 std::vector<DmDeviceInfo> infoList;
119 LOGI("OnDeviceOnline decision decisionInfos_ size: %d", decisionInfos_.size());
120 for (auto iter : decisionInfos_) {
121 std::string listenerPkgName = iter.first;
122 std::string extra = iter.second;
123 infoList.clear();
124 infoList.push_back(info);
125 decisionAdapter->FilterDeviceList(infoList, extra);
126 if (infoList.size() == 1) {
127 PostDeviceOnline(listenerPkgName, info);
128 }
129 }
130 }
131 LOGI("DmDeviceStateManager::OnDeviceOnline out");
132 }
133
OnDeviceOffline(const std::string & pkgName,const DmDeviceInfo & info)134 void DmDeviceStateManager::OnDeviceOffline(const std::string &pkgName, const DmDeviceInfo &info)
135 {
136 LOGI("OnDeviceOffline function is called with pkgName: %s", pkgName.c_str());
137 StartOffLineTimer(info);
138 DeleteOfflineDeviceInfo(pkgName, info);
139
140 DmAdapterManager &adapterMgrPtr = DmAdapterManager::GetInstance();
141 std::shared_ptr<IDecisionAdapter> decisionAdapter = adapterMgrPtr.GetDecisionAdapter(decisionSoName_);
142 if (decisionAdapter == nullptr) {
143 LOGE("OnDeviceOffline decision adapter is null");
144 PostDeviceOffline(pkgName, info);
145 } else if (decisionInfos_.size() == 0) {
146 PostDeviceOffline(pkgName, info);
147 } else {
148 std::vector<DmDeviceInfo> infoList;
149 LOGI("OnDeviceOffline decision decisionInfos_ size: %d", decisionInfos_.size());
150 for (auto iter : decisionInfos_) {
151 std::string listenerPkgName = iter.first;
152 std::string extra = iter.second;
153 infoList.clear();
154 infoList.push_back(info);
155 decisionAdapter->FilterDeviceList(infoList, extra);
156 if (infoList.size() == 1) {
157 PostDeviceOffline(listenerPkgName, info);
158 }
159 }
160 }
161 LOGI("DmDeviceStateManager::OnDeviceOffline out");
162 }
163
OnDeviceChanged(const std::string & pkgName,const DmDeviceInfo & info)164 void DmDeviceStateManager::OnDeviceChanged(const std::string &pkgName, const DmDeviceInfo &info)
165 {
166 LOGI("OnDeviceChanged function is called back with pkgName: %s", pkgName.c_str());
167 }
168
OnDeviceReady(const std::string & pkgName,const DmDeviceInfo & info)169 void DmDeviceStateManager::OnDeviceReady(const std::string &pkgName, const DmDeviceInfo &info)
170 {
171 LOGI("OnDeviceReady function is called back with pkgName: %s", pkgName.c_str());
172 }
173
OnDbReady(const std::string & pkgName,const std::string & deviceId)174 void DmDeviceStateManager::OnDbReady(const std::string &pkgName, const std::string &deviceId)
175 {
176 LOGI("OnDbReady function is called with pkgName: %s", pkgName.c_str());
177 if (pkgName.empty() || deviceId.empty()) {
178 LOGE("On db ready pkgName is empty or deviceId is deviceId");
179 return;
180 }
181 DmDeviceInfo saveInfo;
182 {
183 #if defined(__LITEOS_M__)
184 DmMutex mutexLock;
185 #else
186 std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
187 #endif
188 auto iter = remoteDeviceInfos_.find(deviceId);
189 if (iter == remoteDeviceInfos_.end()) {
190 LOGE("OnDbReady complete not find deviceId: %s", GetAnonyString(deviceId).c_str());
191 return;
192 }
193 saveInfo = iter->second;
194 }
195 DmDistributedHardwareLoad::GetInstance().LoadDistributedHardwareFwk();
196 if (listener_ != nullptr) {
197 DmDeviceState state = DEVICE_INFO_READY;
198 listener_->OnDeviceStateChange(pkgName, state, saveInfo);
199 }
200 }
201
RegisterSoftbusStateCallback()202 int32_t DmDeviceStateManager::RegisterSoftbusStateCallback()
203 {
204 if (softbusConnector_ != nullptr) {
205 return softbusConnector_->RegisterSoftbusStateCallback(std::string(DM_PKG_NAME), shared_from_this());
206 }
207 return DM_OK;
208 }
209
RegisterDevStateCallback(const std::string & pkgName,const std::string & extra)210 void DmDeviceStateManager::RegisterDevStateCallback(const std::string &pkgName, const std::string &extra)
211 {
212 if (pkgName.empty()) {
213 LOGE("DmDeviceStateManager::RegisterDevStateCallback input param is empty");
214 return;
215 }
216 LOGI("DmDeviceStateManager::RegisterDevStateCallback pkgName = %s, extra = %s",
217 GetAnonyString(pkgName).c_str(), GetAnonyString(extra).c_str());
218 if (decisionInfos_.count(pkgName) == 0) {
219 decisionInfos_.insert(std::map<std::string, std::string>::value_type (pkgName, extra));
220 }
221 }
222
UnRegisterDevStateCallback(const std::string & pkgName,const std::string & extra)223 void DmDeviceStateManager::UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra)
224 {
225 if (pkgName.empty()) {
226 LOGE("DmDeviceStateManager::UnRegisterDevStateCallback input param is empty");
227 return;
228 }
229 LOGI("DmDeviceStateManager::UnRegisterDevStateCallback pkgName = %s, extra = %s",
230 GetAnonyString(pkgName).c_str(), GetAnonyString(extra).c_str());
231 if (decisionInfos_.count(pkgName) > 0) {
232 auto iter = decisionInfos_.find(pkgName);
233 if (iter != decisionInfos_.end()) {
234 decisionInfos_.erase(pkgName);
235 }
236 }
237 }
238
RegisterOffLineTimer(const DmDeviceInfo & deviceInfo)239 void DmDeviceStateManager::RegisterOffLineTimer(const DmDeviceInfo &deviceInfo)
240 {
241 std::string deviceId;
242 int32_t ret = softbusConnector_->GetUdidByNetworkId(deviceInfo.deviceId, deviceId);
243 if (ret != DM_OK) {
244 LOGE("fail to get udid by networkId");
245 return;
246 }
247 LOGI("Register offline timer for deviceId: %s", GetAnonyString(deviceId).c_str());
248 #if defined(__LITEOS_M__)
249 DmMutex mutexLock;
250 #else
251 std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
252 #endif
253 for (auto &iter : stateTimerInfoMap_) {
254 if ((iter.first == deviceId) && (timer_ != nullptr)) {
255 timer_->DeleteTimer(iter.second.timerName);
256 stateTimerInfoMap_.erase(iter.first);
257 break;
258 }
259 }
260 if (stateTimerInfoMap_.find(deviceId) == stateTimerInfoMap_.end()) {
261 std::string timerName = std::string(STATE_TIMER_PREFIX) + GetAnonyString(deviceId);
262 StateTimerInfo stateTimer = {
263 .timerName = timerName,
264 .networkId = deviceInfo.deviceId,
265 .isStart = false,
266 };
267 stateTimerInfoMap_[deviceId] = stateTimer;
268 }
269 }
270
StartOffLineTimer(const DmDeviceInfo & deviceInfo)271 void DmDeviceStateManager::StartOffLineTimer(const DmDeviceInfo &deviceInfo)
272 {
273 #if defined(__LITEOS_M__)
274 DmMutex mutexLock;
275 #else
276 std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
277 #endif
278 std::string networkId = deviceInfo.deviceId;
279 LOGI("Start offline timer for networkId: %s", GetAnonyString(networkId).c_str());
280 if (timer_ == nullptr) {
281 timer_ = std::make_shared<DmTimer>();
282 }
283 for (auto &iter : stateTimerInfoMap_) {
284 if ((iter.second.networkId == networkId) && !iter.second.isStart) {
285 timer_->StartTimer(iter.second.timerName, OFFLINE_TIMEOUT,
286 [this] (std::string name) {
287 DmDeviceStateManager::DeleteTimeOutGroup(name);
288 });
289 iter.second.isStart = true;
290 }
291 }
292 }
293
DeleteTimeOutGroup(std::string name)294 void DmDeviceStateManager::DeleteTimeOutGroup(std::string name)
295 {
296 #if defined(__LITEOS_M__)
297 DmMutex mutexLock;
298 #else
299 std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
300 #endif
301 for (auto iter = stateTimerInfoMap_.begin(); iter != stateTimerInfoMap_.end(); iter++) {
302 if (((iter->second).timerName == name) && (hiChainConnector_ != nullptr)) {
303 LOGI("remove hichain group with deviceId: %s", GetAnonyString(iter->first).c_str());
304 hiChainConnector_->DeleteTimeOutGroup((iter->first).c_str());
305 stateTimerInfoMap_.erase(iter);
306 break;
307 }
308 }
309 }
310
StartEventThread()311 void DmDeviceStateManager::StartEventThread()
312 {
313 LOGI("StartEventThread begin");
314 eventTask_.threadRunning_ = true;
315 eventTask_.queueThread_ = std::thread(&DmDeviceStateManager::ThreadLoop, this);
316 LOGI("StartEventThread complete");
317 }
318
StopEventThread()319 void DmDeviceStateManager::StopEventThread()
320 {
321 LOGI("StopEventThread begin");
322 eventTask_.threadRunning_ = false;
323 eventTask_.queueCond_.notify_all();
324 eventTask_.queueFullCond_.notify_all();
325 if (eventTask_.queueThread_.joinable()) {
326 eventTask_.queueThread_.join();
327 }
328 LOGI("StopEventThread complete");
329 }
330
AddTask(const std::shared_ptr<NotifyEvent> & task)331 int32_t DmDeviceStateManager::AddTask(const std::shared_ptr<NotifyEvent> &task)
332 {
333 LOGI("AddTask begin, eventId: %d", task->GetEventId());
334 {
335 std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
336 while (eventTask_.queue_.size() >= DM_EVENT_QUEUE_CAPACITY) {
337 eventTask_.queueFullCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
338 }
339 eventTask_.queue_.push(task);
340 }
341 eventTask_.queueCond_.notify_one();
342 LOGI("AddTask complete");
343 return DM_OK;
344 }
345
ThreadLoop()346 void DmDeviceStateManager::ThreadLoop()
347 {
348 LOGI("ThreadLoop begin");
349 while (eventTask_.threadRunning_) {
350 std::shared_ptr<NotifyEvent> task = nullptr;
351 {
352 std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
353 while (eventTask_.queue_.empty() && eventTask_.threadRunning_) {
354 eventTask_.queueCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
355 }
356 if (!eventTask_.queue_.empty()) {
357 task = eventTask_.queue_.front();
358 eventTask_.queue_.pop();
359 eventTask_.queueFullCond_.notify_one();
360 }
361 }
362 if (task != nullptr) {
363 RunTask(task);
364 }
365 }
366 LOGI("ThreadLoop end");
367 }
368
RunTask(const std::shared_ptr<NotifyEvent> & task)369 void DmDeviceStateManager::RunTask(const std::shared_ptr<NotifyEvent> &task)
370 {
371 LOGI("RunTask begin, eventId: %d", task->GetEventId());
372 if (task->GetEventId() == DM_NOTIFY_EVENT_ONDEVICEREADY) {
373 OnDbReady(std::string(DM_PKG_NAME), task->GetDeviceId());
374 }
375 LOGI("RunTask complete");
376 }
377
ProcNotifyEvent(const std::string & pkgName,const int32_t eventId,const std::string & deviceId)378 int32_t DmDeviceStateManager::ProcNotifyEvent(const std::string &pkgName, const int32_t eventId,
379 const std::string &deviceId)
380 {
381 LOGI("ProcNotifyEvent in, eventId: %d", eventId);
382 return AddTask(std::make_shared<NotifyEvent>(eventId, deviceId));
383 }
384 } // namespace DistributedHardware
385 } // namespace OHOS