• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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         }
257     }
258     if (stateTimerInfoMap_.find(deviceId) == stateTimerInfoMap_.end()) {
259         std::string timerName = std::string(STATE_TIMER_PREFIX) + GetAnonyString(deviceId);
260         StateTimerInfo stateTimer = {
261             .timerName = timerName,
262             .networkId = deviceInfo.deviceId,
263             .isStart = false,
264         };
265         stateTimerInfoMap_[deviceId] = stateTimer;
266     }
267 }
268 
StartOffLineTimer(const DmDeviceInfo & deviceInfo)269 void DmDeviceStateManager::StartOffLineTimer(const DmDeviceInfo &deviceInfo)
270 {
271 #if defined(__LITEOS_M__)
272     DmMutex mutexLock;
273 #else
274     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
275 #endif
276     std::string networkId = deviceInfo.deviceId;
277     LOGI("Start offline timer for networkId: %s", GetAnonyString(networkId).c_str());
278     if (timer_ == nullptr) {
279         timer_ = std::make_shared<DmTimer>();
280     }
281     for (auto &iter : stateTimerInfoMap_) {
282         if ((iter.second.networkId == networkId) && !iter.second.isStart) {
283             timer_->StartTimer(iter.second.timerName, OFFLINE_TIMEOUT,
284                 [this] (std::string name) {
285                     DmDeviceStateManager::DeleteTimeOutGroup(name);
286                 });
287             iter.second.isStart = true;
288         }
289     }
290 }
291 
DeleteTimeOutGroup(std::string name)292 void DmDeviceStateManager::DeleteTimeOutGroup(std::string name)
293 {
294 #if defined(__LITEOS_M__)
295     DmMutex mutexLock;
296 #else
297     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
298 #endif
299     for (auto iter = stateTimerInfoMap_.begin(); iter != stateTimerInfoMap_.end(); iter++) {
300         if (((iter->second).timerName == name) && (hiChainConnector_ != nullptr)) {
301             LOGI("remove hichain group with deviceId: %s", GetAnonyString(iter->first).c_str());
302             hiChainConnector_->DeleteTimeOutGroup((iter->first).c_str());
303             stateTimerInfoMap_.erase(iter);
304             break;
305         }
306     }
307 }
308 
StartEventThread()309 void DmDeviceStateManager::StartEventThread()
310 {
311     LOGI("StartEventThread begin");
312     eventTask_.threadRunning_ = true;
313     eventTask_.queueThread_ = std::thread(&DmDeviceStateManager::ThreadLoop, this);
314     LOGI("StartEventThread complete");
315 }
316 
StopEventThread()317 void DmDeviceStateManager::StopEventThread()
318 {
319     LOGI("StopEventThread begin");
320     eventTask_.threadRunning_ = false;
321     eventTask_.queueCond_.notify_all();
322     eventTask_.queueFullCond_.notify_all();
323     if (eventTask_.queueThread_.joinable()) {
324         eventTask_.queueThread_.join();
325     }
326     LOGI("StopEventThread complete");
327 }
328 
AddTask(const std::shared_ptr<NotifyEvent> & task)329 int32_t DmDeviceStateManager::AddTask(const std::shared_ptr<NotifyEvent> &task)
330 {
331     LOGI("AddTask begin, eventId: %d", task->GetEventId());
332     {
333         std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
334         while (eventTask_.queue_.size() >= DM_EVENT_QUEUE_CAPACITY) {
335             eventTask_.queueFullCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
336         }
337         eventTask_.queue_.push(task);
338     }
339     eventTask_.queueCond_.notify_one();
340     LOGI("AddTask complete");
341     return DM_OK;
342 }
343 
ThreadLoop()344 void DmDeviceStateManager::ThreadLoop()
345 {
346     LOGI("ThreadLoop begin");
347     while (eventTask_.threadRunning_) {
348         std::shared_ptr<NotifyEvent> task = nullptr;
349         {
350             std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
351             while (eventTask_.queue_.empty() && eventTask_.threadRunning_) {
352                 eventTask_.queueCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
353             }
354             if (!eventTask_.queue_.empty()) {
355                 task = eventTask_.queue_.front();
356                 eventTask_.queue_.pop();
357                 eventTask_.queueFullCond_.notify_one();
358             }
359         }
360         if (task != nullptr) {
361             RunTask(task);
362         }
363     }
364     LOGI("ThreadLoop end");
365 }
366 
RunTask(const std::shared_ptr<NotifyEvent> & task)367 void DmDeviceStateManager::RunTask(const std::shared_ptr<NotifyEvent> &task)
368 {
369     LOGI("RunTask begin, eventId: %d", task->GetEventId());
370     if (task->GetEventId() == DM_NOTIFY_EVENT_ONDEVICEREADY) {
371         OnDbReady(std::string(DM_PKG_NAME), task->GetDeviceId());
372     }
373     LOGI("RunTask complete");
374 }
375 
ProcNotifyEvent(const std::string & pkgName,const int32_t eventId,const std::string & deviceId)376 int32_t DmDeviceStateManager::ProcNotifyEvent(const std::string &pkgName, const int32_t eventId,
377     const std::string &deviceId)
378 {
379     LOGI("ProcNotifyEvent in, eventId: %d", eventId);
380     return AddTask(std::make_shared<NotifyEvent>(eventId, deviceId));
381 }
382 } // namespace DistributedHardware
383 } // namespace OHOS