* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "handler.h"
#include <iostream>
#include <sys/time.h>
#include "wifi_log.h"
#include "wifi_config_center.h"
#include "wifi_watchdog_utils.h"
#undef LOG_TAG
#define LOG_TAG "OHWIFI_HANDLER"
namespace OHOS {
namespace Wifi {
#ifdef OHOS_ARCH_LITE
Handler::Handler() : pMyQueue(nullptr), handleThread(0), isRunning(true)
{}
#else
Handler::Handler() : pMyTaskQueue(nullptr)
{}
#endif
Handler::~Handler()
{
LOGI("Handler::~Handler");
StopHandlerThread();
return;
}
bool Handler::InitialHandler(const std::string &name)
{
#ifdef OHOS_ARCH_LITE
if (handleThread != 0) {
return true;
}
if (pMyQueue == nullptr) {
pMyQueue = std::make_unique<MessageQueue>();
}
int ret = pthread_create(&handleThread, nullptr, RunHandleThreadFunc, this);
if (ret != 0) {
LOGE("pthread_create failed.\n");
return false;
}
LOGI("pthread_create ret: %{public}d\n", ret);
pthread_setname_np(handleThread, name.c_str());
#else
if (pMyTaskQueue == nullptr) {
pMyTaskQueue = std::make_unique<WifiEventHandler>(name);
}
#endif
LOGI("InitialHandler success: %{public}s", mThreadName.c_str());
mThreadName = name;
return true;
}
void Handler::StopHandlerThread()
{
LOGI("Enter StopHandlerThread %{public}s", mThreadName.c_str());
#ifdef OHOS_ARCH_LITE
if (isRunning) {
isRunning = false;
if (pMyQueue != nullptr) {
pMyQueue->StopQueueLoop();
}
if (handleThread != 0) {
pthread_join(handleThread, nullptr);
}
}
#else
if (pMyTaskQueue != nullptr) {
pMyTaskQueue.reset();
}
#endif
LOGI("Leave StopHandlerThread %{public}s", mThreadName.c_str());
return;
}
#ifdef OHOS_ARCH_LITE
void *Handler::RunHandleThreadFunc(void *pInstance)
{
if (pInstance == nullptr) {
LOGE("pInstance is null.\n");
return nullptr;
}
LOGI("Run handler func.");
Handler *pHandler = (Handler *)pInstance;
pHandler->GetAndDistributeMessage();
return nullptr;
}
void Handler::GetAndDistributeMessage()
{
if (pMyQueue == nullptr) {
LOGE("pMyQueue is null.\n");
return;
}
while (isRunning) {
InternalMessagePtr msg = pMyQueue->GetNextMessage();
if (msg == nullptr) {
LOGE("GetNextMessage null.\n");
continue;
}
LOGD("Handler get message: %{public}d\n", msg->GetMessageName());
WifiConfigCenter::GetInstance().SetThreadStatusFlag(true);
DistributeMessage(msg);
MessageManage::GetInstance().ReclaimMsg(msg);
WifiConfigCenter::GetInstance().SetThreadStatusFlag(false);
}
return;
}
#endif
void Handler::SendMessage(InternalMessagePtr msg)
{
if (msg == nullptr) {
LOGE("%{public}s SendMessage: msg is null.", mThreadName.c_str());
return;
}
LOGD("%{public}s SendMessage msg:%{public}d", mThreadName.c_str(), msg->GetMessageName());
#ifdef OHOS_ARCH_LITE
MessageExecutedLater(msg, 0);
#else
std::function<void()> func = std::bind([this, msg]() {
msg->PrintMsg(mThreadName);
ExecuteMessage(msg);
MessageManage::GetInstance().ReclaimMsg(msg);
});
if (pMyTaskQueue != nullptr) {
pMyTaskQueue->PostAsyncTask(func, std::to_string(msg->GetMessageName()), 0);
}
#endif
return;
}
void Handler::MessageExecutedLater(InternalMessagePtr msg, int64_t delayTimeMs)
{
if (msg == nullptr) {
LOGE("%{public}s MessageExecutedLater: msg is null.", mThreadName.c_str());
return;
}
LOGD("%{public}s MessageExecutedLater msg:%{public}d %{public}" PRId64,
mThreadName.c_str(), msg->GetMessageName(), delayTimeMs);
int64_t delayTime = delayTimeMs;
if (delayTime < 0) {
delayTime = 0;
}
#ifdef OHOS_ARCH_LITE
struct timespec curTime = {0, 0};
if (clock_gettime(CLOCK_MONOTONIC, &curTime) != 0) {
LOGE("clock_gettime failed.");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
int64_t nowTime = static_cast<int64_t>(curTime.tv_sec) * USEC_1000 +
curTime.tv_nsec / (USEC_1000 * USEC_1000);
MessageExecutedAtTime(msg, nowTime + delayTime);
#else
if (pMyTaskQueue == nullptr) {
LOGE("%{public}s pMyTaskQueue is null.\n", mThreadName.c_str());
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
std::function<void()> func = std::bind([this, msg]() {
msg->PrintMsg(mThreadName);
ExecuteMessage(msg);
MessageManage::GetInstance().ReclaimMsg(msg);
});
pMyTaskQueue->PostAsyncTask(func, std::to_string(msg->GetMessageName()), delayTime);
#endif
return;
}
void Handler::MessageExecutedAtTime(InternalMessagePtr msg, int64_t execTime)
{
if (msg == nullptr) {
LOGE("%{public}s MessageExecutedAtTime: msg is null.", mThreadName.c_str());
return;
}
#ifdef OHOS_ARCH_LITE
if (pMyQueue == nullptr) {
LOGE("pMyQueue is null.\n");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
if (pMyQueue->AddMessageToQueue(msg, execTime) != true) {
LOGE("AddMessageToQueue failed.\n");
return;
}
#else
struct timespec curTime = {0, 0};
if (clock_gettime(CLOCK_MONOTONIC, &curTime) != 0) {
LOGE("clock_gettime failed.");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
int64_t nowTime = static_cast<int64_t>(curTime.tv_sec) * USEC_1000 +
curTime.tv_nsec / (USEC_1000 * USEC_1000);
MessageExecutedLater(msg, execTime - nowTime);
#endif
return;
}
void Handler::PlaceMessageTopOfQueue(InternalMessagePtr msg)
{
if (msg == nullptr) {
LOGE("%{public}s PlaceMessageTopOfQueue: msg is null.", mThreadName.c_str());
return;
}
LOGD("%{public}s PlaceMessageTopOfQueue msg: %{public}d", mThreadName.c_str(), msg->GetMessageName());
#ifdef OHOS_ARCH_LITE
if (pMyQueue == nullptr) {
LOGE("pMyQueue is null.\n");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
if (!pMyQueue->AddMessageToQueue(msg, 0)) {
LOGE("AddMessageToQueue failed.\n");
return;
}
#else
if (pMyTaskQueue == nullptr) {
LOGE("%{public}s pMyQueue is null.\n", mThreadName.c_str());
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
std::function<void()> func = std::bind([this, msg]() {
LOGD("%{public}s ExecuteMessage msg:%{public}d", mThreadName.c_str(), msg->GetMessageName());
ExecuteMessage(msg);
MessageManage::GetInstance().ReclaimMsg(msg);
});
pMyTaskQueue->PostAsyncTask(func, std::to_string(msg->GetMessageName()), 0, true);
#endif
return;
}
void Handler::DeleteMessageFromQueue(int messageName)
{
LOGD("%{public}s DeleteMessageFromQueue msg is: %{public}d", mThreadName.c_str(), messageName);
#ifdef OHOS_ARCH_LITE
if (pMyQueue == nullptr) {
LOGE("pMyQueue is null.\n");
return;
}
if (!pMyQueue->DeleteMessageFromQueue(messageName)) {
LOGE("DeleteMessageFromQueue failed.\n");
return;
}
#else
if (pMyTaskQueue == nullptr) {
LOGE("%{public}s pMyQueue is null.\n", mThreadName.c_str());
return;
}
pMyTaskQueue->RemoveAsyncTask(std::to_string(messageName));
#endif
return;
}
#ifdef OHOS_ARCH_LITE
void Handler::DistributeMessage(InternalMessagePtr msg)
{
if (msg == nullptr) {
return;
}
ExecuteMessage(msg);
return;
}
#endif
}
}