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