1 /*
2  * Copyright (C) 2024 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 "wifi_connection_manager.h"
17 
18 #include "common_event_manager.h"
19 #include "common_event_support.h"
20 #include "external_deps_proxy.h"
21 #include "infc_service.h"
22 #include "loghelper.h"
23 #include "nfc_service.h"
24 #include "wifi_errcode.h"
25 #include "wifi_msg.h"
26 
27 namespace OHOS {
28 namespace NFC {
29 namespace TAG {
30 const int64_t ENABLE_WIFI_TIMEOUT = 5000; // ms
31 const int64_t CONNECT_WIFI_TIMEOUT = 5000; // ms
32 std::shared_ptr<Wifi::WifiDevice> wifiDevPtr_ {};
33 Wifi::WifiDeviceConfig* config_ {};
34 std::shared_ptr<EventFwk::CommonEventSubscriber> wifiSubscriber_ {};
35 bool g_isWaitingForWifiEnable = false;
36 bool g_isWaitingForWifiConnect = false;
37 
WifiConnectionManager()38 WifiConnectionManager::WifiConnectionManager()
39 {
40 }
41 
GetInstance()42 WifiConnectionManager& WifiConnectionManager::GetInstance()
43 {
44     static WifiConnectionManager instance;
45     return instance;
46 }
47 
Initialize(std::weak_ptr<NfcService> nfcService)48 void WifiConnectionManager::Initialize(std::weak_ptr<NfcService> nfcService)
49 {
50     std::unique_lock<std::shared_mutex> guard(mutex_);
51     DebugLog("Init: isInitialized = %{public}d", isInitialized_);
52     if (isInitialized_) {
53         return;
54     }
55     nfcService_ = nfcService;
56     isInitialized_ = true;
57 }
58 
59 class WifiConnectionManager::WifiCommonEventReceiver : public EventFwk::CommonEventSubscriber {
60 public:
61     explicit WifiCommonEventReceiver(WifiConnectionManager& nfcWifiConnMgr,
62         const EventFwk::CommonEventSubscribeInfo& subscribeInfo);
~WifiCommonEventReceiver()63     ~WifiCommonEventReceiver()
64     {
65     }
66     void OnReceiveEvent(const EventFwk::CommonEventData& data) override;
67 
68 private:
69     WifiConnectionManager& nfcWifiConnMgr_;
70 };
71 
WifiCommonEventReceiver(WifiConnectionManager & nfcWifiConnMgr,const EventFwk::CommonEventSubscribeInfo & subscribeInfo)72 WifiConnectionManager::WifiCommonEventReceiver::WifiCommonEventReceiver(WifiConnectionManager& nfcWifiConnMgr,
73     const EventFwk::CommonEventSubscribeInfo& subscribeInfo)
74     : EventFwk::CommonEventSubscriber(subscribeInfo),
75     nfcWifiConnMgr_(nfcWifiConnMgr)
76 {
77 }
78 
SubscribeWifiCommonEvents()79 void WifiConnectionManager::SubscribeWifiCommonEvents()
80 {
81     if (wifiSubscriber_ != nullptr) {
82         InfoLog("already subscribed");
83         return;
84     }
85     EventFwk::MatchingSkills matchingSkills;
86     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_POWER_STATE);
87     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_CONN_STATE);
88     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
89     wifiSubscriber_ = std::make_shared<WifiCommonEventReceiver>(*this, subscribeInfo);
90     if (wifiSubscriber_ == nullptr) {
91         ErrorLog("Create wifi subscriber failed");
92         return;
93     }
94     if (!EventFwk::CommonEventManager::SubscribeCommonEvent(wifiSubscriber_)) {
95         ErrorLog("Subscribe wifi event fail");
96     }
97 }
98 
UnsubscribeWifiCommonEvents()99 void WifiConnectionManager::UnsubscribeWifiCommonEvents()
100 {
101     if (!wifiSubscriber_) {
102         InfoLog("already unsubscribed");
103         return;
104     }
105     DebugLog("UnsubscribeWifiCommonEvents");
106     if (!EventFwk::CommonEventManager::UnSubscribeCommonEvent(wifiSubscriber_)) {
107         ErrorLog("Unsubscribe wifi event fail");
108         return;
109     }
110     wifiSubscriber_ = nullptr;
111 }
112 
SendMsgToEvtHandler(NfcCommonEvent evt,int64_t delay)113 void WifiConnectionManager::SendMsgToEvtHandler(NfcCommonEvent evt, int64_t delay)
114 {
115     if (nfcService_.expired()) {
116         ErrorLog("nfcService expired");
117         return;
118     }
119     if (nfcService_.lock()->eventHandler_ == nullptr) {
120         ErrorLog("event handler is null");
121         return;
122     }
123     DebugLog("SendMsgToEvtHandler: event:%{public}d, delay:%{public}ld", evt, delay);
124     nfcService_.lock()->eventHandler_->SendEvent(static_cast<uint32_t>(evt), delay);
125 }
126 
RemoveMsgFromEvtHandler(NfcCommonEvent evt)127 void WifiConnectionManager::RemoveMsgFromEvtHandler(NfcCommonEvent evt)
128 {
129     if (nfcService_.expired()) {
130         ErrorLog("nfcService expired");
131         return;
132     }
133     if (nfcService_.lock()->eventHandler_ == nullptr) {
134         ErrorLog("event handler is null");
135         return;
136     }
137     DebugLog("RemoveMsgFromEvtHandler: event:%{public}d", evt);
138     nfcService_.lock()->eventHandler_->RemoveEvent(static_cast<uint32_t>(evt), static_cast<int64_t>(0));
139 }
140 
GetWifiDevPtr()141 std::shared_ptr<Wifi::WifiDevice> WifiConnectionManager::GetWifiDevPtr()
142 {
143     if (wifiDevPtr_ == nullptr) {
144         wifiDevPtr_ = Wifi::WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
145     }
146     return wifiDevPtr_;
147 }
148 
OnFinish()149 void WifiConnectionManager::OnFinish()
150 {
151     DebugLog("OnFinish");
152     g_isWaitingForWifiEnable = false;
153     g_isWaitingForWifiConnect = false;
154     delete config_;
155     config_ = nullptr;
156     RemoveMsgFromEvtHandler(NfcCommonEvent::MSG_WIFI_ENABLE_TIMEOUT);
157     RemoveMsgFromEvtHandler(NfcCommonEvent::MSG_WIFI_CONNECT_TIMEOUT);
158     UnsubscribeWifiCommonEvents();
159 }
160 
HandleWifiEnableFailed()161 void WifiConnectionManager::HandleWifiEnableFailed()
162 {
163     std::unique_lock<std::shared_mutex> guard(mutex_);
164     ErrorLog("Wifi Enable Failed");
165     OnFinish();
166 }
167 
HandleWifiConnectFailed()168 void WifiConnectionManager::HandleWifiConnectFailed()
169 {
170     std::unique_lock<std::shared_mutex> guard(mutex_);
171     ErrorLog("Wifi Connect Failed");
172     OnFinish();
173 }
174 
IsWifiEnabled()175 __attribute__((no_sanitize("cfi"))) bool WifiConnectionManager::IsWifiEnabled()
176 {
177     if (GetWifiDevPtr() == nullptr) {
178         ErrorLog("wifi dev is null");
179         return false;
180     }
181     bool isEnabled = false;
182     ErrCode ret = wifiDevPtr_->IsWifiActive(isEnabled);
183     if (ret != Wifi::WIFI_OPT_SUCCESS) {
184         ErrorLog("get wifi active status failed ret = %{public}d", ret);
185         return false;
186     }
187     InfoLog("get wifi active status = %{public}d", isEnabled);
188     return isEnabled;
189 }
190 
HandleEnableWifi()191 __attribute__((no_sanitize("cfi"))) bool WifiConnectionManager::HandleEnableWifi()
192 {
193     if (GetWifiDevPtr() == nullptr) {
194         ErrorLog("wifi dev is null");
195         return false;
196     }
197     ErrCode ret = wifiDevPtr_->EnableWifi();
198     if (ret != Wifi::WIFI_OPT_SUCCESS) {
199         ErrorLog("enable wifi failed ret = %{public}d", ret);
200         return false;
201     }
202     g_isWaitingForWifiEnable = true;
203     SendMsgToEvtHandler(NfcCommonEvent::MSG_WIFI_ENABLE_TIMEOUT, ENABLE_WIFI_TIMEOUT);
204     return true;
205 }
206 
IsSameSsid()207 __attribute__((no_sanitize("cfi"))) bool WifiConnectionManager::IsSameSsid()
208 {
209     if (GetWifiDevPtr() == nullptr) {
210         ErrorLog("wifi dev is null");
211         return false;
212     }
213     if (config_ == nullptr) {
214         ErrorLog("config_ is null");
215         return false;
216     }
217     Wifi::WifiLinkedInfo info;
218     ErrCode ret = wifiDevPtr_->GetLinkedInfo(info);
219     if (ret != Wifi::WIFI_OPT_SUCCESS) {
220         ErrorLog("get linked info failed ret = %{public}d", ret);
221         return false;
222     }
223     DebugLog("current ssid: %{private}s, target ssid: %{private}s", info.ssid.c_str(), config_->ssid.c_str());
224     if (info.ssid.compare(config_->ssid.c_str()) == 0) {
225         return true;
226     }
227     return false;
228 }
229 
TryConnectWifi(std::shared_ptr<WifiData> data)230 void WifiConnectionManager::TryConnectWifi(std::shared_ptr<WifiData> data)
231 {
232     std::unique_lock<std::shared_mutex> guard(mutex_);
233     if (!data || !data->isValid_) {
234         ErrorLog("data invalid");
235         return;
236     }
237     if (!data->config_) {
238         ErrorLog("config is null");
239         return;
240     }
241     RemoveMsgFromEvtHandler(NfcCommonEvent::MSG_WIFI_ENABLE_TIMEOUT);
242     RemoveMsgFromEvtHandler(NfcCommonEvent::MSG_WIFI_CONNECT_TIMEOUT);
243     config_ = data->config_;
244     InfoLog("TryConnectWifi: Publish notification ssid: %{private}s", config_->ssid.c_str());
245     ExternalDepsProxy::GetInstance().PublishNfcNotification(NFC_WIFI_NOTIFICATION_ID, config_->ssid, 0);
246 }
247 
HandleConnectWifi()248 __attribute__((no_sanitize("cfi"))) bool WifiConnectionManager::HandleConnectWifi()
249 {
250     if (IsSameSsid()) {
251         InfoLog("already connected to target");
252         OnFinish();
253         return true;
254     }
255 
256     InfoLog("HandleConnectWifi");
257     if (GetWifiDevPtr() == nullptr) {
258         ErrorLog("wifi dev is null");
259         OnFinish();
260         return false;
261     }
262     if (config_ == nullptr) {
263         ErrorLog("config_ is null");
264         OnFinish();
265         return false;
266     }
267     // NDEF msg does not include hiddenSSID info, set true to connect all type WiFi.
268     config_->hiddenSSID = true;
269     ErrCode err = wifiDevPtr_->ConnectToDevice(*(config_));
270     InfoLog("ConnectToDevice err: %{public}d", err);
271     if (err != Wifi::WIFI_OPT_SUCCESS) {
272         ErrorLog("ConnectToDevice failed err: %{public}d", err);
273         OnFinish();
274         return false;
275     }
276     SendMsgToEvtHandler(NfcCommonEvent::MSG_WIFI_CONNECT_TIMEOUT, CONNECT_WIFI_TIMEOUT);
277     g_isWaitingForWifiConnect = true;
278     return true;
279 }
280 
OnWifiNtfClicked()281 void WifiConnectionManager::OnWifiNtfClicked()
282 {
283     InfoLog("OnWifiNtfClicked");
284     std::unique_lock<std::shared_mutex> guard(mutex_);
285     SubscribeWifiCommonEvents();
286     if (IsWifiEnabled()) {
287         HandleConnectWifi();
288     } else if (!HandleEnableWifi()) {
289         OnFinish();
290     }
291 }
292 
OnWifiEnabled()293 void WifiConnectionManager::OnWifiEnabled()
294 {
295     DebugLog("OnWifiEnabled");
296     std::unique_lock<std::shared_mutex> guard(mutex_);
297     if (!g_isWaitingForWifiEnable) {
298         ErrorLog("not waiting for wifi enable, exit");
299         return;
300     }
301     RemoveMsgFromEvtHandler(NfcCommonEvent::MSG_WIFI_ENABLE_TIMEOUT);
302     g_isWaitingForWifiEnable = false;
303     HandleConnectWifi();
304 }
305 
OnWifiConnected()306 void WifiConnectionManager::OnWifiConnected()
307 {
308     DebugLog("OnWifiConnected");
309     std::unique_lock<std::shared_mutex> guard(mutex_);
310     if (!g_isWaitingForWifiConnect) {
311         ErrorLog("not waiting for wifi connect, exit");
312         return;
313     }
314     if (!IsSameSsid()) {
315         OnFinish();
316     } else {
317         InfoLog("connected to target config");
318         OnFinish();
319     }
320 }
321 
OnReceiveEvent(const EventFwk::CommonEventData & data)322 void WifiConnectionManager::WifiCommonEventReceiver::OnReceiveEvent(const EventFwk::CommonEventData& data)
323 {
324     std::string action = data.GetWant().GetAction();
325     if (action.empty()) {
326         ErrorLog("action is empty");
327         return;
328     }
329     InfoLog("OnReceiveEvent: action: %{public}s, code: %{public}d", action.c_str(), data.GetCode());
330     if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_POWER_STATE) == 0) {
331         if (data.GetCode() != static_cast<int32_t>(Wifi::WifiState::ENABLED)) {
332             return;
333         }
334         std::unique_lock<std::shared_mutex> guard(nfcWifiConnMgr_.mutex_);
335         nfcWifiConnMgr_.SendMsgToEvtHandler(NfcCommonEvent::MSG_WIFI_ENABLED, 0);
336     } else if (action.compare(EventFwk::CommonEventSupport::COMMON_EVENT_WIFI_CONN_STATE) == 0) {
337         if (data.GetCode() != static_cast<int32_t>(Wifi::ConnState::CONNECTED)) {
338             return;
339         }
340         std::unique_lock<std::shared_mutex> guard(nfcWifiConnMgr_.mutex_);
341         nfcWifiConnMgr_.SendMsgToEvtHandler(NfcCommonEvent::MSG_WIFI_CONNECTED, 0);
342     }
343 }
344 } // namespace TAG
345 } // namespace NFC
346 } // namespace OHOS
347