1 /*
2 * Copyright (C) 2021-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 "group_formed_state.h"
17 #include "wifi_p2p_hal_interface.h"
18 #include "p2p_state_machine.h"
19 #include "wifi_p2p_temp_disc_event.h"
20 #include "wifi_logger.h"
21 #include "wifi_hisysevent.h"
22
23 DEFINE_WIFILOG_P2P_LABEL("GroupFormedState");
24
25 namespace OHOS {
26 namespace Wifi {
GroupFormedState(P2pStateMachine & stateMachine,WifiP2pGroupManager & groupMgr,WifiP2pDeviceManager & deviceMgr)27 GroupFormedState::GroupFormedState(
28 P2pStateMachine &stateMachine, WifiP2pGroupManager &groupMgr, WifiP2pDeviceManager &deviceMgr)
29 : State("GroupFormedState"), p2pStateMachine(stateMachine), groupManager(groupMgr), deviceManager(deviceMgr)
30 {
31 Init();
32 }
GoInState()33 void GroupFormedState::GoInState()
34 {
35 WIFI_LOGI(" GoInState");
36 if (!groupManager.GetCurrentGroup().IsGroupOwner()) {
37 WriteWifiP2pStateHiSysEvent(groupManager.GetCurrentGroup().GetInterface(), P2P_GC, P2P_ON);
38 }
39 p2pStateMachine.StopTimer(static_cast<int>(P2P_STATE_MACHINE_CMD::EXCEPTION_TIMED_OUT));
40 }
41
GoOutState()42 void GroupFormedState::GoOutState()
43 {
44 WIFI_LOGI(" GoOutState");
45 }
46
Init()47 void GroupFormedState::Init()
48 {
49 mProcessFunMap.insert(
50 std::make_pair(P2P_STATE_MACHINE_CMD::AP_STA_CONNECTED, &GroupFormedState::ProcessConnectEvt));
51 mProcessFunMap.insert(
52 std::make_pair(P2P_STATE_MACHINE_CMD::AP_STA_DISCONNECTED, &GroupFormedState::ProcessDisconnectEvt));
53 mProcessFunMap.insert(
54 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_DEVICE_LOST, &GroupFormedState::ProcessDeviceLostEvt));
55 mProcessFunMap.insert(
56 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_REMOVE_GROUP, &GroupFormedState::ProcessCmdRemoveGroup));
57 mProcessFunMap.insert(
58 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_DELETE_GROUP, &GroupFormedState::ProcessCmdDeleteGroup));
59 mProcessFunMap.insert(
60 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_REMOVED, &GroupFormedState::ProcessGroupRemovedEvt));
61 mProcessFunMap.insert(
62 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_REMOVE_GROUP_CLIENT, &GroupFormedState::ProcessCmdRemoveGroupClient));
63 mProcessFunMap.insert(
64 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_CONNECT, &GroupFormedState::ProcessCmdConnect));
65 mProcessFunMap.insert(
66 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_PROV_DISC_PBC_REQ, &GroupFormedState::ProcessProvDiscEvt));
67 mProcessFunMap.insert(
68 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_PROV_DISC_ENTER_PIN, &GroupFormedState::ProcessProvDiscEvt));
69 mProcessFunMap.insert(
70 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_PROV_DISC_SHOW_PIN, &GroupFormedState::ProcessProvDiscEvt));
71 mProcessFunMap.insert(
72 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_STARTED, &GroupFormedState::ProcessGroupStartedEvt));
73 mProcessFunMap.insert(
74 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_DEVICE_DISCOVERS, &GroupFormedState::ProcessCmdDiscoverPeer));
75 mProcessFunMap.insert(
76 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_DISCOVER_SERVICES, &GroupFormedState::ProcessCmdDiscServices));
77 mProcessFunMap.insert(
78 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_START_LISTEN, &GroupFormedState::ProcessCmdStartListen));
79 mProcessFunMap.insert(
80 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_P2P_DISABLE, &GroupFormedState::ProcessCmdDisable));
81 mProcessFunMap.insert(
82 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_CANCEL_CONNECT, &GroupFormedState::ProcessCmdCancelConnect));
83 mProcessFunMap.insert(
84 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_CH_SWITCH, &GroupFormedState::ProcessCmdChSwitch));
85 mProcessFunMap.insert(
86 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_IP_ADDRESS, &GroupFormedState::ProcessCmdSetIpAddress));
87 }
88
ProcessCmdConnect(const InternalMessagePtr msg) const89 bool GroupFormedState::ProcessCmdConnect(const InternalMessagePtr msg) const
90 {
91 WifiP2pConfigInternal config;
92 if (!msg->GetMessageObj(config)) {
93 WIFI_LOGE("Connect:Failed to obtain config info.");
94 return EXECUTED;
95 }
96
97 P2pConfigErrCode ret = p2pStateMachine.IsConfigUnusable(config);
98 if (ret != P2pConfigErrCode::SUCCESS) {
99 WIFI_LOGE("Configuration Unavailable");
100 if (ret == P2pConfigErrCode::MAC_EMPTY) {
101 p2pStateMachine.BroadcastActionResult(P2pActionCallback::P2pConnect, ErrCode::WIFI_OPT_INVALID_PARAM);
102 } else if (ret == P2pConfigErrCode::MAC_NOT_FOUND) {
103 p2pStateMachine.BroadcastActionResult(P2pActionCallback::P2pConnect, ErrCode::WIFI_OPT_P2P_MAC_NOT_FOUND);
104 } else if (ret == P2pConfigErrCode::ERR_MAC_FORMAT) {
105 p2pStateMachine.BroadcastActionResult(P2pActionCallback::P2pConnect, ErrCode::WIFI_OPT_P2P_ERR_MAC_FORMAT);
106 }
107 return EXECUTED;
108 }
109
110 p2pStateMachine.savedP2pConfig = config;
111 p2pStateMachine.SwitchState(&p2pStateMachine.p2pInvitationRequestState);
112 return EXECUTED;
113 }
114
ProcessProvDiscEvt(const InternalMessagePtr msg) const115 bool GroupFormedState::ProcessProvDiscEvt(const InternalMessagePtr msg) const
116 {
117 WifiP2pTempDiscEvent procDisc;
118 if (!msg->GetMessageObj(procDisc) || !procDisc.GetDevice().IsValid()) {
119 WIFI_LOGE("Prov disc :Failed to obtain config info.");
120 return EXECUTED;
121 }
122
123 p2pStateMachine.savedP2pConfig = WifiP2pConfigInternal();
124 p2pStateMachine.savedP2pConfig.SetDeviceAddress(procDisc.GetDevice().GetDeviceAddress());
125
126 WpsInfo wps;
127 switch (static_cast<P2P_STATE_MACHINE_CMD>(msg->GetMessageName())) {
128 case P2P_STATE_MACHINE_CMD::P2P_EVENT_PROV_DISC_ENTER_PIN: {
129 wps.SetWpsMethod(WpsMethod::WPS_METHOD_KEYPAD);
130 break;
131 }
132 case P2P_STATE_MACHINE_CMD::P2P_EVENT_PROV_DISC_SHOW_PIN: {
133 wps.SetWpsMethod(WpsMethod::WPS_METHOD_DISPLAY);
134 wps.SetPin(procDisc.GetPin());
135 break;
136 }
137 default: {
138 wps.SetWpsMethod(WpsMethod::WPS_METHOD_PBC);
139 break;
140 }
141 }
142
143 p2pStateMachine.savedP2pConfig.SetWpsInfo(wps);
144 if (groupManager.GetCurrentGroup().IsGroupOwner()) {
145 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupJoinState);
146 } else {
147 /* Do nothing */
148 }
149 return EXECUTED;
150 }
151
ProcessGroupStartedEvt(const InternalMessagePtr msg) const152 bool GroupFormedState::ProcessGroupStartedEvt(const InternalMessagePtr msg) const
153 {
154 WIFI_LOGI("recv CMD: %{public}d", msg->GetMessageName());
155 return EXECUTED;
156 }
157
ProcessCmdDiscoverPeer(const InternalMessagePtr msg) const158 bool GroupFormedState::ProcessCmdDiscoverPeer(const InternalMessagePtr msg) const
159 {
160 WIFI_LOGI("recv CMD: %{public}d", msg->GetMessageName());
161 p2pStateMachine.HandlerDiscoverPeers();
162 return EXECUTED;
163 }
164
ProcessGroupRemovedEvt(const InternalMessagePtr msg) const165 bool GroupFormedState::ProcessGroupRemovedEvt(const InternalMessagePtr msg) const
166 {
167 /**
168 * The group has been removed. The possible cause is that an exception occurs during the connection.
169 */
170 WIFI_LOGI("The group has been removed.");
171 p2pStateMachine.DelayMessage(msg);
172 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupOperatingState);
173 return EXECUTED;
174 }
175
ProcessCmdRemoveGroupClient(const InternalMessagePtr msg) const176 bool GroupFormedState::ProcessCmdRemoveGroupClient(const InternalMessagePtr msg) const
177 {
178 GcInfo info;
179 if (!msg->GetMessageObj(info)) {
180 return EXECUTED;
181 }
182 std::string deviceMac = info.mac;
183 WifiP2pGroupInfo currentGroup = groupManager.GetCurrentGroup();
184 for (auto client : currentGroup.GetClientDevices()) {
185 if (info.mac == client.GetDeviceAddress()) {
186 deviceMac = client.GetDeviceAddress();
187 break;
188 }
189 if (info.host == client.GetDeviceName()) {
190 deviceMac = client.GetDeviceAddress();
191 break;
192 }
193 }
194 if (WifiP2PHalInterface::GetInstance().GroupClientRemove(deviceMac)) {
195 WIFI_LOGE("p2p remove client failed.");
196 p2pStateMachine.BroadcastActionResult(P2pActionCallback::RemoveGroupClient, WIFI_OPT_FAILED);
197 } else {
198 WIFI_LOGI("p2p remove client successful.");
199 p2pStateMachine.BroadcastActionResult(P2pActionCallback::RemoveGroupClient, WIFI_OPT_SUCCESS);
200 }
201 return EXECUTED;
202 }
203
ProcessCmdRemoveGroup(const InternalMessagePtr msg) const204 bool GroupFormedState::ProcessCmdRemoveGroup(const InternalMessagePtr msg) const
205 {
206 p2pStateMachine.DelayMessage(msg);
207 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupOperatingState);
208 return EXECUTED;
209 }
210
ProcessCmdDeleteGroup(const InternalMessagePtr msg) const211 bool GroupFormedState::ProcessCmdDeleteGroup(const InternalMessagePtr msg) const
212 {
213 p2pStateMachine.DelayMessage(msg);
214 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupOperatingState);
215 return EXECUTED;
216 }
ProcessCmdDisable(const InternalMessagePtr msg) const217 bool GroupFormedState::ProcessCmdDisable(const InternalMessagePtr msg) const
218 {
219 p2pStateMachine.DelayMessage(msg);
220 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupOperatingState);
221 return EXECUTED;
222 }
223
ProcessDeviceLostEvt(const InternalMessagePtr msg) const224 bool GroupFormedState::ProcessDeviceLostEvt(const InternalMessagePtr msg) const
225 {
226 WifiP2pDevice device;
227 if (!msg->GetMessageObj(device) || !device.IsValid()) {
228 WIFI_LOGE("Device lost:Failed to obtain client information.");
229 return EXECUTED;
230 }
231
232 if (!groupManager.GetCurrentGroup().IsContainsDevice(device)) {
233 return NOT_EXECUTED;
234 }
235
236 return EXECUTED;
237 }
238
ProcessDisconnectEvt(const InternalMessagePtr msg) const239 bool GroupFormedState::ProcessDisconnectEvt(const InternalMessagePtr msg) const
240 {
241 WifiP2pDevice device;
242 if (!msg->GetMessageObj(device) || !device.IsValid()) {
243 WIFI_LOGE("Disconnect:Failed to obtain client information.");
244 return EXECUTED;
245 }
246
247 IpPool::ReleaseIp(device.GetDeviceAddress());
248 device.SetP2pDeviceStatus(P2pDeviceStatus::PDS_AVAILABLE);
249 deviceManager.UpdateDeviceStatus(device); // used for peers change event querying device infos
250 deviceManager.UpdateGroupAddress(device);
251 groupManager.RemoveCurrGroupClient(device);
252 if (WIFI_OPT_SUCCESS != p2pStateMachine.RemoveClientInfo(device.GetDeviceAddress())) {
253 WIFI_LOGE("Connect: remove client info faild");
254 }
255 auto iter = std::find(p2pStateMachine.curClientList.begin(),
256 p2pStateMachine.curClientList.end(), device.GetDeviceAddress());
257 if (iter != p2pStateMachine.curClientList.end()) {
258 p2pStateMachine.curClientList.erase(iter);
259 } else {
260 WIFI_LOGD("curClientList(%s) has been erased", device.GetDeviceAddress().c_str());
261 }
262 p2pStateMachine.BroadcastP2pPeersChanged();
263 p2pStateMachine.BroadcastP2pConnectionChanged();
264 p2pStateMachine.BroadcastP2pGcLeaveGroup(device);
265 deviceManager.RemoveDevice(device);
266 if (groupManager.IsCurrGroupClientEmpty() && !groupManager.GetCurrentGroup().IsExplicitGroup()) {
267 WIFI_LOGE("Clients empty, remove p2p group.");
268 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupOperatingState);
269 }
270 return EXECUTED;
271 }
272
ProcessConnectEvt(const InternalMessagePtr msg) const273 bool GroupFormedState::ProcessConnectEvt(const InternalMessagePtr msg) const
274 {
275 WifiP2pDevice device;
276 if (!msg->GetMessageObj(device) || !device.IsValid()) {
277 WIFI_LOGE("Connect:Failed to obtain client information.");
278 return EXECUTED;
279 }
280
281 if (WifiErrorNo::WIFI_HAL_OPT_OK !=
282 WifiP2PHalInterface::GetInstance().SetP2pGroupIdle(groupManager.GetCurrentGroup().GetInterface(), 0)) {
283 WIFI_LOGE("fail to set GO Idle time.");
284 }
285 device.SetP2pDeviceStatus(P2pDeviceStatus::PDS_CONNECTED);
286 deviceManager.UpdateDeviceStatus(device);
287 WifiP2pDevice memberPeer = deviceManager.GetDevices(device.GetDeviceAddress());
288 if (memberPeer.IsValid()) {
289 memberPeer.SetP2pDeviceStatus(P2pDeviceStatus::PDS_CONNECTED);
290 memberPeer.SetRandomDeviceAddress(device.GetRandomDeviceAddress());
291 groupManager.UpdateCurrGroupClient(memberPeer);
292 WIFI_LOGI("ProcessConnectEvt memberPeer:%{private}s %{private}s", memberPeer.GetDeviceAddress().c_str(),
293 memberPeer.GetRandomDeviceAddress().c_str());
294 p2pStateMachine.UpdatePersistentGroups();
295 } else {
296 groupManager.UpdateCurrGroupClient(device);
297 }
298 p2pStateMachine.curClientList.emplace_back(device.GetDeviceAddress());
299 p2pStateMachine.BroadcastP2pPeersChanged();
300 p2pStateMachine.BroadcastP2pConnectionChanged();
301 return EXECUTED;
302 }
303
ProcessCmdCancelConnect(const InternalMessagePtr msg) const304 bool GroupFormedState::ProcessCmdCancelConnect(const InternalMessagePtr msg) const
305 {
306 WIFI_LOGI("recv CMD: %{public}d", msg->GetMessageName());
307 p2pStateMachine.BroadcastActionResult(P2pActionCallback::P2pCancelConnect, ErrCode::WIFI_OPT_FAILED);
308 return EXECUTED;
309 }
310
ProcessCmdDiscServices(const InternalMessagePtr msg) const311 bool GroupFormedState::ProcessCmdDiscServices(const InternalMessagePtr msg) const
312 {
313 WIFI_LOGI("recv CMD: %{public}d", msg->GetMessageName());
314 WIFI_LOGD("p2p_enabled_state recv CMD_DISCOVER_SERVICES");
315
316 p2pStateMachine.CancelSupplicantSrvDiscReq();
317 std::string reqId;
318 WifiP2pServiceRequest request;
319 WifiP2pDevice device;
320 device.SetDeviceAddress(std::string("00:00:00:00:00:00"));
321 request.SetProtocolType(P2pServicerProtocolType::SERVICE_TYPE_ALL);
322 request.SetTransactionId(p2pStateMachine.serviceManager.GetTransId());
323
324 WifiErrorNo retCode =
325 WifiP2PHalInterface::GetInstance().ReqServiceDiscovery(device.GetDeviceAddress(), request.GetTlv(), reqId);
326 if (WifiErrorNo::WIFI_HAL_OPT_OK != retCode) {
327 WIFI_LOGI("Failed to schedule the P2P service discovery request.");
328 p2pStateMachine.BroadcastActionResult(P2pActionCallback::DiscoverServices, ErrCode::WIFI_OPT_FAILED);
329 return EXECUTED;
330 }
331 p2pStateMachine.serviceManager.SetQueryId(reqId);
332
333 retCode = WifiP2PHalInterface::GetInstance().P2pFind(DISC_TIMEOUT_S);
334 if (retCode != WifiErrorNo::WIFI_HAL_OPT_OK) {
335 WIFI_LOGE("call P2pFind failed, ErrorCode: %{public}d", static_cast<int>(retCode));
336 p2pStateMachine.BroadcastActionResult(P2pActionCallback::DiscoverServices, ErrCode::WIFI_OPT_FAILED);
337 return EXECUTED;
338 }
339
340 WIFI_LOGI("CMD_DISCOVER_SERVICES successful.");
341 p2pStateMachine.BroadcastActionResult(P2pActionCallback::DiscoverServices, ErrCode::WIFI_OPT_SUCCESS);
342 p2pStateMachine.BroadcastP2pDiscoveryChanged(true);
343 return EXECUTED;
344 }
345
ProcessCmdStartListen(const InternalMessagePtr msg) const346 bool GroupFormedState::ProcessCmdStartListen(const InternalMessagePtr msg) const
347 {
348 if (WifiP2PHalInterface::GetInstance().P2pFlush()) {
349 WIFI_LOGW("Unexpected results in p2p flush.");
350 }
351
352 constexpr int defaultOpClass = 81;
353 constexpr int defaultChannel = 6;
354 if (WifiP2PHalInterface::GetInstance().SetListenChannel(defaultChannel, defaultOpClass)) {
355 WIFI_LOGI("p2p set listen channel failed. channel:%{public}d, opclass:%{public}d", defaultChannel,
356 defaultOpClass);
357 p2pStateMachine.BroadcastActionResult(P2pActionCallback::StartP2pListen, WIFI_OPT_FAILED);
358 return EXECUTED;
359 }
360
361 size_t period = static_cast<size_t>(msg->GetParam1());
362 size_t interval = static_cast<size_t>(msg->GetParam2());
363 if (WifiP2PHalInterface::GetInstance().P2pConfigureListen(true, period, interval)) {
364 WIFI_LOGE("p2p configure to start listen failed.");
365 p2pStateMachine.BroadcastActionResult(P2pActionCallback::StartP2pListen, WIFI_OPT_FAILED);
366 } else {
367 WIFI_LOGI("p2p configure to start listen successful.");
368 p2pStateMachine.BroadcastActionResult(P2pActionCallback::StartP2pListen, WIFI_OPT_SUCCESS);
369 }
370 return EXECUTED;
371 }
372
ExecuteStateMsg(InternalMessagePtr msg)373 bool GroupFormedState::ExecuteStateMsg(InternalMessagePtr msg)
374 {
375 if (msg == nullptr) {
376 WIFI_LOGE("fatal error!");
377 return NOT_EXECUTED;
378 }
379 int msgName = msg->GetMessageName();
380 auto iter = mProcessFunMap.find(static_cast<P2P_STATE_MACHINE_CMD>(msgName));
381 if (iter == mProcessFunMap.end()) {
382 return NOT_EXECUTED;
383 }
384 if ((this->*(iter->second))(msg)) {
385 return EXECUTED;
386 } else {
387 return NOT_EXECUTED;
388 }
389 }
390
ProcessCmdChSwitch(const InternalMessagePtr msg) const391 bool GroupFormedState::ProcessCmdChSwitch(const InternalMessagePtr msg) const
392 {
393 WifiP2pGroupInfo group;
394 if (!msg->GetMessageObj(group)) {
395 WIFI_LOGE("Failed to obtain the group information.");
396 return EXECUTED;
397 }
398 WIFI_LOGI("p2p channel is switch");
399 int freq = group.GetFrequency();
400 WifiP2pGroupInfo currGroup = groupManager.GetCurrentGroup();
401 currGroup.SetFrequency(freq);
402 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, currGroup);
403 return EXECUTED;
404 }
405
ProcessCmdSetIpAddress(const InternalMessagePtr msg) const406 bool GroupFormedState::ProcessCmdSetIpAddress(const InternalMessagePtr msg) const
407 {
408 IpAddrInfo ipInfo;
409 if (!msg->GetMessageObj(ipInfo)) {
410 WIFI_LOGE("Failed to obtain the group information.");
411 return EXECUTED;
412 }
413 WIFI_LOGI("set ip address");
414 WifiP2pGroupInfo currGroup = groupManager.GetCurrentGroup();
415 currGroup.SetGcIpAddress(ipInfo.ip);
416 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, currGroup);
417 return EXECUTED;
418 }
419 } // namespace Wifi
420 } // namespace OHOS
421