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