1 /*
2 * Copyright (c) 2025 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 "mc_connect_manager.h"
17
18 #include <chrono>
19 #include <functional>
20 #include <thread>
21 #include <unistd.h>
22
23 #include "event_runner.h"
24 #include "mechbody_controller_service.h"
25
26 namespace OHOS {
27 namespace MechBodyController {
GetInstance()28 MechConnectManager& MechConnectManager::GetInstance()
29 {
30 static auto instance = new MechConnectManager();
31 return *instance;
32 }
33
34 namespace {
35 const std::string TAG = "MechConnectManager";
36 }
37
Init()38 void MechConnectManager::Init()
39 {
40 HILOGI("called");
41 auto runner = AppExecFwk::EventRunner::Create("dmsDnetwork");
42 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
43 }
44
UnInit()45 void MechConnectManager::UnInit()
46 {
47 HILOGI("called");
48 if (eventHandler_ != nullptr) {
49 eventHandler_->GetEventRunner()->Stop();
50 } else {
51 HILOGE("eventHandler_ is nullptr");
52 }
53 }
54
NotifyMechConnect(MechInfo & mechInfo)55 int32_t MechConnectManager::NotifyMechConnect(MechInfo& mechInfo)
56 {
57 MechBodyControllerService::GetInstance().OnDeviceConnected(mechInfo.mechId);
58 auto connectNotifyTask = [this, mechInfo]() {
59 std::lock_guard<std::mutex> autoLock(listenerSetMutex_);
60 for (auto& listener : listenerSet_) {
61 if (listener != nullptr) {
62 listener->OnMechConnect(mechInfo);
63 }
64 }
65 };
66 if (eventHandler_ == nullptr || !eventHandler_->PostTask(connectNotifyTask)) {
67 HILOGE("post task failed");
68 return ERR_OK;
69 }
70 return ERR_OK;
71 }
72
NotifyMechDisconnect(const MechInfo & mechInfo)73 int32_t MechConnectManager::NotifyMechDisconnect(const MechInfo& mechInfo)
74 {
75 HILOGI("called, mechId: %{public}d.", mechInfo.mechId);
76 {
77 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
78 auto it = mechInfos_.find(mechInfo);
79 if (it != mechInfos_.end()) {
80 mechInfos_.erase(it);
81 MechBodyControllerService::GetInstance().OnDeviceDisconnected(mechInfo.mechId);
82 }
83 }
84 auto offlineNotifyTask = [this, mechInfo]() {
85 std::lock_guard<std::mutex> autoLock(listenerSetMutex_);
86 for (auto& listener : listenerSet_) {
87 if (listener != nullptr) {
88 listener->OnMechDisconnect(mechInfo);
89 }
90 }
91 };
92 if (eventHandler_ == nullptr || !eventHandler_->PostTask(offlineNotifyTask)) {
93 HILOGE("post task failed");
94 return ERR_OK;
95 }
96 return ERR_OK;
97 }
98
AddDeviceChangeListener(const std::shared_ptr<IMechConnectListener> & listener)99 int32_t MechConnectManager::AddDeviceChangeListener(const std::shared_ptr<IMechConnectListener>& listener)
100 {
101 HILOGI("called");
102 if (listener == nullptr) {
103 HILOGI("listener is nullptr.");
104 return INVALID_PARAMETERS_ERR;
105 }
106 std::lock_guard<std::mutex> autoLock(listenerSetMutex_);
107 auto result = listenerSet_.insert(listener);
108 if (!result.second) {
109 HILOGI("listener is already.");
110 }
111 if (listenerSet_.find(listener) == listenerSet_.end()) {
112 HILOGI("error.");
113 return INVALID_PARAMETERS_ERR;
114 }
115 return ERR_OK;
116 }
117
RemoveDeviceChangeListener(const std::shared_ptr<IMechConnectListener> & listener)118 int32_t MechConnectManager::RemoveDeviceChangeListener(const std::shared_ptr<IMechConnectListener>& listener)
119 {
120 HILOGI("called");
121 if (listener == nullptr) {
122 HILOGI("listener is nullptr.");
123 return INVALID_PARAMETERS_ERR;
124 }
125 {
126 std::lock_guard<std::mutex> autoLock(listenerSetMutex_);
127 auto it = listenerSet_.find(listener);
128 if (it == listenerSet_.end()) {
129 HILOGI("error.");
130 return INVALID_PARAMETERS_ERR;
131 }
132 listenerSet_.erase(listener);
133 if (listenerSet_.size() > 0) {
134 return ERR_OK;
135 }
136 }
137 HILOGI("remove ok");
138 return ERR_OK;
139 }
140
GetMechBasicInfo(int32_t mechId,MechInfo & mechInfo)141 bool MechConnectManager::GetMechBasicInfo(int32_t mechId, MechInfo& mechInfo)
142 {
143 HILOGI("called, mechId: %{public}d", mechId);
144 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
145 auto it = std::find_if(mechInfos_.begin(), mechInfos_.end(), [mechId](const MechInfo& mechInfo) {
146 return mechInfo.mechId == mechId;
147 });
148 if (it == mechInfos_.end()) {
149 HILOGE("not found");
150 return false;
151 }
152 HILOGI("found");
153 mechInfo = *it;
154 return true;
155 }
156
GetConnectMechList(std::set<MechInfo> & mechInfos)157 bool MechConnectManager::GetConnectMechList(std::set<MechInfo>& mechInfos)
158 {
159 HILOGI("called");
160 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
161 if (mechInfos_.empty()) {
162 HILOGE("list is empty");
163 return false;
164 }
165 mechInfos = mechInfos_;
166 return true;
167 }
168
NotifyMechState(int32_t mechId,bool isAttached)169 bool MechConnectManager::NotifyMechState(int32_t mechId, bool isAttached)
170 {
171 HILOGI("called, mechId: %{public}d. isAttached %{public}d", mechId, isAttached);
172 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
173 auto it = std::find_if(mechInfos_.begin(), mechInfos_.end(),
174 [&](const MechInfo& mechInfo) { return mechInfo.mechId == mechId; });
175 if (it == mechInfos_.end()) {
176 HILOGE("can not find this mechInfo");
177 return false;
178 }
179 MechInfo newMechInfo = *it;
180 newMechInfo.state = isAttached ? AttachmentState::ATTACHED : AttachmentState::DETACHED;
181 mechInfos_.erase(it);
182 mechInfos_.insert(newMechInfo);
183
184 if (!isAttached) {
185 auto disconnectTask = [this, newMechInfo]() mutable {
186 BleSendManager::GetInstance().MechbodyDisConnect(newMechInfo);
187 };
188 if (eventHandler_ == nullptr || !eventHandler_->PostTask(disconnectTask, "disconnect")) {
189 HILOGE("MECHBODY_EXEC_CONNECT post task failed");
190 return ERR_OK;
191 }
192 }
193 return true;
194 }
195
GetMechState(int32_t mechId)196 bool MechConnectManager::GetMechState(int32_t mechId)
197 {
198 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
199 auto it = std::find_if(mechInfos_.begin(), mechInfos_.end(), [mechId](const MechInfo& mechInfo) {
200 return mechInfo.mechId == mechId;
201 });
202 if (it == mechInfos_.end()) {
203 HILOGE("mechId: %{public}d not found", mechId);
204 return false;
205 }
206 HILOGD("mechId: %{public}d found", mechId);
207 MechInfo mechInfo = *it;
208 return mechInfo.state == AttachmentState::ATTACHED ? true : false;
209 }
210
UpdateBleStatus(bool isBLEActive)211 bool MechConnectManager::UpdateBleStatus(bool isBLEActive)
212 {
213 HILOGI("called");
214 isBLEActive_.store(isBLEActive);
215 return true;
216 }
217
GetLocalDeviceBleStatus()218 bool MechConnectManager::GetLocalDeviceBleStatus()
219 {
220 HILOGD("called");
221 return isBLEActive_.load();
222 }
223
IsConnect()224 bool MechConnectManager::IsConnect()
225 {
226 HILOGI("called");
227 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
228 if (mechInfos_.empty() || mechInfos_.size() == 0) {
229 HILOGW("list is empty");
230 return false;
231 }
232 return true;
233 }
234
AddMechInfo(MechInfo & mechInfo)235 int32_t MechConnectManager::AddMechInfo(MechInfo &mechInfo)
236 {
237 {
238 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", mechInfo.ToString().c_str());
239 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
240 while (mechInfos_.count(mechInfo) != 0) {
241 mechInfo.mechId = (mechInfo.mechId + 1) % INT32_MAX;
242 }
243 mechInfos_.insert(mechInfo);
244 }
245 return ERR_OK;
246 }
247
248
GetMechInfo(std::string & mac,MechInfo & mechInfo)249 int32_t MechConnectManager::GetMechInfo(std::string &mac, MechInfo &mechInfo)
250 {
251 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
252 for (auto &info: mechInfos_) {
253 if (info.mac == mac) {
254 mechInfo = info;
255 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
256 return ERR_OK;
257 }
258 }
259 return MECH_INFO_NOT_FOUND;
260 }
261
SetMechanicGattState(std::string & mac,bool state)262 int32_t MechConnectManager::SetMechanicGattState(std::string &mac, bool state)
263 {
264 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
265 for (const auto& info : mechInfos_) {
266 if (info.mac == mac) {
267 const_cast<MechInfo&>(info).gattCoonectState = state;
268 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
269 return ERR_OK;
270 }
271 }
272 return MECH_INFO_NOT_FOUND;
273 }
GetMechanicGattState(std::string & mac,bool & state)274 int32_t MechConnectManager::GetMechanicGattState(std::string &mac, bool &state)
275 {
276 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
277 for (auto &info: mechInfos_) {
278 if (info.mac == mac) {
279 state = info.gattCoonectState;
280 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
281 return ERR_OK;
282 }
283 }
284 return MECH_INFO_NOT_FOUND;
285 }
286
SetMechanicPairState(std::string & mac,bool state)287 int32_t MechConnectManager::SetMechanicPairState(std::string &mac, bool state)
288 {
289 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
290 for (const auto& info : mechInfos_) {
291 if (info.mac == mac) {
292 const_cast<MechInfo&>(info).pairState = state;
293 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
294 return ERR_OK;
295 }
296 }
297 return MECH_INFO_NOT_FOUND;
298 }
299
GetMechanicPairState(std::string & mac,bool & state)300 int32_t MechConnectManager::GetMechanicPairState(std::string &mac, bool &state)
301 {
302 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
303 for (auto &info: mechInfos_) {
304 if (info.mac == mac) {
305 state = info.pairState;
306 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
307 return ERR_OK;
308 }
309 }
310 return MECH_INFO_NOT_FOUND;
311 }
312
SetMechanicHidState(std::string & mac,bool state)313 int32_t MechConnectManager::SetMechanicHidState(std::string &mac, bool state)
314 {
315 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
316 for (const auto& info : mechInfos_) {
317 if (info.mac == mac) {
318 const_cast<MechInfo&>(info).hidState = state;
319 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
320 return ERR_OK;
321 }
322 }
323 return MECH_INFO_NOT_FOUND;
324 }
325
GetMechanicHidState(std::string & mac,bool & state)326 int32_t MechConnectManager::GetMechanicHidState(std::string &mac, bool &state)
327 {
328 std::lock_guard<std::mutex> autoLock(mechInfosMutex_);
329 for (auto &info: mechInfos_) {
330 if (info.mac == mac) {
331 state = info.hidState;
332 HILOGI("MECHBODY_EXEC_CONNECT mechInfo: %{public}s", info.ToString().c_str());
333 return ERR_OK;
334 }
335 }
336 return MECH_INFO_NOT_FOUND;
337 }
338 } // namespace MechBodyController
339 } // namespace OHOS
340