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 "opp_statemachine.h"
17
18 #include "log.h"
19 #include "opp_service.h"
20
21 namespace OHOS {
22 namespace bluetooth {
OppStateMachine(const std::string & address)23 OppStateMachine::OppStateMachine(const std::string &address)
24 : address_(address)
25 {}
26
Init()27 void OppStateMachine::Init()
28 {
29 connTimer_ = std::make_unique<utility::Timer>(
30 std::bind(&bluetooth::OppStateMachine::ConnectionTimeout, this));
31 disconnTimer_ = std::make_unique<utility::Timer>(
32 std::bind(&bluetooth::OppStateMachine::DisonnectionTimeout, this));
33
34 std::unique_ptr<utility::StateMachine::State> disconnectedState =
35 std::make_unique<OppDisconnectedState>(DISCONNECTED, *this);
36 std::unique_ptr<utility::StateMachine::State> connectingState =
37 std::make_unique<OppConnectingState>(CONNECTING, *this);
38 std::unique_ptr<utility::StateMachine::State> disconnectingState =
39 std::make_unique<OppDisconnectingState>(DISCONNECTING, *this);
40 std::unique_ptr<utility::StateMachine::State> connectedState =
41 std::make_unique<OppConnectedState>(CONNECTED, *this);
42
43 Move(disconnectedState);
44 Move(connectingState);
45 Move(disconnectingState);
46 Move(connectedState);
47
48 InitState(DISCONNECTED);
49 }
50
IsRemoving() const51 bool OppStateMachine::IsRemoving() const
52 {
53 return isRemoving_;
54 }
55
SetRemoving(bool isRemoving)56 void OppStateMachine::SetRemoving(bool isRemoving)
57 {
58 isRemoving_ = isRemoving;
59 }
60
GetDeviceAdress()61 std::string OppStateMachine::GetDeviceAdress()
62 {
63 return address_;
64 }
65
Entry()66 void OppDisconnectedState::Entry()
67 {
68 if (isReentry_) {
69 stateMachine_.SetRemoving(true);
70 OppService *service = OppService::GetService();
71 if (service != nullptr) {
72 service->RemoveStateMachine(stateMachine_.GetDeviceAdress());
73 } else {
74 HILOGE("[OPP Machine]:OppService is nullptr!");
75 }
76 stateMachine_.NotifyStateTransitions();
77 }
78 }
79
Exit()80 void OppDisconnectedState::Exit()
81 {
82 isReentry_ = true;
83 }
84
Dispatch(const utility::Message & msg)85 bool OppDisconnectedState::Dispatch(const utility::Message &msg)
86 {
87 OppMessage &event = (OppMessage &)msg;
88 HILOGI("[OPP Machine]:[Disconnected][%{public}s]",
89 OppStateMachine::GetEventName(event.what_).c_str());
90 switch (event.what_) {
91 case OPP_CONNECT_REQ_EVT:
92 stateMachine_.ProcessConnectReqEvent(event);
93 Transition(OppStateMachine::CONNECTING);
94 break;
95 case OPP_CONNECTED_EVT:
96 stateMachine_.ProcessConnectedEvent(event);
97 Transition(OppStateMachine::CONNECTED);
98 break;
99 default:
100 break;
101 }
102 return true;
103 }
104
Entry()105 void OppConnectingState::Entry()
106 {
107 stateMachine_.NotifyStateTransitions();
108 stateMachine_.StartConnectionTimer();
109 }
Exit()110 void OppConnectingState::Exit()
111 {
112 stateMachine_.StopConnectionTimer();
113 }
114
Dispatch(const utility::Message & msg)115 bool OppConnectingState::Dispatch(const utility::Message &msg)
116 {
117 OppMessage &event = (OppMessage &)msg;
118 HILOGI("[OPP Machine]:[Connecting][%{public}s]",
119 OppStateMachine::GetEventName(event.what_).c_str());
120 switch (event.what_) {
121 case OPP_DISCONNECT_REQ_EVT:
122 stateMachine_.ProcessDisconnectReqEvent(event);
123 Transition(OppStateMachine::DISCONNECTING);
124 break;
125 case OPP_CONNECTED_EVT:
126 stateMachine_.ProcessConnectedEvent(event);
127 Transition(OppStateMachine::CONNECTED);
128 break;
129 case OPP_DISCONNECTED_EVT:
130 stateMachine_.ProcessDisconnectedEvent(event);
131 Transition(OppStateMachine::DISCONNECTED);
132 break;
133 case OPP_SDP_CMPL_EVT:
134 stateMachine_.ProcessSdpCompleteEvent(event);
135 break;
136 case OPP_GAP_CMPL_EVT:
137 stateMachine_.ProcessGapCompleteEvent(event);
138 break;
139 case OPP_CONNECTION_TIMEOUT_EVT:
140 stateMachine_.ProcessDisconnectedEvent(event);
141 Transition(OppStateMachine::DISCONNECTED);
142 break;
143 default:
144 break;
145 }
146 return true;
147 }
148
Entry()149 void OppDisconnectingState::Entry()
150 {
151 stateMachine_.NotifyStateTransitions();
152 stateMachine_.StartDisconnectionTimer();
153 }
154
Exit()155 void OppDisconnectingState::Exit()
156 {
157 stateMachine_.StopDisconnectionTimer();
158 }
159
Dispatch(const utility::Message & msg)160 bool OppDisconnectingState::Dispatch(const utility::Message &msg)
161 {
162 OppMessage &event = (OppMessage &)msg;
163 HILOGI("[OPP Machine]:[Disconnecting][%{public}s]",
164 OppStateMachine::GetEventName(event.what_).c_str());
165 switch (event.what_) {
166 case OPP_CONNECTED_EVT:
167 stateMachine_.ProcessConnectedEvent(event);
168 Transition(OppStateMachine::CONNECTED);
169 break;
170 case OPP_DISCONNECTED_EVT:
171 stateMachine_.ProcessDisconnectedEvent(event);
172 Transition(OppStateMachine::DISCONNECTED);
173 break;
174 case OPP_DISCONNECTION_TIMEOUT_EVT:
175 stateMachine_.ProcessDisconnectedEvent(event);
176 Transition(OppStateMachine::DISCONNECTED);
177 break;
178 default:
179 break;
180 }
181 return true;
182 }
183
Entry()184 void OppConnectedState::Entry()
185 {
186 stateMachine_.NotifyStateTransitions();
187 }
188
Exit()189 void OppConnectedState::Exit()
190 {
191 }
192
Dispatch(const utility::Message & msg)193 bool OppConnectedState::Dispatch(const utility::Message &msg)
194 {
195 OppMessage &event = (OppMessage &)msg;
196 HILOGI("[OPP Machine]:[Connected][%{public}s]",
197 OppStateMachine::GetEventName(event.what_).c_str());
198 switch (event.what_) {
199 case OPP_DISCONNECT_REQ_EVT:
200 stateMachine_.ProcessDisconnectReqEvent(event);
201 Transition(OppStateMachine::DISCONNECTING);
202 break;
203 case OPP_DISCONNECTED_EVT:
204 stateMachine_.ProcessDisconnectedEvent(event);
205 Transition(OppStateMachine::DISCONNECTED);
206 break;
207 default:
208 break;
209 }
210 return true;
211 }
212
ProcessConnectReqEvent(const OppMessage & msg)213 void OppStateMachine::ProcessConnectReqEvent(const OppMessage &msg)
214 {
215 if (sdpClient_ == nullptr) {
216 sdpClient_ = std::make_unique<OppSdpClient>(address_);
217 }
218 sdpClient_->SdpSearch();
219 }
220
ProcessDisconnectReqEvent(const OppMessage & msg)221 void OppStateMachine::ProcessDisconnectReqEvent(const OppMessage &msg)
222 {
223 OppService::GetService()->DisconnectObex(address_);
224 }
225
ProcessSdpCompleteEvent(const OppMessage & msg)226 void OppStateMachine::ProcessSdpCompleteEvent(const OppMessage &msg)
227 {
228 if (msg.arg1_ == OPP_SDP_SUCCESS) {
229 GapSecChannel gapSecChannel;
230 RawAddress(address_).ConvertToUint8(obexConfig_.addr_.addr);
231 obexConfig_.addr_.type = BT_PUBLIC_DEVICE_ADDRESS;
232 obexConfig_.lpsm_ = OPP_GOEP_L2CAP_PSM;
233 obexConfig_.isSupportReliableSession_ = false;
234 if (msg.sdpInfo_.psm > 0) {
235 obexConfig_.isGoepL2capPSM_ = true;
236 obexConfig_.scn_ = msg.sdpInfo_.psm;
237 obexConfig_.isSupportSrm_ = true;
238 obexConfig_.mtu_ = OppService::GetService()->GetOppConfig().l2capMtu;
239 gapSecChannel.l2capPsm = obexConfig_.scn_;
240 } else {
241 obexConfig_.scn_ = msg.sdpInfo_.rfcommNo;
242 obexConfig_.mtu_ = OppService::GetService()->GetOppConfig().rfcommMtu;
243 gapSecChannel.rfcommChannel = obexConfig_.scn_;
244 }
245 gapClient_ = std::make_unique<OppGapClient>(address_, gapSecChannel, obexConfig_.isGoepL2capPSM_);
246 if ((gapClient_->Register() != BT_NO_ERROR) || (gapClient_->RequestSecurity() != BT_NO_ERROR)) {
247 OppMessage event(OPP_DISCONNECTED_EVT);
248 event.dev_ = address_;
249 OppService::GetService()->PostEvent(event);
250 }
251 } else {
252 OppMessage event(OPP_DISCONNECTED_EVT);
253 event.dev_ = address_;
254 OppService::GetService()->PostEvent(event);
255 }
256 }
257
ProcessGapCompleteEvent(const OppMessage & msg)258 void OppStateMachine::ProcessGapCompleteEvent(const OppMessage &msg)
259 {
260 if (msg.arg1_ == OPP_GAP_SUCCESS) {
261 OppService::GetService()->ConnectObex(address_, obexConfig_);
262 } else {
263 OppMessage event(OPP_DISCONNECTED_EVT);
264 event.dev_ = address_;
265 OppService::GetService()->PostEvent(event);
266 }
267 }
268
ProcessConnectedEvent(const OppMessage & msg)269 void OppStateMachine::ProcessConnectedEvent(const OppMessage &msg)
270 {
271 OppService::GetService()->OnObexConnected(address_);
272 }
273
ProcessDisconnectedEvent(const OppMessage & msg)274 void OppStateMachine::ProcessDisconnectedEvent(const OppMessage &msg)
275 {
276 OppService::GetService()->OnObexDisconnected(address_);
277 }
278
GetDeviceStateInt() const279 int OppStateMachine::GetDeviceStateInt() const
280 {
281 return static_cast<const OppState*>(GetState())->GetStateInt();
282 }
283
StartConnectionTimer() const284 void OppStateMachine::StartConnectionTimer() const
285 {
286 connTimer_->Start(connectionTimeoutMs);
287 HILOGI("[OPP Machine]:Start connection timer!");
288 }
289
StopConnectionTimer() const290 void OppStateMachine::StopConnectionTimer() const
291 {
292 connTimer_->Stop();
293 HILOGI("[OPP Machine]:Stop connection timer!");
294 }
295
ConnectionTimeout() const296 void OppStateMachine::ConnectionTimeout() const
297 {
298 OppMessage event(OPP_CONNECTION_TIMEOUT_EVT);
299 event.dev_ = address_;
300 OppService::GetService()->PostEvent(event);
301 }
302
StartDisconnectionTimer() const303 void OppStateMachine::StartDisconnectionTimer() const
304 {
305 disconnTimer_->Start(disconnectionTimeoutMs);
306 HILOGI("[OPP Machine]:Start disconnection timer!");
307 }
308
StopDisconnectionTimer() const309 void OppStateMachine::StopDisconnectionTimer() const
310 {
311 disconnTimer_->Stop();
312 HILOGI("[OPP Machine]:Stop disconnection timer!");
313 }
314
DisonnectionTimeout() const315 void OppStateMachine::DisonnectionTimeout() const
316 {
317 OppMessage event(OPP_DISCONNECTION_TIMEOUT_EVT);
318 event.dev_ = address_;
319 OppService::GetService()->PostEvent(event);
320 }
321
GetEventName(int what)322 std::string OppStateMachine::GetEventName(int what)
323 {
324 switch (what) {
325 case OPP_CONNECT_REQ_EVT:
326 return "OPP_CONNECT_REQ_EVT";
327 case OPP_DISCONNECT_REQ_EVT:
328 return "OPP_DISCONNECT_REQ_EVT";
329 case OPP_CONNECTED_EVT:
330 return "OPP_CONNECTED_EVT";
331 case OPP_DISCONNECTED_EVT:
332 return "OPP_DISCONNECTED_EVT";
333 case OPP_SDP_CMPL_EVT:
334 return "OPP_SDP_CMPL_EVT";
335 case OPP_GAP_CMPL_EVT:
336 return "OPP_GAP_CMPL_EVT";
337 case OPP_CONNECTION_TIMEOUT_EVT:
338 return "OPP_CONNECTION_TIMEOUT_EVT";
339 case OPP_DISCONNECTION_TIMEOUT_EVT:
340 return "OPP_DISCONNECTION_TIMEOUT_EVT";
341 default:
342 return "Unknown";
343 }
344 }
345
NotifyStateTransitions()346 void OppStateMachine::NotifyStateTransitions()
347 {
348 OppService *service = OppService::GetService();
349 int toState = GetDeviceStateInt();
350 if (service != nullptr) {
351 RawAddress device(address_);
352 if ((preState_ != toState) && (preState_ <= OPP_STATE_CONNECTED) &&
353 (toState <= OPP_STATE_CONNECTED)) {
354 service->NotifyStateChanged(device, toState);
355 }
356 }
357
358 preState_ = toState;
359 }
360 } // namespace bluetooth
361 } // namespace OHOS
362