• 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 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
26 #include "deviceprofile_connector.h"
27 #endif
28 
29 namespace OHOS {
30 namespace DistributedHardware {
31 const uint32_t DM_EVENT_QUEUE_CAPACITY = 20;
32 const uint32_t DM_EVENT_WAIT_TIMEOUT = 2;
33 constexpr const char* THREAD_LOOP = "ThreadLoop";
DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,std::shared_ptr<IDeviceManagerServiceListener> listener,std::shared_ptr<HiChainConnector> hiChainConnector,std::shared_ptr<HiChainAuthConnector> hiChainAuthConnector)34 DmDeviceStateManager::DmDeviceStateManager(std::shared_ptr<SoftbusConnector> softbusConnector,
35     std::shared_ptr<IDeviceManagerServiceListener> listener, std::shared_ptr<HiChainConnector> hiChainConnector,
36     std::shared_ptr<HiChainAuthConnector> hiChainAuthConnector)
37     : softbusConnector_(softbusConnector), listener_(listener), hiChainConnector_(hiChainConnector),
38     hiChainAuthConnector_(hiChainAuthConnector)
39 {
40     decisionSoName_ = "libdevicemanagerext_decision.z.so";
41     StartEventThread();
42     LOGI("DmDeviceStateManager constructor");
43 }
44 
~DmDeviceStateManager()45 DmDeviceStateManager::~DmDeviceStateManager()
46 {
47     LOGI("DmDeviceStateManager destructor");
48     softbusConnector_->UnRegisterSoftbusStateCallback();
49     StopEventThread();
50 }
51 
RegisterSoftbusStateCallback()52 int32_t DmDeviceStateManager::RegisterSoftbusStateCallback()
53 {
54     if (softbusConnector_ != nullptr) {
55         return softbusConnector_->RegisterSoftbusStateCallback(shared_from_this());
56     }
57     return DM_OK;
58 }
59 
SaveOnlineDeviceInfo(const DmDeviceInfo & info)60 void DmDeviceStateManager::SaveOnlineDeviceInfo(const DmDeviceInfo &info)
61 {
62     LOGI("SaveOnlineDeviceInfo begin, deviceId = %s", GetAnonyString(std::string(info.deviceId)).c_str());
63     std::string udid;
64     if (SoftbusConnector::GetUdidByNetworkId(info.networkId, udid) == DM_OK) {
65         std::string uuid;
66         DmDeviceInfo saveInfo = info;
67         SoftbusConnector::GetUuidByNetworkId(info.networkId, uuid);
68         {
69             std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
70             remoteDeviceInfos_[uuid] = saveInfo;
71             stateDeviceInfos_[udid] = saveInfo;
72         }
73         LOGI("SaveOnlineDeviceInfo complete, networkId = %s, udid = %s, uuid = %s",
74              GetAnonyString(std::string(info.networkId)).c_str(),
75              GetAnonyString(udid).c_str(), GetAnonyString(uuid).c_str());
76     }
77 }
78 
DeleteOfflineDeviceInfo(const DmDeviceInfo & info)79 void DmDeviceStateManager::DeleteOfflineDeviceInfo(const DmDeviceInfo &info)
80 {
81     LOGI("DeleteOfflineDeviceInfo begin, deviceId = %s", GetAnonyString(std::string(info.deviceId)).c_str());
82     std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
83     std::string deviceId = std::string(info.deviceId);
84     for (auto iter: remoteDeviceInfos_) {
85         if (std::string(iter.second.deviceId) == deviceId) {
86             remoteDeviceInfos_.erase(iter.first);
87             LOGI("Delete remoteDeviceInfos complete");
88             break;
89         }
90     }
91     for (auto iter: stateDeviceInfos_) {
92         if (std::string(iter.second.deviceId) == deviceId) {
93             stateDeviceInfos_.erase(iter.first);
94             LOGI("Delete stateDeviceInfos complete");
95             break;
96         }
97     }
98 }
99 
OnDeviceOnline(std::string deviceId)100 void DmDeviceStateManager::OnDeviceOnline(std::string deviceId)
101 {
102     LOGI("DmDeviceStateManager::OnDeviceOnline, deviceId = %s", GetAnonyString(deviceId).c_str());
103     DmDeviceInfo devInfo = softbusConnector_->GetDeviceInfoByDeviceId(deviceId);
104     {
105         std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
106         stateDeviceInfos_[deviceId] = devInfo;
107     }
108     std::vector<std::string> pkgName = softbusConnector_->GetPkgName();
109     if (pkgName.size() == 0) {
110         listener_->OnDeviceStateChange(std::string(DM_PKG_NAME), DEVICE_STATE_ONLINE, devInfo);
111     } else {
112         for (auto item : pkgName) {
113             listener_->OnDeviceStateChange(item, DEVICE_STATE_ONLINE, devInfo);
114         }
115     }
116     softbusConnector_->ClearPkgName();
117 }
118 
OnDeviceOffline(std::string deviceId)119 void DmDeviceStateManager::OnDeviceOffline(std::string deviceId)
120 {
121     LOGI("DmDeviceStateManager::OnDeviceOffline, deviceId = %s", GetAnonyString(deviceId).c_str());
122     {
123         std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
124         if (stateDeviceInfos_.find(deviceId) == stateDeviceInfos_.end()) {
125             LOGE("DmDeviceStateManager::OnDeviceOnline not find deviceId");
126             return;
127         }
128     }
129     DmDeviceInfo devInfo = stateDeviceInfos_[deviceId];
130     std::vector<std::string> pkgName = softbusConnector_->GetPkgName();
131     if (pkgName.size() == 0) {
132         listener_->OnDeviceStateChange(std::string(DM_PKG_NAME), DEVICE_STATE_OFFLINE, devInfo);
133     } else {
134         for (auto item : pkgName) {
135             listener_->OnDeviceStateChange(item, DEVICE_STATE_OFFLINE, devInfo);
136         }
137     }
138     softbusConnector_->ClearPkgName();
139 }
140 
HandleDeviceStatusChange(DmDeviceState devState,DmDeviceInfo & devInfo)141 void DmDeviceStateManager::HandleDeviceStatusChange(DmDeviceState devState, DmDeviceInfo &devInfo)
142 {
143     LOGI("Handle device status change: devState=%d, deviceId=%s.", devState, GetAnonyString(devInfo.deviceId).c_str());
144     switch (devState) {
145         case DEVICE_STATE_ONLINE:
146             RegisterOffLineTimer(devInfo);
147             SaveOnlineDeviceInfo(devInfo);
148             devInfo.authForm = GetAuthForm(devInfo.networkId);
149             DmDistributedHardwareLoad::GetInstance().LoadDistributedHardwareFwk();
150             break;
151         case DEVICE_STATE_OFFLINE:
152             StartOffLineTimer(devInfo);
153             DeleteOfflineDeviceInfo(devInfo);
154             if (softbusConnector_ != nullptr) {
155                 std::string udid;
156                 softbusConnector_->GetUdidByNetworkId(devInfo.networkId, udid);
157                 softbusConnector_->EraseUdidFromMap(udid);
158             }
159             break;
160         case DEVICE_INFO_CHANGED:
161             ChangeDeviceInfo(devInfo);
162             break;
163         default:
164             LOGE("HandleDeviceStatusChange error, unknown device state = %d", devState);
165             break;
166     }
167     if (listener_ == nullptr) {
168         LOGE("HandleDeviceStatusChange failed, device manager client listener is null.");
169         return;
170     }
171     if (softbusConnector_ != nullptr) {
172         std::vector<std::string> pkgName = softbusConnector_->GetPkgName();
173         if (pkgName.size() == 0) {
174             listener_->OnDeviceStateChange(std::string(DM_PKG_NAME), devState, devInfo);
175         } else {
176             for (auto item : pkgName) {
177                 listener_->OnDeviceStateChange(item, devState, devInfo);
178             }
179         }
180         softbusConnector_->ClearPkgName();
181     }
182 }
183 
OnDbReady(const std::string & pkgName,const std::string & uuid)184 void DmDeviceStateManager::OnDbReady(const std::string &pkgName, const std::string &uuid)
185 {
186     LOGI("OnDbReady function is called with pkgName: %s and uuid = %s",
187          pkgName.c_str(), GetAnonyString(uuid).c_str());
188     if (pkgName.empty() || uuid.empty()) {
189         LOGE("On db ready pkgName is empty or uuid is empty");
190         return;
191     }
192     DmDeviceInfo saveInfo;
193     {
194         std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
195         auto iter = remoteDeviceInfos_.find(uuid);
196         if (iter == remoteDeviceInfos_.end()) {
197             LOGE("OnDbReady complete not find uuid: %s", GetAnonyString(uuid).c_str());
198             return;
199         }
200         saveInfo = iter->second;
201     }
202     if (listener_ != nullptr) {
203         DmDeviceState state = DEVICE_INFO_READY;
204         listener_->OnDeviceStateChange(pkgName, state, saveInfo);
205     }
206 }
207 
RegisterOffLineTimer(const DmDeviceInfo & deviceInfo)208 void DmDeviceStateManager::RegisterOffLineTimer(const DmDeviceInfo &deviceInfo)
209 {
210     std::string deviceUdid;
211     int32_t ret = softbusConnector_->GetUdidByNetworkId(deviceInfo.networkId, deviceUdid);
212     if (ret != DM_OK) {
213         LOGE("fail to get udid by networkId");
214         return;
215     }
216     LOGI("Register offline timer for deviceUdid: %s", GetAnonyString(deviceUdid).c_str());
217     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
218     for (auto &iter : stateTimerInfoMap_) {
219         if ((iter.first == deviceUdid) && (timer_ != nullptr)) {
220             timer_->DeleteTimer(iter.second.timerName);
221             stateTimerInfoMap_.erase(iter.first);
222             break;
223         }
224     }
225     if (stateTimerInfoMap_.find(deviceUdid) == stateTimerInfoMap_.end()) {
226         std::string timerName = std::string(STATE_TIMER_PREFIX) + GetAnonyString(deviceUdid);
227         StateTimerInfo stateTimer = {
228             .timerName = timerName,
229             .networkId = deviceInfo.networkId,
230             .isStart = false,
231         };
232         stateTimerInfoMap_[deviceUdid] = stateTimer;
233     }
234 }
235 
StartOffLineTimer(const DmDeviceInfo & deviceInfo)236 void DmDeviceStateManager::StartOffLineTimer(const DmDeviceInfo &deviceInfo)
237 {
238     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
239     std::string networkId = deviceInfo.networkId;
240     LOGI("Start offline timer for networkId: %s", GetAnonyString(networkId).c_str());
241     if (timer_ == nullptr) {
242         timer_ = std::make_shared<DmTimer>();
243     }
244     for (auto &iter : stateTimerInfoMap_) {
245         if ((iter.second.networkId == networkId) && !iter.second.isStart) {
246             timer_->StartTimer(iter.second.timerName, OFFLINE_TIMEOUT,
247                 [this] (std::string name) {
248                     DmDeviceStateManager::DeleteTimeOutGroup(name);
249                 });
250             iter.second.isStart = true;
251         }
252     }
253 }
254 
DeleteTimeOutGroup(std::string name)255 void DmDeviceStateManager::DeleteTimeOutGroup(std::string name)
256 {
257     std::lock_guard<std::mutex> mutexLock(timerMapMutex_);
258     for (auto iter = stateTimerInfoMap_.begin(); iter != stateTimerInfoMap_.end(); iter++) {
259         if (((iter->second).timerName == name) && (hiChainConnector_ != nullptr)) {
260             LOGI("remove hichain group with deviceId: %s", GetAnonyString(iter->first).c_str());
261             hiChainConnector_->DeleteTimeOutGroup((iter->first).c_str());
262 #if !(defined(__LITEOS_M__) || defined(LITE_DEVICE))
263             uint32_t res = DeviceProfileConnector::GetInstance().DeleteTimeOutAcl(iter->first);
264             if (res == 0) {
265                 hiChainAuthConnector_->DeleteCredential(iter->first,
266                                                         MultipleUserConnector::GetCurrentAccountUserID());
267             }
268 #endif
269             stateTimerInfoMap_.erase(iter);
270             break;
271         }
272     }
273 }
274 
StartEventThread()275 void DmDeviceStateManager::StartEventThread()
276 {
277     LOGI("StartEventThread begin");
278     eventTask_.threadRunning_ = true;
279     eventTask_.queueThread_ = std::thread(&DmDeviceStateManager::ThreadLoop, this);
280     LOGI("StartEventThread complete");
281 }
282 
StopEventThread()283 void DmDeviceStateManager::StopEventThread()
284 {
285     LOGI("StopEventThread begin");
286     eventTask_.threadRunning_ = false;
287     eventTask_.queueCond_.notify_all();
288     eventTask_.queueFullCond_.notify_all();
289     if (eventTask_.queueThread_.joinable()) {
290         eventTask_.queueThread_.join();
291     }
292     LOGI("StopEventThread complete");
293 }
294 
AddTask(const std::shared_ptr<NotifyEvent> & task)295 int32_t DmDeviceStateManager::AddTask(const std::shared_ptr<NotifyEvent> &task)
296 {
297     LOGI("AddTask begin, eventId: %d", task->GetEventId());
298     {
299         std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
300         while (eventTask_.queue_.size() >= DM_EVENT_QUEUE_CAPACITY) {
301             eventTask_.queueFullCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
302         }
303         eventTask_.queue_.push(task);
304     }
305     eventTask_.queueCond_.notify_one();
306     LOGI("AddTask complete");
307     return DM_OK;
308 }
309 
ThreadLoop()310 void DmDeviceStateManager::ThreadLoop()
311 {
312     LOGI("ThreadLoop begin");
313     int32_t ret = pthread_setname_np(pthread_self(), THREAD_LOOP);
314     if (ret != DM_OK) {
315         LOGE("ThreadLoop setname failed.");
316     }
317     while (eventTask_.threadRunning_) {
318         std::shared_ptr<NotifyEvent> task = nullptr;
319         {
320             std::unique_lock<std::mutex> lock(eventTask_.queueMtx_);
321             while (eventTask_.queue_.empty() && eventTask_.threadRunning_) {
322                 eventTask_.queueCond_.wait_for(lock, std::chrono::seconds(DM_EVENT_WAIT_TIMEOUT));
323             }
324             if (!eventTask_.queue_.empty()) {
325                 task = eventTask_.queue_.front();
326                 eventTask_.queue_.pop();
327                 eventTask_.queueFullCond_.notify_one();
328             }
329         }
330         if (task != nullptr) {
331             RunTask(task);
332         }
333     }
334     LOGI("ThreadLoop end");
335 }
336 
RunTask(const std::shared_ptr<NotifyEvent> & task)337 void DmDeviceStateManager::RunTask(const std::shared_ptr<NotifyEvent> &task)
338 {
339     LOGI("RunTask begin, eventId: %d", task->GetEventId());
340     if (task->GetEventId() == DM_NOTIFY_EVENT_ONDEVICEREADY) {
341         OnDbReady(std::string(DM_PKG_NAME), task->GetDeviceId());
342     }
343     LOGI("RunTask complete");
344 }
345 
GetAuthForm(const std::string & networkId)346 DmAuthForm DmDeviceStateManager::GetAuthForm(const std::string &networkId)
347 {
348     LOGI("GetAuthForm start");
349     if (hiChainConnector_ == nullptr) {
350         LOGE("hiChainConnector_ is nullptr");
351         return DmAuthForm::INVALID_TYPE;
352     }
353 
354     if (networkId.empty()) {
355         LOGE("networkId is empty");
356         return DmAuthForm::INVALID_TYPE;
357     }
358 
359     std::string udid;
360     if (SoftbusConnector::GetUdidByNetworkId(networkId.c_str(), udid) == DM_OK) {
361         return hiChainConnector_->GetGroupType(udid);
362     }
363 
364     return DmAuthForm::INVALID_TYPE;
365 }
366 
ProcNotifyEvent(const int32_t eventId,const std::string & deviceId)367 int32_t DmDeviceStateManager::ProcNotifyEvent(const int32_t eventId, const std::string &deviceId)
368 {
369     LOGI("ProcNotifyEvent in, eventId: %d", eventId);
370     return AddTask(std::make_shared<NotifyEvent>(eventId, deviceId));
371 }
372 
ChangeDeviceInfo(const DmDeviceInfo & info)373 void DmDeviceStateManager::ChangeDeviceInfo(const DmDeviceInfo &info)
374 {
375     std::lock_guard<std::mutex> mutexLock(remoteDeviceInfosMutex_);
376     for (auto iter: remoteDeviceInfos_) {
377         if (iter.second.deviceId == info.deviceId) {
378             if (memcpy_s(iter.second.deviceName, sizeof(iter.second.deviceName), info.deviceName,
379                 sizeof(info.deviceName)) != DM_OK) {
380                     LOGE("ChangeDeviceInfo copy deviceName failed");
381             }
382             if (memcpy_s(iter.second.networkId, sizeof(iter.second.networkId), info.networkId,
383                 sizeof(info.networkId)) != DM_OK) {
384                     LOGE("ChangeDeviceInfo copy networkId failed");
385             }
386             iter.second.deviceTypeId = info.deviceTypeId;
387             LOGI("ChangeDeviceInfo complete");
388             break;
389         }
390     }
391 }
392 } // namespace DistributedHardware
393 } // namespace OHOS