1 /*
2  * Copyright (C) 2023 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 <map>
16 #include "wifi_event_handler.h"
17 #include "wifi_logger.h"
18 #ifdef OHOS_ARCH_LITE
19 #include <atomic>
20 #include <condition_variable>
21 #include <deque>
22 #include <memory>
23 #include <mutex>
24 #include <thread>
25 #elif WIFI_FFRT_ENABLE
26 #include "ffrt_inner.h"
27 #else
28 #include "event_handler.h"
29 #include "event_runner.h"
30 #endif
31 namespace OHOS {
32 namespace Wifi {
33 DEFINE_WIFILOG_LABEL("WifiEventHandler");
34 #ifdef OHOS_ARCH_LITE
35 class WifiEventHandler::WifiEventHandlerImpl {
36 public:
WifiEventHandlerImpl(const std::string & threadName,const Callback & timeOutFunc=nullptr)37     WifiEventHandlerImpl(const std::string &threadName, const Callback &timeOutFunc = nullptr)
38     {
39         mRunFlag = true;
40         mWorkerThread = std::thread(WifiEventHandlerImpl::Run, std::ref(*this));
41         pthread_setname_np(mWorkerThread.native_handle(), threadName.c_str());
42     }
~WifiEventHandlerImpl()43     ~WifiEventHandlerImpl()
44     {
45         mRunFlag = false;
46         mCondition.notify_one();
47         if (mWorkerThread.joinable()) {
48             mWorkerThread.join();
49         }
50     }
PostSyncTask(Callback & callback)51     bool PostSyncTask(Callback &callback)
52     {
53         WIFI_LOGE("WifiEventHandlerImpl PostSyncTask Unsupported in lite.");
54         return false;
55     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)56     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
57     {
58         if (delayTime > 0) {
59             WIFI_LOGE("WifiEventHandlerImpl PostAsyncTask with delayTime Unsupported in lite.");
60             return false;
61         }
62         WIFI_LOGD("PostAsyncTask Enter");
63         {
64             std::unique_lock<std::mutex> lock(mMutex);
65             mEventQue.push_back(callback);
66         }
67         mCondition.notify_one();
68         return true;
69     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0)70     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0)
71     {
72         WIFI_LOGE("WifiEventHandlerImpl PostAsyncTask with name Unsupported in lite.");
73         return false;
74     }
RemoveAsyncTask(const std::string & name)75     void RemoveAsyncTask(const std::string &name)
76     {
77         WIFI_LOGE("WifiEventHandlerImpl RemoveAsyncTask Unsupported in lite.");
78     }
79 private:
Run(WifiEventHandlerImpl & instance)80     static  void Run(WifiEventHandlerImpl &instance)
81     {
82         while (instance.mRunFlag) {
83             std::unique_lock<std::mutex> lock(instance.mMutex);
84             while (instance.mEventQue.empty() && instance.mRunFlag) {
85                 instance.mCondition.wait(lock);
86             }
87             if (!instance.mRunFlag) {
88                 break;
89             }
90             Callback msg = instance.mEventQue.front();
91             instance.mEventQue.pop_front();
92             lock.unlock();
93             msg();
94         }
95         return;
96     }
97     std::thread mWorkerThread;
98     std::atomic<bool> mRunFlag;
99     std::mutex mMutex;
100     std::condition_variable mCondition;
101     std::deque<Callback> mEventQue;
102 };
103 #elif WIFI_FFRT_ENABLE
104 constexpr int WIFI_THREAD_TIMEOUT_LIMIT = 30 * 1000 * 1000; // 30s
105 class WifiEventHandler::WifiEventHandlerImpl {
106 public:
WifiEventHandlerImpl(const std::string & threadName,const Callback & timeOutFunc=nullptr)107     WifiEventHandlerImpl(const std::string &threadName, const Callback &timeOutFunc = nullptr)
108     {
109         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
110         if (eventQueue != nullptr) {
111             WIFI_LOGI("WifiEventHandlerImpl already init.");
112             return;
113         }
114         if (timeOutFunc == nullptr) {
115             eventQueue = std::make_shared<ffrt::queue>(threadName.c_str());
116             WIFI_LOGI("WifiEventHandlerImpl: Create a new eventQueue, threadName:%{public}s", threadName.c_str());
117         } else {
118             eventQueue = std::make_shared<ffrt::queue>(threadName.c_str(),
119             ffrt::queue_attr().callback(timeOutFunc));
120             WIFI_LOGI("WifiEventHandlerImpl: Create a new eventQueue with callback,"
121                 "threadName:%{public}s", threadName.c_str());
122         }
123     }
124 
~WifiEventHandlerImpl()125     ~WifiEventHandlerImpl()
126     {
127         WIFI_LOGI("WifiEventHandler: ~WifiEventHandler");
128         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
129         for (auto iter = taskMap_.begin(); iter != taskMap_.end();) {
130             if (iter->second != nullptr && eventQueue != nullptr) {
131                 int32_t ret = eventQueue->cancel(iter->second);
132                 if (ret != 0) {
133                     WIFI_LOGD("~WifiEventHandler cancel failed, error code : %{public}d", ret);
134                 }
135                 iter->second = nullptr;
136             }
137             iter = taskMap_.erase(iter);
138         }
139         if (eventQueue != nullptr) {
140             eventQueue.reset();
141         }
142     }
PostSyncTask(Callback & callback)143     bool PostSyncTask(Callback &callback)
144     {
145         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
146         if (eventQueue == nullptr) {
147             WIFI_LOGE("PostSyncTask: eventQueue is nullptr!");
148             return false;
149         }
150         WIFI_LOGD("PostSyncTask Enter");
151         ffrt::task_handle handle = eventQueue->submit_h(callback);
152         if (handle == nullptr) {
153             return false;
154         }
155         eventQueue->wait(handle);
156         return true;
157     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)158     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
159     {
160         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
161         if (eventQueue == nullptr) {
162             WIFI_LOGE("PostAsyncTask: eventQueue is nullptr!");
163             return false;
164         }
165         int64_t delayTimeUs = delayTime * 1000;
166         WIFI_LOGD("PostAsyncTask Enter");
167         ffrt::task_handle handle = eventQueue->submit_h(callback, ffrt::task_attr().delay(delayTimeUs));
168         return handle != nullptr;
169     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0)170     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0)
171     {
172         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
173         if (eventQueue == nullptr) {
174             WIFI_LOGE("PostAsyncTask: eventQueue is nullptr!");
175             return false;
176         }
177         int64_t delayTimeUs = delayTime * 1000;
178         WIFI_LOGD("PostAsyncTask Enter %{public}s", name.c_str());
179         ffrt::task_handle handle = eventQueue->submit_h(
180             callback, ffrt::task_attr().name(name.c_str()).delay(delayTimeUs));
181         if (handle == nullptr) {
182             return false;
183         }
184         taskMap_[name]  = std::move(handle);
185         return true;
186     }
RemoveAsyncTask(const std::string & name)187     void RemoveAsyncTask(const std::string &name)
188     {
189         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
190         WIFI_LOGD("RemoveAsyncTask Enter %{public}s", name.c_str());
191         auto iter = taskMap_.find(name);
192         if (iter != taskMap_.end() && iter->second != nullptr && eventQueue != nullptr) {
193             int32_t ret = eventQueue->cancel(iter->second);
194             if (ret != 0) {
195                 WIFI_LOGD("RemoveAsyncTask failed, error code : %{public}d", ret);
196             }
197             taskMap_.erase(iter);
198         }
199     }
200 private:
201     std::shared_ptr<ffrt::queue> eventQueue = nullptr;
202     mutable ffrt::mutex eventQurueMutex;
203     std::map<std::string, ffrt::task_handle> taskMap_;
204 };
205 #else
206 class WifiEventHandler::WifiEventHandlerImpl {
207 public:
WifiEventHandlerImpl(const std::string & threadName,const Callback & timeOutFunc=nullptr)208     WifiEventHandlerImpl(const std::string &threadName, const Callback &timeOutFunc = nullptr)
209     {
210         eventRunner = AppExecFwk::EventRunner::Create(threadName);
211         if (eventRunner) {
212             eventHandler = std::make_shared<AppExecFwk::EventHandler>(eventRunner);
213         } else {
214             WIFI_LOGE("WifiEventHandler: Create event runner failed!");
215         }
216         WIFI_LOGI("WifiEventHandler: Create a new event handler, threadName:%{public}s", threadName.c_str());
217     }
~WifiEventHandlerImpl()218     ~WifiEventHandlerImpl()
219     {
220         WIFI_LOGI("WifiEventHandler: ~WifiEventHandler");
221         if (eventRunner) {
222             eventRunner->Stop();
223             eventRunner.reset();
224         }
225         if (eventHandler) {
226             eventHandler.reset();
227         }
228     }
PostSyncTask(Callback & callback)229     bool PostSyncTask(Callback &callback)
230     {
231         if (eventHandler == nullptr) {
232             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
233             return false;
234         }
235         return eventHandler->PostSyncTask(callback, AppExecFwk::EventHandler::Priority::HIGH);
236     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)237     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
238     {
239         if (eventHandler == nullptr) {
240             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
241             return false;
242         }
243         return eventHandler->PostTask(callback, delayTime, AppExecFwk::EventHandler::Priority::HIGH);
244     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0)245     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0)
246     {
247         if (eventHandler == nullptr) {
248             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
249             return false;
250         }
251         return eventHandler->PostTask(callback, name, delayTime, AppExecFwk::EventHandler::Priority::HIGH);
252     }
RemoveAsyncTask(const std::string & name)253     void RemoveAsyncTask(const std::string &name)
254     {
255         if (eventHandler == nullptr) {
256             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
257             return;
258         }
259         eventHandler->RemoveTask(name);
260     }
261 private:
262     std::shared_ptr<AppExecFwk::EventRunner> eventRunner = nullptr;
263     std::shared_ptr<AppExecFwk::EventHandler> eventHandler = nullptr;
264 };
265 #endif
266 
WifiEventHandler(const std::string & threadName,const Callback & timeOutFunc)267 WifiEventHandler::WifiEventHandler(const std::string &threadName, const Callback &timeOutFunc)
268     :ptr(new WifiEventHandlerImpl(threadName, timeOutFunc))
269 {}
270 
~WifiEventHandler()271 WifiEventHandler::~WifiEventHandler()
272 {
273     ptr.reset();
274 }
275 
PostSyncTask(const Callback & callback)276 bool WifiEventHandler::PostSyncTask(const Callback &callback)
277 {
278     if (ptr == nullptr) {
279         WIFI_LOGE("PostSyncTask: ptr is nullptr!");
280         return false;
281     }
282     return ptr->PostSyncTask(const_cast<Callback &>(callback));
283 }
284 
PostAsyncTask(const Callback & callback,int64_t delayTime)285 bool WifiEventHandler::PostAsyncTask(const Callback &callback, int64_t delayTime)
286 {
287     if (ptr == nullptr) {
288         WIFI_LOGE("PostAsyncTask: ptr is nullptr!");
289         return false;
290     }
291     return ptr->PostAsyncTask(const_cast<Callback &>(callback), delayTime);
292 }
293 
PostAsyncTask(const Callback & callback,const std::string & name,int64_t delayTime)294 bool WifiEventHandler::PostAsyncTask(const Callback &callback, const std::string &name, int64_t delayTime)
295 {
296     if (ptr == nullptr) {
297         WIFI_LOGE("PostAsyncTask: ptr is nullptr!");
298         return false;
299     }
300     return ptr->PostAsyncTask(const_cast<Callback &>(callback), name, delayTime);
301 }
RemoveAsyncTask(const std::string & name)302 void WifiEventHandler::RemoveAsyncTask(const std::string &name)
303 {
304     if (ptr == nullptr) {
305         WIFI_LOGE("RemoveAsyncTask: ptr is nullptr!");
306         return;
307     }
308     ptr->RemoveAsyncTask(name);
309 }
310 
311 
PostSyncTimeOutTask(const Callback & callback,uint64_t waitTime)312 bool WifiEventHandler::PostSyncTimeOutTask(const Callback &callback, uint64_t waitTime)
313 {
314 #ifdef WIFI_FFRT_ENABLE
315     ffrt::future f = ffrt::async(callback);
316     ffrt::future_status status = f.wait_for(std::chrono::milliseconds(waitTime));
317     if (status == ffrt::future_status::timeout) {
318         WIFI_LOGE("PostSyncTimeOutTask: Task timeout!");
319         return false;
320     }
321 
322     return true;
323 #else
324     std::future f = std::async(callback);
325     std::future_status status = f.wait_for(std::chrono::milliseconds(waitTime));
326     if (status == std::future_status::timeout) {
327         WIFI_LOGE("PostSyncTimeOutTask: Task timeout!");
328         return false;
329     }
330 
331     return true;
332 #endif
333 }
334 
335 
336 } // namespace Wifi
337 } // namespace OHOS