• 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 "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