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