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