• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_send_adapter.h"
17 
18 #include <map>
19 #include <string>
20 #include <securec.h>
21 
22 #include "mechbody_controller_log.h"
23 #include "mc_command_factory.h"
24 #include "mc_connect_manager.h"
25 #include "mc_data_buffer.h"
26 #include "mc_protocol_convertor.h"
27 
28 namespace OHOS {
29 namespace MechBodyController {
30 namespace {
31     const std::string TAG = "TransportSendAdapter";
32     const std::string RESPONSE_TIMEOUT_TASK = "transport_send_task";
33     constexpr int32_t RESPONSE_TIMEOUT = 10000;
34     constexpr int32_t CMD_RETRY_INTERVAL = 10; //ms
35 }
36 
TransportSendAdapter()37 TransportSendAdapter::TransportSendAdapter()
38 {
39     HILOGI("called");
40     if (sendEventHandler_ != nullptr && recvEventHandler_ != nullptr) {
41         HILOGI("already inited, end.");
42         return;
43     }
44     sendEventThread_ = std::thread(&TransportSendAdapter::StartSendEvent, this);
45     std::unique_lock<std::mutex> sendLock(sendEventMutex_);
46     sendEventCon_.wait(sendLock, [this] {
47         return sendEventHandler_ != nullptr;
48     });
49 
50     recvEventThread_ = std::thread(&TransportSendAdapter::StartRecvEvent, this);
51     std::unique_lock<std::mutex> recvLock(recvEventMutex_);
52     recvEventCon_.wait(recvLock, [this] {
53         return recvEventHandler_ != nullptr;
54     });
55 
56     HILOGI("end");
57 }
58 
StartSendEvent()59 void TransportSendAdapter::StartSendEvent()
60 {
61     HILOGI("called");
62     prctl(PR_SET_NAME, TAG.c_str());
63     auto runner = AppExecFwk::EventRunner::Create(false);
64     {
65         std::lock_guard<std::mutex> lock(sendEventMutex_);
66         sendEventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
67     }
68     sendEventCon_.notify_one();
69     CHECK_POINTER_RETURN(runner, "runner");
70     runner->Run();
71     HILOGI("end");
72 }
73 
StartRecvEvent()74 void TransportSendAdapter::StartRecvEvent()
75 {
76     HILOGI("called");
77     prctl(PR_SET_NAME, TAG.c_str());
78     auto runner = AppExecFwk::EventRunner::Create(false);
79     {
80         std::lock_guard<std::mutex> lock(recvEventMutex_);
81         recvEventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
82     }
83     recvEventCon_.notify_one();
84     CHECK_POINTER_RETURN(runner, "runner");
85     runner->Run();
86     HILOGI("end");
87 }
88 
~TransportSendAdapter()89 TransportSendAdapter::~TransportSendAdapter()
90 {
91     HILOGI("called");
92     if (sendEventHandler_ != nullptr) {
93         sendEventHandler_->GetEventRunner()->Stop();
94         HILOGI("prepare to clear thread resources");
95         if (sendEventThread_.joinable()) {
96             HILOGI("start clearing thread resources");
97             sendEventThread_.join();
98         }
99         sendEventHandler_ = nullptr;
100     } else {
101         HILOGE("sendEventHandler is nullptr");
102     }
103     std::lock_guard<std::mutex> lock(recvEventMutex_);
104     if (recvEventHandler_ != nullptr) {
105         recvEventHandler_->GetEventRunner()->Stop();
106         HILOGI("prepare to clear thread resources");
107         if (recvEventThread_.joinable()) {
108             HILOGI("start clearing thread resources");
109             recvEventThread_.join();
110         }
111         recvEventHandler_ = nullptr;
112     } else {
113         HILOGE("recvEventHandler is nullptr");
114     }
115     UnRegisterBluetoothListener();
116     HILOGI("end");
117 }
118 
RegisterBluetoothListener()119 int32_t TransportSendAdapter::RegisterBluetoothListener()
120 {
121     HILOGI("called");
122     if (receviceListener_ == nullptr) {
123         HILOGI("RegisterReceiveListener");
124         receviceListener_ = std::make_shared<BleReceviceListenerImpl>(shared_from_this());
125     }
126     int32_t ret = BleSendManager::GetInstance().RegisterTransportSendAdapter(receviceListener_);
127     if (ret != ERR_OK) {
128         HILOGE("get RegisterBluetoothEventListener failed, ret: %{public}d", ret);
129     }
130     HILOGI("end.");
131     return ERR_OK;
132 }
133 
UnRegisterBluetoothListener()134 int32_t TransportSendAdapter::UnRegisterBluetoothListener()
135 {
136     HILOGI("UnRegisterBluetoothListenercalled");
137     if (receviceListener_ == nullptr) {
138         HILOGI("UnRegisterReceiveListener ok.");
139         return ERR_OK;
140     }
141     int32_t ret = BleSendManager::GetInstance().UnRegisterTransportSendAdapter(receviceListener_);
142     if (ret != ERR_OK) {
143         HILOGE("get RegisterBluetoothEventListener failed, ret: %{public}d", ret);
144     }
145     HILOGI("end.");
146     return ERR_OK;
147 }
148 
SendCommand(const std::shared_ptr<CommandBase> & cmd,int32_t delayMs)149 int32_t TransportSendAdapter::SendCommand(const std::shared_ptr<CommandBase> &cmd, int32_t delayMs)
150 {
151     if (cmd == nullptr) {
152         HILOGE("cmd is nullptr");
153         return INVALID_PARAMETERS_ERR;
154     }
155 
156     auto sendTask = [this, cmd]() {
157         HILOGI("sendTask cmdType: 0x%{public}x", cmd->GetCmdType());
158         if (MechConnectManager::GetInstance().GetLocalDeviceBleStatus() == false) {
159             HILOGE("ble status error");
160             return;
161         }
162         std::shared_ptr<MechDataBuffer> mechDataBuffer = cmd->Marshal();
163         if (mechDataBuffer == nullptr) {
164             HILOGE("mechDataBuffer is nullptr");
165             return;
166         }
167         uint16_t seqNo = CreateResponseSeqNo();
168 
169         ProtocolConverter protocolConverter;
170         OptType optType = cmd->NeedResponse() ? OptType::GET : OptType::PUT;
171         auto buffer = protocolConverter.Convert(optType, seqNo, mechDataBuffer);
172         if (buffer == nullptr) {
173             HILOGE("buffer is nullptr");
174             return;
175         }
176         int32_t result = BleSendManager::GetInstance().SendData(buffer->Data(), buffer->Size());
177         HILOGI("sendTask cmdType: 0x%{public}x; dataLen= %{public}zu, result = %{public}d",
178             cmd->GetCmdType(), buffer->Size(), result);
179         std::this_thread::sleep_for(std::chrono::milliseconds(CMD_RETRY_INTERVAL));
180         int32_t retry = cmd->GetRetryTimes();
181         while (result != Bluetooth::BT_SUCCESS && retry > 0) {
182             HILOGI("data send failed, retry.");
183             retry--;
184             result = BleSendManager::GetInstance().SendData(buffer->Data(), buffer->Size());
185             HILOGI("sendTask cmdType: 0x%{public}x; dataLen= %{public}zu, result = %{public}d",
186                 cmd->GetCmdType(), buffer->Size(), result);
187             std::this_thread::sleep_for(std::chrono::milliseconds(CMD_RETRY_INTERVAL));
188         }
189 
190         if (cmd->NeedResponse()) {
191             PushResponseTask(cmd, seqNo);
192         }
193     };
194 
195     CHECK_POINTER_RETURN_VALUE(sendEventHandler_, INVALID_PARAMETERS_ERR, "sendEventHandler_");
196     sendEventHandler_->PostTask(sendTask, delayMs);
197 
198     HILOGI("end");
199     return ERR_OK;
200 }
201 
OnReceive(const uint8_t * data,uint32_t dataLen)202 int32_t BleReceviceListenerImpl::OnReceive(const uint8_t *data, uint32_t dataLen)
203 {
204     HILOGD("called");
205     ProtocolConverter protocolConverter;
206     if (!protocolConverter.Validate(data, dataLen)) {
207         HILOGE("protocolConverter Validate");
208         return INVALID_PARAMETERS_ERR;
209     }
210     std::shared_ptr<MechDataBuffer> mechDataBuffer = std::make_shared<MechDataBuffer>(dataLen);
211     if (mechDataBuffer == nullptr) {
212         HILOGE("mechDataBuffer is nullptr");
213         return INVALID_PARAMETERS_ERR;
214     }
215     mechDataBuffer->SetRange(0, dataLen);
216     if (memcpy_s(mechDataBuffer->Data(), mechDataBuffer->Size(), data, dataLen) != 0) {
217         HILOGE("memcpy failed");
218         return INVALID_PARAMETERS_ERR;
219     }
220     uint16_t seqNo = 0;
221     bool isAck = false;
222     std::shared_ptr<MechDataBuffer> newMechDataBuffer = protocolConverter.GetData(mechDataBuffer, seqNo, isAck);
223     return sendAdapter_->OnReceive(isAck, seqNo, newMechDataBuffer);
224 }
225 
OnReceive(bool isAck,uint16_t seqNo,std::shared_ptr<MechDataBuffer> dataBuffer)226 int32_t TransportSendAdapter::OnReceive(bool isAck, uint16_t seqNo, std::shared_ptr<MechDataBuffer> dataBuffer)
227 {
228     CHECK_POINTER_RETURN_VALUE(dataBuffer, INVALID_PARAMETERS_ERR, "dataBuffer");
229     if (!isAck) {
230         CommandFactory commandFactory;
231         std::shared_ptr<CommandBase> cmd = commandFactory.CreateFromData(dataBuffer);
232         if (cmd == nullptr) {
233             HILOGE("cmd is nullptr");
234             return ERR_OK;
235         }
236         auto recvTask = [this, cmd]() {
237             SubscriptionCenter::GetInstance().Notify(cmd);
238         };
239         std::lock_guard<std::mutex> lock(recvEventMutex_);
240         if (recvEventHandler_ == nullptr) {
241             HILOGE("eventHandler is nullptr");
242             return ERR_OK;
243         }
244         recvEventHandler_->PostTask(recvTask);
245         return ERR_OK;
246     }
247 
248     auto responseTask = [this, seqNo, dataBuffer]() {
249         ExeResponseTask(seqNo, dataBuffer);
250     };
251     std::lock_guard<std::mutex> lock(recvEventMutex_);
252     if (recvEventHandler_ == nullptr) {
253         HILOGE("eventHandler is nullptr");
254         return ERR_OK;
255     }
256     recvEventHandler_->PostTask(responseTask);
257     const std::string taskName = RESPONSE_TIMEOUT_TASK + std::to_string(seqNo);
258     recvEventHandler_->RemoveTask(taskName);
259     return ERR_OK;
260 }
261 
BleReceviceListenerImpl(std::shared_ptr<TransportSendAdapter> sendAdapter)262 BleReceviceListenerImpl::BleReceviceListenerImpl(std::shared_ptr<TransportSendAdapter> sendAdapter)
263 {
264     sendAdapter_ = sendAdapter;
265 }
266 
PushResponseTask(const std::shared_ptr<CommandBase> & cmd,uint16_t seqNo)267 int32_t TransportSendAdapter::PushResponseTask(const std::shared_ptr<CommandBase> &cmd, uint16_t seqNo)
268 {
269     if (cmd == nullptr) {
270         HILOGE("cmd is nullptr");
271         return INVALID_PARAMETERS_ERR;
272     }
273     {
274         std::unique_lock<std::shared_mutex> responseReadLock(responseMutex_);
275         pendingRequests_.insert(std::make_pair(seqNo, cmd));
276     }
277     HILOGI("cmdType : 0x%{public}x, seqNo: %{public}d", cmd->GetCmdType(), seqNo);
278     std::lock_guard<std::mutex> lock(recvEventMutex_);
279     if (recvEventHandler_ == nullptr) {
280         HILOGE("eventHandler is nullptr");
281         return INVALID_PARAMETERS_ERR;
282     }
283     auto responseTimeoutTask = [this, seqNo]() {
284         ExeRespTimeoutTask(seqNo);
285     };
286     const std::string taskName = RESPONSE_TIMEOUT_TASK + std::to_string(seqNo);
287     recvEventHandler_->PostTask(responseTimeoutTask, taskName, RESPONSE_TIMEOUT);
288     HILOGI("end");
289     return ERR_OK;
290 }
291 
CreateResponseSeqNo()292 uint16_t TransportSendAdapter::CreateResponseSeqNo()
293 {
294     std::unique_lock<std::shared_mutex> responseReadLock(responseMutex_);
295     if (lastSeqNo_ >= UINT16_MAX) {
296         HILOGE("the seqNo is full, reorder the seqNo.");
297         lastSeqNo_ = 0;
298         return 0;
299     }
300     uint16_t seqNo = ++lastSeqNo_;
301     HILOGI("end, new seqNo is %{public}d", seqNo);
302     return seqNo;
303 }
304 
GetCmdBySeqNo(uint16_t seqNo)305 const std::shared_ptr<CommandBase> TransportSendAdapter::GetCmdBySeqNo(uint16_t seqNo)
306 {
307     HILOGI("called");
308     std::unique_lock<std::shared_mutex> responseReadLock(responseMutex_);
309     if (pendingRequests_.count(seqNo) != 0) {
310         return pendingRequests_[seqNo];
311     }
312     HILOGI("end");
313     return nullptr;
314 }
315 
ExeResponseTask(uint16_t seqNo,const std::shared_ptr<MechDataBuffer> & mechDataBuffer)316 int32_t TransportSendAdapter::ExeResponseTask(uint16_t seqNo, const std::shared_ptr<MechDataBuffer>& mechDataBuffer)
317 {
318     CHECK_POINTER_RETURN_VALUE(mechDataBuffer, INVALID_PARAMETERS_ERR, "mechDataBuffer");
319     HILOGI("called, seqNo: %{public}d", seqNo);
320     {
321         std::unique_lock<std::shared_mutex> responseWriteLock(responseMutex_);
322         auto it = pendingRequests_.find(seqNo);
323         if (it != pendingRequests_.end() && it->second != nullptr) {
324             it->second->TriggerResponse(mechDataBuffer);
325             pendingRequests_.erase(it);
326         }
327     }
328     HILOGI("end");
329     return ERR_OK;
330 }
331 
ExeRespTimeoutTask(uint16_t seqNo)332 int32_t TransportSendAdapter::ExeRespTimeoutTask(uint16_t seqNo)
333 {
334     HILOGI("called, seqNo: %{public}d", seqNo);
335     {
336         std::unique_lock<std::shared_mutex> responseWriteLock(responseMutex_);
337         auto it = pendingRequests_.find(seqNo);
338         if (it != pendingRequests_.end() && it->second != nullptr) {
339             it->second->TriggerTimeout();
340             pendingRequests_.erase(it);
341         }
342     }
343     HILOGI("end");
344     return ERR_OK;
345 }
346 
RemoveRespTimeoutTask(uint16_t seqNo)347 int32_t TransportSendAdapter::RemoveRespTimeoutTask(uint16_t seqNo)
348 {
349     HILOGI("called");
350     {
351         std::unique_lock<std::shared_mutex> responseWriteLock(responseMutex_);
352         auto it = pendingRequests_.find(seqNo);
353         if (it != pendingRequests_.end()) {
354             pendingRequests_.erase(it);
355         }
356     }
357     HILOGI("end");
358     return ERR_OK;
359 }
360 }  // namespace MechBodyController
361 }  // namespace OHOS
362