• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,bool isHighPriority=false)70     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0, bool isHighPriority = false)
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     }
HasAsyncTask(const std::string & name,bool & hasTask)79     int HasAsyncTask(const std::string &name, bool &hasTask)
80     {
81         WIFI_LOGE("WifiEventHandlerImpl HasAsyncTask Unsupported in lite.");
82         return -1;
83     }
84 private:
Run(WifiEventHandlerImpl & instance)85     static  void Run(WifiEventHandlerImpl &instance)
86     {
87         while (instance.mRunFlag) {
88             std::unique_lock<std::mutex> lock(instance.mMutex);
89             while (instance.mEventQue.empty() && instance.mRunFlag) {
90                 instance.mCondition.wait(lock);
91             }
92             if (!instance.mRunFlag) {
93                 break;
94             }
95             Callback msg = instance.mEventQue.front();
96             instance.mEventQue.pop_front();
97             lock.unlock();
98             msg();
99         }
100         return;
101     }
102     std::thread mWorkerThread;
103     std::atomic<bool> mRunFlag;
104     std::mutex mMutex;
105     std::condition_variable mCondition;
106     std::deque<Callback> mEventQue;
107 };
108 #elif WIFI_FFRT_ENABLE
109 constexpr int WIFI_THREAD_TIMEOUT_LIMIT = 30 * 1000 * 1000; // 30s
110 constexpr int WIFI_THREAD_MAX_CONCURRENCY = 1;
TransferQueuePtr(std::shared_ptr<ffrt::queue> queue)111 inline ffrt_queue_t* TransferQueuePtr(std::shared_ptr<ffrt::queue> queue)
112 {
113     if (queue) {
114         return reinterpret_cast<ffrt_queue_t*>(queue.get());
115     }
116     return nullptr;
117 }
118 class WifiEventHandler::WifiEventHandlerImpl {
119 public:
WifiEventHandlerImpl(const std::string & threadName,const Callback & timeOutFunc=nullptr)120     WifiEventHandlerImpl(const std::string &threadName, const Callback &timeOutFunc = nullptr)
121     {
122         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
123         if (eventQueue != nullptr) {
124             WIFI_LOGI("WifiEventHandlerImpl already init.");
125             return;
126         }
127         if (timeOutFunc == nullptr) {
128             eventQueue = std::make_shared<ffrt::queue>(ffrt::queue_concurrent, threadName.c_str(),
129                 ffrt::queue_attr().max_concurrency(WIFI_THREAD_MAX_CONCURRENCY));
130             WIFI_LOGI("WifiEventHandlerImpl: Create a new eventQueue, threadName:%{public}s", threadName.c_str());
131         } else {
132             eventQueue = std::make_shared<ffrt::queue>(ffrt::queue_concurrent, threadName.c_str(),
133             ffrt::queue_attr().callback(timeOutFunc).max_concurrency(WIFI_THREAD_MAX_CONCURRENCY));
134             WIFI_LOGI("WifiEventHandlerImpl: Create a new eventQueue with callback,"
135                 "threadName:%{public}s", threadName.c_str());
136         }
137     }
138 
~WifiEventHandlerImpl()139     ~WifiEventHandlerImpl()
140     {
141         WIFI_LOGI("WifiEventHandler: ~WifiEventHandler");
142         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
143         ffrt_queue_t* queue = TransferQueuePtr(eventQueue);
144         if (queue == nullptr) {
145             WIFI_LOGE("~WifiEventHandler is unavailable.");
146             return;
147         }
148         ffrt_queue_cancel_all(*queue);
149         if (eventQueue != nullptr) {
150             eventQueue.reset();
151         }
152     }
153 
PostSyncTask(Callback & callback)154     bool PostSyncTask(Callback &callback)
155     {
156         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
157         if (eventQueue == nullptr) {
158             WIFI_LOGE("PostSyncTask: eventQueue is nullptr!");
159             return false;
160         }
161         WIFI_LOGD("PostSyncTask Enter");
162         ffrt::task_handle handle = eventQueue->submit_h(callback);
163         if (handle == nullptr) {
164             return false;
165         }
166         eventQueue->wait(handle);
167         return true;
168     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)169     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
170     {
171         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
172         if (eventQueue == nullptr) {
173             WIFI_LOGE("PostAsyncTask: eventQueue is nullptr!");
174             return false;
175         }
176         int64_t delayTimeUs = delayTime * 1000;
177         WIFI_LOGD("PostAsyncTask Enter");
178         ffrt::task_handle handle = eventQueue->submit_h(callback, ffrt::task_attr().delay(delayTimeUs));
179         return handle != nullptr;
180     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0,bool isHighPriority=false)181     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0, bool isHighPriority = false)
182     {
183         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
184         if (eventQueue == nullptr) {
185             WIFI_LOGE("PostAsyncTask: eventQueue is nullptr!");
186             return false;
187         }
188         int64_t delayTimeUs = delayTime * 1000;
189         WIFI_LOGD("PostAsyncTask Enter %{public}s", name.c_str());
190         ffrt::task_handle handle = nullptr;
191         if (isHighPriority) {
192             handle = eventQueue->submit_h(callback,
193                 ffrt::task_attr().name(name.c_str()).delay(delayTimeUs).priority(ffrt_queue_priority_immediate));
194         } else {
195             handle = eventQueue->submit_h(callback, ffrt::task_attr().name(name.c_str()).delay(delayTimeUs));
196         }
197         if (handle == nullptr) {
198             return false;
199         }
200         return true;
201     }
RemoveAsyncTask(const std::string & name)202     void RemoveAsyncTask(const std::string &name)
203     {
204         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
205         WIFI_LOGD("RemoveAsyncTask Enter %{public}s", name.c_str());
206         ffrt_queue_t* queue = TransferQueuePtr(eventQueue);
207         if (queue == nullptr) {
208             WIFI_LOGE("RemoveAsyncTask is unavailable.");
209             return;
210         }
211         int ret = ffrt_queue_cancel_by_name(*queue, name.c_str());
212         if (ret != 0) {
213             WIFI_LOGD("RemoveAsyncTask failed.");
214         }
215     }
HasAsyncTask(const std::string & name,bool & hasTask)216     int HasAsyncTask(const std::string &name, bool &hasTask)
217     {
218         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
219         ffrt_queue_t* queue = TransferQueuePtr(eventQueue);
220         if (queue == nullptr) {
221             WIFI_LOGE("HasAsyncTask is unavailable.");
222             return -1;
223         }
224         bool result = ffrt_queue_has_task(*queue, name.c_str());
225         WIFI_LOGD("HasAsyncTask Enter %{public}s %{public}d", name.c_str(), static_cast<int>(result));
226         hasTask = result;
227         return 0;
228     }
229 private:
230     std::shared_ptr<ffrt::queue> eventQueue = nullptr;
231     mutable ffrt::mutex eventQurueMutex;
232 };
233 #else
234 class WifiEventHandler::WifiEventHandlerImpl {
235 public:
WifiEventHandlerImpl(const std::string & threadName,const Callback & timeOutFunc=nullptr)236     WifiEventHandlerImpl(const std::string &threadName, const Callback &timeOutFunc = nullptr)
237     {
238         eventRunner = AppExecFwk::EventRunner::Create(threadName);
239         if (eventRunner) {
240             eventHandler = std::make_shared<AppExecFwk::EventHandler>(eventRunner);
241         } else {
242             WIFI_LOGE("WifiEventHandler: Create event runner failed!");
243         }
244         WIFI_LOGI("WifiEventHandler: Create a new event handler, threadName:%{public}s", threadName.c_str());
245     }
~WifiEventHandlerImpl()246     ~WifiEventHandlerImpl()
247     {
248         WIFI_LOGI("WifiEventHandler: ~WifiEventHandler");
249         if (eventRunner) {
250             eventRunner->Stop();
251             eventRunner.reset();
252         }
253         if (eventHandler) {
254             eventHandler.reset();
255         }
256     }
PostSyncTask(Callback & callback)257     bool PostSyncTask(Callback &callback)
258     {
259         if (eventHandler == nullptr) {
260             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
261             return false;
262         }
263         return eventHandler->PostSyncTask(callback, AppExecFwk::EventHandler::Priority::HIGH);
264     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)265     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
266     {
267         if (eventHandler == nullptr) {
268             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
269             return false;
270         }
271         return eventHandler->PostTask(callback, delayTime, AppExecFwk::EventHandler::Priority::HIGH);
272     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0,bool isHighPriority=false)273     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0, bool isHighPriority = false)
274     {
275         if (eventHandler == nullptr) {
276             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
277             return false;
278         }
279         if (isHighPriority) {
280             return eventHandler->PostTask(callback, name, delayTime, AppExecFwk::EventHandler::Priority::IMMEDIATE);
281         }
282         return eventHandler->PostTask(callback, name, delayTime, AppExecFwk::EventHandler::Priority::HIGH);
283     }
RemoveAsyncTask(const std::string & name)284     void RemoveAsyncTask(const std::string &name)
285     {
286         if (eventHandler == nullptr) {
287             WIFI_LOGE("PostSyncTask: eventHandler is nullptr!");
288             return;
289         }
290         eventHandler->RemoveTask(name);
291     }
HasAsyncTask(const std::string & name,bool & hasTask)292     int HasAsyncTask(const std::string &name, bool &hasTask)
293     {
294         WIFI_LOGE("WifiEventHandlerImpl HasAsyncTask Unsupported in this mode.");
295         return -1;
296     }
297 private:
298     std::shared_ptr<AppExecFwk::EventRunner> eventRunner = nullptr;
299     std::shared_ptr<AppExecFwk::EventHandler> eventHandler = nullptr;
300 };
301 #endif
302 
WifiEventHandler(const std::string & threadName,const Callback & timeOutFunc)303 WifiEventHandler::WifiEventHandler(const std::string &threadName, const Callback &timeOutFunc)
304     :ptr(new WifiEventHandlerImpl(threadName, timeOutFunc))
305 {}
306 
~WifiEventHandler()307 WifiEventHandler::~WifiEventHandler()
308 {
309     ptr.reset();
310 }
311 
PostSyncTask(const Callback & callback)312 bool WifiEventHandler::PostSyncTask(const Callback &callback)
313 {
314     if (ptr == nullptr) {
315         WIFI_LOGE("PostSyncTask: ptr is nullptr!");
316         return false;
317     }
318     return ptr->PostSyncTask(const_cast<Callback &>(callback));
319 }
320 
PostAsyncTask(const Callback & callback,int64_t delayTime)321 bool WifiEventHandler::PostAsyncTask(const Callback &callback, int64_t delayTime)
322 {
323     if (ptr == nullptr) {
324         WIFI_LOGE("PostAsyncTask: ptr is nullptr!");
325         return false;
326     }
327     return ptr->PostAsyncTask(const_cast<Callback &>(callback), delayTime);
328 }
329 
PostAsyncTask(const Callback & callback,const std::string & name,int64_t delayTime,bool isHighPriority)330 bool WifiEventHandler::PostAsyncTask(const Callback &callback, const std::string &name,
331     int64_t delayTime, bool isHighPriority)
332 {
333     if (ptr == nullptr) {
334         WIFI_LOGE("PostAsyncTask: ptr is nullptr!");
335         return false;
336     }
337     return ptr->PostAsyncTask(const_cast<Callback &>(callback), name, delayTime, isHighPriority);
338 }
RemoveAsyncTask(const std::string & name)339 void WifiEventHandler::RemoveAsyncTask(const std::string &name)
340 {
341     if (ptr == nullptr) {
342         WIFI_LOGE("RemoveAsyncTask: ptr is nullptr!");
343         return;
344     }
345     ptr->RemoveAsyncTask(name);
346 }
347 
HasAsyncTask(const std::string & name,bool & hasTask)348 int WifiEventHandler::HasAsyncTask(const std::string &name, bool &hasTask)
349 {
350     if (ptr == nullptr) {
351         WIFI_LOGE("HasAsyncTask: ptr is nullptr!");
352         return -1;
353     }
354     return ptr->HasAsyncTask(name, hasTask);
355 }
356 
PostSyncTimeOutTask(const Callback & callback,uint64_t waitTime)357 bool WifiEventHandler::PostSyncTimeOutTask(const Callback &callback, uint64_t waitTime)
358 {
359 #ifdef WIFI_FFRT_ENABLE
360     ffrt::future f = ffrt::async(callback);
361     ffrt::future_status status = f.wait_for(std::chrono::milliseconds(waitTime));
362     if (status == ffrt::future_status::timeout) {
363         WIFI_LOGE("PostSyncTimeOutTask: Task timeout!");
364         return false;
365     }
366 
367     return true;
368 #else
369     std::future f = std::async(callback);
370     std::future_status status = f.wait_for(std::chrono::milliseconds(waitTime));
371     if (status == std::future_status::timeout) {
372         WIFI_LOGE("PostSyncTimeOutTask: Task timeout!");
373         return false;
374     }
375 
376     return true;
377 #endif
378 }
379 
380 
381 } // namespace Wifi
382 } // namespace OHOS