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 #include "group_negotiation_state.h"
16 #include "mac_address.h"
17 #include "wifi_p2p_hal_interface.h"
18 #include "p2p_state_machine.h"
19 #include "wifi_logger.h"
20 #include "p2p_define.h"
21 #include "wifi_hisysevent.h"
22 #include "wifi_config_center.h"
23
24 DEFINE_WIFILOG_P2P_LABEL("GroupNegotiationState");
25
26 namespace OHOS {
27 namespace Wifi {
GroupNegotiationState(P2pStateMachine & stateMachine,WifiP2pGroupManager & groupMgr,WifiP2pDeviceManager & deviceMgr)28 GroupNegotiationState::GroupNegotiationState(
29 P2pStateMachine &stateMachine, WifiP2pGroupManager &groupMgr, WifiP2pDeviceManager &deviceMgr)
30 : State("GroupNegotiationState"), mProcessFunMap(), p2pStateMachine(stateMachine), groupManager(groupMgr), deviceManager(deviceMgr)
31 {}
GoInState()32 void GroupNegotiationState::GoInState()
33 {
34 Init();
35 WIFI_LOGI(" GoInState");
36 }
37
GoOutState()38 void GroupNegotiationState::GoOutState()
39 {
40 WIFI_LOGI(" GoOutState");
41 }
42
Init()43 void GroupNegotiationState::Init()
44 {
45 mProcessFunMap.insert(std::make_pair(
46 P2P_STATE_MACHINE_CMD::P2P_EVENT_GO_NEG_SUCCESS, &GroupNegotiationState::ProcessNegotSucessEvt));
47 mProcessFunMap.insert(std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_FORMATION_SUCCESS,
48 &GroupNegotiationState::ProcessGroupFormationSuccessEvt));
49 mProcessFunMap.insert(
50 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_STARTED, &GroupNegotiationState::ProcessGroupStartedEvt));
51 mProcessFunMap.insert(std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_FORMATION_FAILURE,
52 &GroupNegotiationState::ProcessGroupFormationFailEvt));
53 mProcessFunMap.insert(std::make_pair(
54 P2P_STATE_MACHINE_CMD::P2P_EVENT_GO_NEG_FAILURE, &GroupNegotiationState::ProcessNegotFailEvt));
55 mProcessFunMap.insert(std::make_pair(
56 P2P_STATE_MACHINE_CMD::P2P_EVENT_INVITATION_RESULT, &GroupNegotiationState::ProcessInvitationResultEvt));
57 mProcessFunMap.insert(
58 std::make_pair(P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_REMOVED, &GroupNegotiationState::ProcessGroupRemovedEvt));
59 mProcessFunMap.insert(
60 std::make_pair(P2P_STATE_MACHINE_CMD::CMD_REMOVE_GROUP, &GroupNegotiationState::ProcessCmdRemoveGroup));
61 }
62
ProcessNegotSucessEvt(InternalMessagePtr msg) const63 bool GroupNegotiationState::ProcessNegotSucessEvt(InternalMessagePtr msg) const
64 {
65 WIFI_LOGI("Negotiation success: %{public}d", msg->GetMessageName());
66 return EXECUTED;
67 }
68
ProcessGroupFormationSuccessEvt(InternalMessagePtr msg) const69 bool GroupNegotiationState::ProcessGroupFormationSuccessEvt(InternalMessagePtr msg) const
70 {
71 WIFI_LOGI("Group formation success: %{public}d", msg->GetMessageName());
72 return EXECUTED;
73 }
74
ProcessGroupStartedEvt(InternalMessagePtr msg) const75 bool GroupNegotiationState::ProcessGroupStartedEvt(InternalMessagePtr msg) const
76 {
77 WifiP2pGroupInfo group;
78 if (!msg->GetMessageObj(group)) {
79 WIFI_LOGE("Failed to obtain the group information.");
80 return EXECUTED;
81 }
82 WifiP2pLinkedInfo p2pInfo;
83 WifiConfigCenter::GetInstance().GetP2pInfo(p2pInfo);
84 p2pInfo.SetConnectState(P2pConnectedState::P2P_CONNECTED);
85 WifiConfigCenter::GetInstance().SaveP2pInfo(p2pInfo);
86 group.SetP2pGroupStatus(P2pGroupStatus::GS_STARTED);
87 group.SetCreatorUid(WifiConfigCenter::GetInstance().GetP2pCreatorUid());
88 WifiConfigCenter::GetInstance().SaveP2pCreatorUid(-1);
89 if (p2pStateMachine.CheckIsDisplayDevice(group.GetOwner().GetDeviceAddress())) {
90 group.SetPersistentFlag(true);
91 }
92 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, group);
93
94 if (groupManager.GetCurrentGroup().IsGroupOwner() &&
95 MacAddress::IsValidMac(groupManager.GetCurrentGroup().GetOwner().GetDeviceAddress().c_str())) {
96 deviceManager.GetThisDevice().SetP2pDeviceStatus(P2pDeviceStatus::PDS_CONNECTED);
97 group.SetOwner(deviceManager.GetThisDevice());
98 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, group);
99 }
100
101 if (groupManager.GetCurrentGroup().IsPersistent()) {
102 p2pStateMachine.UpdateGroupManager();
103 const WifiP2pDevice &owner = groupManager.GetCurrentGroup().GetOwner();
104 WifiP2pGroupInfo copy = groupManager.GetCurrentGroup();
105 copy.SetNetworkId(groupManager.GetGroupNetworkId(owner, groupManager.GetCurrentGroup().GetGroupName()));
106 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, copy);
107 groupManager.AddOrUpdateGroup(groupManager.GetCurrentGroup());
108 p2pStateMachine.UpdatePersistentGroups();
109 } else {
110 WifiP2pGroupInfo copy = groupManager.GetCurrentGroup();
111 copy.SetNetworkId(TEMPORARY_NET_ID);
112 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, copy);
113 }
114
115 DoDhcpInGroupStart();
116 SharedLinkManager::IncreaseSharedLink();
117 if (WifiP2PHalInterface::GetInstance().SetP2pPowerSave(group.GetInterface(), true) != WIFI_HAL_OPT_OK) {
118 WIFI_LOGE("SetP2pPowerSave() failed!");
119 }
120 p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupFormedState);
121 return EXECUTED;
122 }
123
DoDhcpInGroupStart(void) const124 void GroupNegotiationState::DoDhcpInGroupStart(void) const
125 {
126 if (groupManager.GetCurrentGroup().IsGroupOwner()) {
127 if (!p2pStateMachine.StartDhcpServer()) {
128 WIFI_LOGE("failed to startup Dhcp server.");
129 p2pStateMachine.SendMessage(static_cast<int>(P2P_STATE_MACHINE_CMD::CMD_REMOVE_GROUP));
130 }
131 if (WifiErrorNo::WIFI_HAL_OPT_OK !=
132 WifiP2PHalInterface::GetInstance().SetP2pGroupIdle(groupManager.GetCurrentGroup().GetInterface(), 0)) {
133 WIFI_LOGE("failed to set GO Idle time.");
134 }
135 } else {
136 if (WifiErrorNo::WIFI_HAL_OPT_OK !=
137 WifiP2PHalInterface::GetInstance().SetP2pGroupIdle(groupManager.GetCurrentGroup().GetInterface(), 0)) {
138 WIFI_LOGE("failed to set GC Idle time.");
139 }
140
141 /* GC start DHCP Client. */
142 if (p2pStateMachine.GetIsNeedDhcp() == DHCPTYPE::NO_DHCP) {
143 p2pStateMachine.BroadcastP2pConnectionChanged();
144 } else {
145 p2pStateMachine.StartDhcpClientInterface();
146 }
147 const WifiP2pDevice &owner = groupManager.GetCurrentGroup().GetOwner();
148 WifiP2pDevice device = deviceManager.GetDevices(owner.GetDeviceAddress());
149 if (device.IsValid()) {
150 device.SetRandomDeviceAddress(owner.GetRandomDeviceAddress());
151 device.SetP2pDeviceStatus(P2pDeviceStatus::PDS_CONNECTED);
152 WifiP2pGroupInfo copy = groupManager.GetCurrentGroup();
153 copy.SetOwner(device);
154 groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, copy);
155 WIFI_LOGI("ProcessGroupStartedEvt %{private}s %{private}s",
156 device.GetDeviceAddress().c_str(), device.GetRandomDeviceAddress().c_str());
157 deviceManager.UpdateDeviceStatus(owner.GetDeviceAddress(), P2pDeviceStatus::PDS_CONNECTED);
158 p2pStateMachine.BroadcastP2pPeersChanged();
159 } else {
160 WIFI_LOGE("fail:No GO device information is found.");
161 }
162 }
163 }
164
ProcessGroupFormationFailEvt(InternalMessagePtr msg) const165 bool GroupNegotiationState::ProcessGroupFormationFailEvt(InternalMessagePtr msg) const
166 {
167 int status = msg->GetParam1();
168 WIFI_LOGW("Group formation failure. Error code: %{public}d", status);
169 return EXECUTED;
170 }
171
ProcessNegotFailEvt(InternalMessagePtr msg) const172 bool GroupNegotiationState::ProcessNegotFailEvt(InternalMessagePtr msg) const
173 {
174 int status = msg->GetParam1();
175 WIFI_LOGE("Negotiation failure. Error code: %{public}d", status);
176 WriteP2pConnectFailedHiSysEvent(status, static_cast<int>(P2P_ERROR_RES::NEGO_FAILURE));
177 p2pStateMachine.DealGroupCreationFailed();
178 p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
179 return EXECUTED;
180 }
181
ProcessInvitationResultEvt(InternalMessagePtr msg) const182 bool GroupNegotiationState::ProcessInvitationResultEvt(InternalMessagePtr msg) const
183 {
184 P2pStatus status = static_cast<P2pStatus>(msg->GetParam1());
185 WIFI_LOGI("Invitation result is %{public}d", msg->GetParam1());
186 if (status == P2pStatus::SUCCESS) {
187 WIFI_LOGI("Invitation is succeeded.");
188 return EXECUTED;
189 }
190
191 if (P2pStatus::UNKNOWN_P2P_GROUP == status) {
192 int networkId = p2pStateMachine.savedP2pConfig.GetNetId();
193 if (networkId >= 0) {
194 groupManager.RemoveClientFromGroup(networkId, p2pStateMachine.savedP2pConfig.GetDeviceAddress());
195 }
196 p2pStateMachine.savedP2pConfig.SetNetId(-1);
197 p2pStateMachine.P2pConnectByShowingPin(p2pStateMachine.savedP2pConfig);
198 } else if (P2pStatus::INFORMATION_IS_CURRENTLY_UNAVAILABLE == status) {
199 p2pStateMachine.savedP2pConfig.SetNetId(-1);
200 p2pStateMachine.P2pConnectByShowingPin(p2pStateMachine.savedP2pConfig);
201 } else if (P2pStatus::NO_COMMON_CHANNELS == status) {
202 WIFI_LOGE("fail:There is no common channel.");
203 } else {
204 p2pStateMachine.DealGroupCreationFailed();
205 p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
206 }
207 return EXECUTED;
208 }
ProcessGroupRemovedEvt(InternalMessagePtr msg) const209 bool GroupNegotiationState::ProcessGroupRemovedEvt(InternalMessagePtr msg) const
210 {
211 /**
212 * The group has been removed. The possible cause is that an exception occurs during the connection.
213 */
214 WIFI_LOGI("Recv event: %{public}d. The group has been removed.", msg->GetMessageName());
215 p2pStateMachine.DealGroupCreationFailed();
216 p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
217 return EXECUTED;
218 }
219
ProcessCmdRemoveGroup(InternalMessagePtr msg) const220 bool GroupNegotiationState::ProcessCmdRemoveGroup(InternalMessagePtr msg) const
221 {
222 std::string ifName = p2pStateMachine.p2pDevIface;
223 if (ifName.empty()) {
224 WIFI_LOGE("invalid ifname on ProcessCmdRemoveGroup");
225 return EXECUTED;
226 }
227 p2pStateMachine.p2pDevIface = "";
228 WifiErrorNo ret = WifiP2PHalInterface::GetInstance().GroupRemove(ifName);
229 if (ret) {
230 WIFI_LOGE("P2P group (%{public}s) removal failed.", ifName.c_str());
231 p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_DISCONNECTED);
232 p2pStateMachine.BroadcastActionResult(P2pActionCallback::RemoveGroup, WIFI_OPT_FAILED);
233 } else {
234 WIFI_LOGI("The P2P group (%{public}s) is successfully removed.", ifName.c_str());
235 p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_DISCONNECTED);
236 p2pStateMachine.BroadcastActionResult(P2pActionCallback::RemoveGroup, WIFI_OPT_SUCCESS);
237 ret = WifiP2PHalInterface::GetInstance().P2pFlush();
238 if (ret != WifiErrorNo::WIFI_HAL_OPT_OK) {
239 WIFI_LOGE("call P2pFlush() failed, ErrCode: %{public}d", static_cast<int>(ret));
240 }
241 }
242 p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
243 return EXECUTED;
244 }
245
ExecuteStateMsg(InternalMessagePtr msg)246 bool GroupNegotiationState::ExecuteStateMsg(InternalMessagePtr msg)
247 {
248 if (msg == nullptr) {
249 WIFI_LOGE("fatal error!");
250 return NOT_EXECUTED;
251 }
252 int msgName = msg->GetMessageName();
253 auto iter = mProcessFunMap.find(static_cast<P2P_STATE_MACHINE_CMD>(msgName));
254 if (iter == mProcessFunMap.end()) {
255 return NOT_EXECUTED;
256 }
257 if ((this->*(iter->second))(msg)) {
258 return EXECUTED;
259 } else {
260 return NOT_EXECUTED;
261 }
262 }
263 } // namespace Wifi
264 } // namespace OHOS
265