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