• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dm_device_state_manager.h"
17 
18 #include <pthread.h>
19 
20 #include "dm_adapter_manager.h"
21 #include "dm_anonymous.h"
22 #include "dm_constants.h"
23 #include "dm_distributed_hardware_load.h"
24 #include "dm_log.h"
25 
26 namespace OHOS {
27 namespace DistributedHardware {
28 const uint32_t DM_EVENT_QUEUE_CAPACITY = 20;
29 const uint32_t DM_EVENT_WAIT_TIMEOUT = 2;
30 constexpr const char* THREAD_LOOP = "ThreadLoop";
DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,std::shared_ptr<IDeviceManagerServiceListener> listener,std::shared_ptr<HiChainConnector> hiChainConnector)31 DmDeviceStateManager::DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,
32     std::shared_ptr<IDeviceManagerServiceListener> listener, std::shared_ptr<HiChainConnector> hiChainConnector)
33     : softbusConnector_(softbusConnector), listener_(listener), hiChainConnector_(hiChainConnector)
34 {
35     decisionSoName_ = "libdevicemanagerext_decision.z.so";
36     StartEventThread();
37     LOGI("DmDeviceStateManager constructor");
38 }
39 
~DmDeviceStateManager()40 DmDeviceStateManager::~DmDeviceStateManager()
41 {
42     LOGI("DmDeviceStateManager destructor");
43     if (softbusConnector_ != nullptr) {
44         softbusConnector_->UnRegisterSoftbusStateCallback("DM_PKG_NAME");
45     }
46     StopEventThread();
47 }
48 
SaveOnlineDeviceInfo(const std::string & pkgName,const DmDeviceInfo & info)49 void DmDeviceStateManager::SaveOnlineDeviceInfo(const std::string &pkgName, const DmDeviceInfo &info)
50 {
51     (void)pkgName;
52     LOGI("SaveOnlineDeviceInfo begin, deviceId = %s", GetAnonyString(std::string(info.deviceId)).c_str());
53     std::string udid;
54     if (SoftbusConnector::GetUdidByNetworkId(info.networkId, udid) == DM_OK) {
55         std::string uuid;
56         DmDeviceInfo saveInfo = info;
57         SoftbusConnector::GetUuidByNetworkId(info.networkId, uuid);
58         {
59 #if defined(__LITEOS_M__)
60             DmMutex mutexLock;
61 #else
62             std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
63 #endif
64             remoteDeviceInfos_[uuid] = saveInfo;
65         }
66         LOGI("SaveOnlineDeviceInfo complete, networkId = %s, udid = %s, uuid = %s",
67             GetAnonyString(std::string(info.networkId)).c_str(), GetAnonyString(udid).c_str(),
68             GetAnonyString(uuid).c_str());
69     }
70 }
71 
DeleteOfflineDeviceInfo(const std::string & pkgName,const DmDeviceInfo & info)72 void DmDeviceStateManager::DeleteOfflineDeviceInfo(const std::string &pkgName, const DmDeviceInfo &info)
73 {
74     (void)pkgName;
75     LOGI("DeleteOfflineDeviceInfo begin, deviceId = %s", GetAnonyString(std::string(info.deviceId)).c_str());
76 #if defined(__LITEOS_M__)
77     DmMutex mutexLock;
78 #else
79     std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
80 #endif
81     for (auto iter: remoteDeviceInfos_) {
82         if (iter.second.deviceId == info.deviceId) {
83             remoteDeviceInfos_.erase(iter.first);
84             LOGI("DeleteOfflineDeviceInfo complete");
85             break;
86         }
87     }
88 }
89 
PostDeviceOnline(const std::string & pkgName,DmDeviceInfo & info)90 void DmDeviceStateManager::PostDeviceOnline(const std::string &pkgName, DmDeviceInfo &info)
91 {
92     LOGI("DmDeviceStateManager::PostDeviceOnline in");
93     if (listener_ != nullptr) {
94         DmDeviceState state = DEVICE_STATE_ONLINE;
95         info.authForm = GetAuthForm(info.networkId);
96         listener_->OnDeviceStateChange(pkgName, state, info);
97     }
98     LOGI("DmDeviceStateManager::PostDeviceOnline out");
99 }
100 
PostDeviceOffline(const std::string & pkgName,const DmDeviceInfo & info)101 void DmDeviceStateManager::PostDeviceOffline(const std::string &pkgName, const DmDeviceInfo &info)
102 {
103     LOGI("DmDeviceStateManager::PostDeviceOffline in");
104     if (listener_ != nullptr) {
105         DmDeviceState state = DEVICE_STATE_OFFLINE;
106         listener_->OnDeviceStateChange(pkgName, state, info);
107     }
108     LOGI("DmDeviceStateManager::PostDeviceOffline out");
109 }
110 
PostDeviceChanged(const std::string & pkgName,const DmDeviceInfo & info)111 void DmDeviceStateManager::PostDeviceChanged(const std::string &pkgName, const DmDeviceInfo &info)
112 {
113     LOGI("DmDeviceStateManager::PostDeviceChanged in");
114     if (listener_ != nullptr) {
115         DmDeviceState state = DEVICE_INFO_CHANGED;
116         listener_->OnDeviceStateChange(pkgName, state, info);
117     }
118     LOGI("DmDeviceStateManager::PostDeviceChanged out");
119 }
120 
OnDeviceOnline(const std::string & pkgName,DmDeviceInfo & info)121 void DmDeviceStateManager::OnDeviceOnline(const std::string &pkgName, DmDeviceInfo &info)
122 {
123     LOGI("OnDeviceOnline function is called with pkgName: %s", pkgName.c_str());
124     RegisterOffLineTimer(info);
125     SaveOnlineDeviceInfo(pkgName, info);
126 
127     DmAdapterManager &adapterMgrPtr = DmAdapterManager::GetInstance();
128     std::shared_ptr<IDecisionAdapter> decisionAdapter = adapterMgrPtr.GetDecisionAdapter(decisionSoName_);
129 #if defined(__LITEOS_M__)
130     DmMutex mutexLock;
131 #else
132     std::lock_guard<std::mutex> mutexLock(decisionInfosMutex_);
133 #endif
134     if (decisionAdapter == nullptr) {
135         LOGE("OnDeviceOnline decision adapter is null");
136         PostDeviceOnline(pkgName, info);
137     } else if (decisionInfos_.size() == 0) {
138         PostDeviceOnline(pkgName, info);
139     } else {
140         std::vector<DmDeviceInfo> infoList;
141         LOGI("OnDeviceOnline decision decisionInfos_ size: %d", decisionInfos_.size());
142         for (auto iter : decisionInfos_) {
143             std::string listenerPkgName = iter.first;
144             std::string extra = iter.second;
145             infoList.clear();
146             infoList.push_back(info);
147             decisionAdapter->FilterDeviceList(infoList, extra);
148             if (infoList.size() == 1) {
149                 PostDeviceOnline(listenerPkgName, info);
150             }
151         }
152     }
153     LOGI("DmDeviceStateManager::OnDeviceOnline out");
154 }
155 
OnDeviceOffline(const std::string & pkgName,const DmDeviceInfo & info)156 void DmDeviceStateManager::OnDeviceOffline(const std::string &pkgName, const DmDeviceInfo &info)
157 {
158     LOGI("OnDeviceOffline function is called with pkgName: %s", pkgName.c_str());
159     StartOffLineTimer(info);
160     DeleteOfflineDeviceInfo(pkgName, info);
161 
162     DmAdapterManager &adapterMgrPtr = DmAdapterManager::GetInstance();
163     std::shared_ptr<IDecisionAdapter> decisionAdapter = adapterMgrPtr.GetDecisionAdapter(decisionSoName_);
164 #if defined(__LITEOS_M__)
165     DmMutex mutexLock;
166 #else
167     std::lock_guard<std::mutex> mutexLock(decisionInfosMutex_);
168 #endif
169     if (decisionAdapter == nullptr) {
170         LOGE("OnDeviceOffline decision adapter is null");
171         PostDeviceOffline(pkgName, info);
172     } else if (decisionInfos_.size() == 0) {
173         PostDeviceOffline(pkgName, info);
174     } else {
175         std::vector<DmDeviceInfo> infoList;
176         LOGI("OnDeviceOffline decision decisionInfos_ size: %d", decisionInfos_.size());
177         for (auto iter : decisionInfos_) {
178             std::string listenerPkgName = iter.first;
179             std::string extra = iter.second;
180             infoList.clear();
181             infoList.push_back(info);
182             decisionAdapter->FilterDeviceList(infoList, extra);
183             if (infoList.size() == 1) {
184                 PostDeviceOffline(listenerPkgName, info);
185             }
186         }
187     }
188     LOGI("DmDeviceStateManager::OnDeviceOffline out");
189 }
190 
OnDeviceChanged(const std::string & pkgName,const DmDeviceInfo & info)191 void DmDeviceStateManager::OnDeviceChanged(const std::string &pkgName, const DmDeviceInfo &info)
192 {
193     LOGI("OnDeviceChanged function is called with pkgName: %s", pkgName.c_str());
194     ChangeDeviceInfo(pkgName, info);
195     DmAdapterManager &adapterMgrPtr = DmAdapterManager::GetInstance();
196     std::shared_ptr<IDecisionAdapter> decisionAdapter = adapterMgrPtr.GetDecisionAdapter(decisionSoName_);
197 #if defined(__LITEOS_M__)
198     DmMutex mutexLock;
199 #else
200     std::lock_guard<std::mutex> mutexLock(decisionInfosMutex_);
201 #endif
202     if (decisionAdapter == nullptr) {
203         LOGE("OnDeviceChanged decision adapter is null");
204         PostDeviceChanged(pkgName, info);
205     } else if (decisionInfos_.size() == 0) {
206         PostDeviceChanged(pkgName, info);
207     } else {
208         std::vector<DmDeviceInfo> infoList;
209         LOGI("OnDeviceChanged decision decisionInfos_ size: %d", decisionInfos_.size());
210         for (auto iter : decisionInfos_) {
211             std::string listenerPkgName = iter.first;
212             std::string extra = iter.second;
213             infoList.clear();
214             infoList.push_back(info);
215             decisionAdapter->FilterDeviceList(infoList, extra);
216             if (infoList.size() == 1) {
217                 PostDeviceChanged(listenerPkgName, info);
218             }
219         }
220     }
221     LOGI("DmDeviceStateManager::OnDeviceChanged out");
222 }
223 
OnDeviceReady(const std::string & pkgName,const DmDeviceInfo & info)224 void DmDeviceStateManager::OnDeviceReady(const std::string &pkgName, const DmDeviceInfo &info)
225 {
226     LOGI("OnDeviceReady function is called back with pkgName: %s", pkgName.c_str());
227 }
228 
OnDbReady(const std::string & pkgName,const std::string & deviceId)229 void DmDeviceStateManager::OnDbReady(const std::string &pkgName, const std::string &deviceId)
230 {
231     LOGI("OnDbReady function is called with pkgName: %s", pkgName.c_str());
232     if (pkgName.empty() || deviceId.empty()) {
233         LOGE("On db ready pkgName is empty or deviceId is deviceId");
234         return;
235     }
236     DmDeviceInfo saveInfo;
237     {
238 #if defined(__LITEOS_M__)
239         DmMutex mutexLock;
240 #else
241         std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
242 #endif
243         auto iter = remoteDeviceInfos_.find(deviceId);
244         if (iter == remoteDeviceInfos_.end()) {
245             LOGE("OnDbReady complete not find deviceId: %s", GetAnonyString(deviceId).c_str());
246             return;
247         }
248         saveInfo = iter->second;
249     }
250     DmDistributedHardwareLoad::GetInstance().LoadDistributedHardwareFwk();
251     if (listener_ != nullptr) {
252         DmDeviceState state = DEVICE_INFO_READY;
253         listener_->OnDeviceStateChange(pkgName, state, saveInfo);
254     }
255 }
256 
RegisterSoftbusStateCallback()257 int32_t DmDeviceStateManager::RegisterSoftbusStateCallback()
258 {
259     if (softbusConnector_ != nullptr) {
260         return softbusConnector_->RegisterSoftbusStateCallback(std::string(DM_PKG_NAME), shared_from_this());
261     }
262     return DM_OK;
263 }
264 
RegisterDevStateCallback(const std::string & pkgName,const std::string & extra)265 void DmDeviceStateManager::RegisterDevStateCallback(const std::string &pkgName, const std::string &extra)
266 {
267     if (pkgName.empty()) {
268         LOGE("DmDeviceStateManager::RegisterDevStateCallback input param is empty");
269         return;
270     }
271     LOGI("DmDeviceStateManager::RegisterDevStateCallback pkgName = %s, extra = %s",
272         GetAnonyString(pkgName).c_str(), GetAnonyString(extra).c_str());
273 #if defined(__LITEOS_M__)
274     DmMutex mutexLock;
275 #else
276     std::lock_guard<std::mutex> mutexLock(decisionInfosMutex_);
277 #endif
278     if (decisionInfos_.count(pkgName) == 0) {
279         decisionInfos_.insert(std::map<std::string, std::string>::value_type (pkgName, extra));
280     }
281 }
282 
UnRegisterDevStateCallback(const std::string & pkgName,const std::string & extra)283 void DmDeviceStateManager::UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra)
284 {
285     if (pkgName.empty()) {
286         LOGE("DmDeviceStateManager::UnRegisterDevStateCallback input param is empty");
287         return;
288     }
289     LOGI("DmDeviceStateManager::UnRegisterDevStateCallback pkgName = %s, extra = %s",
290         GetAnonyString(pkgName).c_str(), GetAnonyString(extra).c_str());
291 #if defined(__LITEOS_M__)
292     DmMutex mutexLock;
293 #else
294     std::lock_guard<std::mutex> mutexLock(decisionInfosMutex_);
295 #endif
296     if (decisionInfos_.count(pkgName) > 0) {
297         auto iter = decisionInfos_.find(pkgName);
298         if (iter != decisionInfos_.end()) {
299             decisionInfos_.erase(pkgName);
300         }
301     }
302 }
303 
RegisterOffLineTimer(const DmDeviceInfo & deviceInfo)304 void DmDeviceStateManager::RegisterOffLineTimer(const DmDeviceInfo &deviceInfo)
305 {
306     std::string deviceUdid;
307     int32_t ret = softbusConnector_->GetUdidByNetworkId(deviceInfo.networkId, deviceUdid);
308     if (ret != DM_OK) {
309         LOGE("fail to get udid by networkId");
310         return;
311     }
312     LOGI("Register offline timer for deviceUdid: %s", GetAnonyString(deviceUdid).c_str());
313 #if defined(__LITEOS_M__)
314     DmMutex mutexLock;
315 #else
316     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
317 #endif
318     for (auto &iter : stateTimerInfoMap_) {
319         if ((iter.first == deviceUdid) && (timer_ != nullptr)) {
320             timer_->DeleteTimer(iter.second.timerName);
321             stateTimerInfoMap_.erase(iter.first);
322             break;
323         }
324     }
325     if (stateTimerInfoMap_.find(deviceUdid) == stateTimerInfoMap_.end()) {
326         std::string timerName = std::string(STATE_TIMER_PREFIX) + GetAnonyString(deviceUdid);
327         StateTimerInfo stateTimer = {
328             .timerName = timerName,
329             .networkId = deviceInfo.networkId,
330             .isStart = false,
331         };
332         stateTimerInfoMap_[deviceUdid] = stateTimer;
333     }
334 }
335 
StartOffLineTimer(const DmDeviceInfo & deviceInfo)336 void DmDeviceStateManager::StartOffLineTimer(const DmDeviceInfo &deviceInfo)
337 {
338 #if defined(__LITEOS_M__)
339     DmMutex mutexLock;
340 #else
341     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
342 #endif
343     std::string networkId = deviceInfo.networkId;
344     LOGI("Start offline timer for networkId: %s", GetAnonyString(networkId).c_str());
345     if (timer_ == nullptr) {
346         timer_ = std::make_shared<DmTimer>();
347     }
348     for (auto &iter : stateTimerInfoMap_) {
349         if ((iter.second.networkId == networkId) && !iter.second.isStart) {
350             timer_->StartTimer(iter.second.timerName, OFFLINE_TIMEOUT,
351                 [this] (std::string name) {
352                     DmDeviceStateManager::DeleteTimeOutGroup(name);
353                 });
354             iter.second.isStart = true;
355         }
356     }
357 }
358 
DeleteTimeOutGroup(std::string name)359 void DmDeviceStateManager::DeleteTimeOutGroup(std::string name)
360 {
361 #if defined(__LITEOS_M__)
362     DmMutex mutexLock;
363 #else
364     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
365 #endif
366     for (auto iter = stateTimerInfoMap_.begin(); iter != stateTimerInfoMap_.end(); iter++) {
367         if (((iter->second).timerName == name) && (hiChainConnector_ != nullptr)) {
368             LOGI("remove hichain group with deviceId: %s", GetAnonyString(iter->first).c_str());
369             hiChainConnector_->DeleteTimeOutGroup((iter->first).c_str());
370             stateTimerInfoMap_.erase(iter);
371             break;
372         }
373     }
374 }
375 
StartEventThread()376 void DmDeviceStateManager::StartEventThread()
377 {
378     LOGI("StartEventThread begin");
379     eventTask_.threadRunning_ = true;
380     eventTask_.queueThread_ = std::thread(&DmDeviceStateManager::ThreadLoop, this);
381     LOGI("StartEventThread complete");
382 }
383 
StopEventThread()384 void DmDeviceStateManager::StopEventThread()
385 {
386     LOGI("StopEventThread begin");
387     eventTask_.threadRunning_ = false;
388     eventTask_.queueCond_.notify_all();
389     eventTask_.queueFullCond_.notify_all();
390     if (eventTask_.queueThread_.joinable()) {
391         eventTask_.queueThread_.join();
392     }
393     LOGI("StopEventThread complete");
394 }
395 
AddTask(const std::shared_ptr<NotifyEvent> & task)396 int32_t DmDeviceStateManager::AddTask(const std::shared_ptr<NotifyEvent> &task)
397 {
398     LOGI("AddTask begin, eventId: %d", task->GetEventId());
399     {
400         std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
401         while (eventTask_.queue_.size() >= DM_EVENT_QUEUE_CAPACITY) {
402             eventTask_.queueFullCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
403         }
404         eventTask_.queue_.push(task);
405     }
406     eventTask_.queueCond_.notify_one();
407     LOGI("AddTask complete");
408     return DM_OK;
409 }
410 
ThreadLoop()411 void DmDeviceStateManager::ThreadLoop()
412 {
413     LOGI("ThreadLoop begin");
414     int32_t ret = pthread_setname_np(pthread_self(), THREAD_LOOP);
415     if (ret != DM_OK) {
416         LOGE("ThreadLoop setname failed.");
417     }
418     while (eventTask_.threadRunning_) {
419         std::shared_ptr<NotifyEvent> task = nullptr;
420         {
421             std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
422             while (eventTask_.queue_.empty() && eventTask_.threadRunning_) {
423                 eventTask_.queueCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
424             }
425             if (!eventTask_.queue_.empty()) {
426                 task = eventTask_.queue_.front();
427                 eventTask_.queue_.pop();
428                 eventTask_.queueFullCond_.notify_one();
429             }
430         }
431         if (task != nullptr) {
432             RunTask(task);
433         }
434     }
435     LOGI("ThreadLoop end");
436 }
437 
RunTask(const std::shared_ptr<NotifyEvent> & task)438 void DmDeviceStateManager::RunTask(const std::shared_ptr<NotifyEvent> &task)
439 {
440     LOGI("RunTask begin, eventId: %d", task->GetEventId());
441     if (task->GetEventId() == DM_NOTIFY_EVENT_ONDEVICEREADY) {
442         OnDbReady(std::string(DM_PKG_NAME), task->GetDeviceId());
443     }
444     LOGI("RunTask complete");
445 }
446 
GetAuthForm(const std::string & networkId)447 DmAuthForm DmDeviceStateManager::GetAuthForm(const std::string &networkId)
448 {
449     LOGI("GetAuthForm start");
450     if (hiChainConnector_ == nullptr) {
451         LOGE("hiChainConnector_ is nullptr");
452         return DmAuthForm::INVALID_TYPE;
453     }
454 
455     if (networkId.empty()) {
456         LOGE("networkId is empty");
457         return DmAuthForm::INVALID_TYPE;
458     }
459 
460     std::string udid;
461     if (SoftbusConnector::GetUdidByNetworkId(networkId.c_str(), udid) == DM_OK) {
462         return hiChainConnector_->GetGroupType(udid);
463     }
464 
465     return DmAuthForm::INVALID_TYPE;
466 }
467 
ProcNotifyEvent(const std::string & pkgName,const int32_t eventId,const std::string & deviceId)468 int32_t DmDeviceStateManager::ProcNotifyEvent(const std::string &pkgName, const int32_t eventId,
469     const std::string &deviceId)
470 {
471     (void)pkgName;
472     LOGI("ProcNotifyEvent in, eventId: %d", eventId);
473     return AddTask(std::make_shared<NotifyEvent>(eventId, deviceId));
474 }
475 
ChangeDeviceInfo(const std::string & pkgName,const DmDeviceInfo & info)476 void DmDeviceStateManager::ChangeDeviceInfo(const std::string &pkgName, const DmDeviceInfo &info)
477 {
478     (void)pkgName;
479 #if defined(__LITEOS_M__)
480     DmMutex mutexLock;
481 #else
482     std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
483 #endif
484     for (auto iter: remoteDeviceInfos_) {
485         if (iter.second.deviceId == info.deviceId) {
486             if (memcpy_s(iter.second.deviceName, sizeof(iter.second.deviceName), info.deviceName,
487                 sizeof(info.deviceName)) != DM_OK) {
488                     LOGE("ChangeDeviceInfo copy deviceName failed");
489             }
490             if (memcpy_s(iter.second.networkId, sizeof(iter.second.networkId), info.networkId,
491                 sizeof(info.networkId)) != DM_OK) {
492                     LOGE("ChangeDeviceInfo copy networkId failed");
493             }
494             iter.second.deviceTypeId = info.deviceTypeId;
495             LOGI("ChangeDeviceInfo complete");
496             break;
497         }
498     }
499 }
500 } // namespace DistributedHardware
501 } // namespace OHOS