* Copyright (c) 2022 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 "dm_common_event_manager.h"
#include <thread>
#include "dm_constants.h"
using namespace OHOS::EventFwk;
namespace OHOS {
namespace DistributedHardware {
std::mutex DmCommonEventManager::callbackQueueMutex_;
std::mutex DmCommonEventManager::eventSubscriberMutex_;
std::condition_variable DmCommonEventManager::notEmpty_;
std::list<CommomEventCallbackNode> DmCommonEventManager::callbackQueue_;
DmCommonEventManager &DmCommonEventManager::GetInstance()
{
static DmCommonEventManager instance;
return instance;
}
DmCommonEventManager::DmCommonEventManager()
{
std::thread th(DealCallback);
th.detach();
}
DmCommonEventManager::~DmCommonEventManager()
{
std::unique_lock<std::mutex> mutexLock(eventSubscriberMutex_);
for (auto iter = dmEventSubscriber_.begin(); iter != dmEventSubscriber_.end(); iter++) {
if (!CommonEventManager::UnSubscribeCommonEvent(iter->second)) {
LOGI("Unsubscribe service event failed: %s", iter->first.c_str());
}
}
}
void DmCommonEventManager::DealCallback(void)
{
while (1) {
std::unique_lock<std::mutex> callbackQueueMutexLock(callbackQueueMutex_);
notEmpty_.wait(callbackQueueMutexLock, [] { return !callbackQueue_.empty(); });
CommomEventCallbackNode node = callbackQueue_.front();
int32_t input = node.input_;
CommomEventCallback funcPrt = node.callback_;
funcPrt(input);
callbackQueue_.pop_front();
}
}
bool DmCommonEventManager::SubscribeServiceEvent(const std::string &event, const CommomEventCallback callback)
{
LOGI("Subscribe event: %s", event.c_str());
if (dmEventSubscriber_.find(event) != dmEventSubscriber_.end() || callback == nullptr) {
LOGE("Subscribe event:%s has been exist or callback is nullptr", event.c_str());
return false;
}
MatchingSkills matchingSkills;
matchingSkills.AddEvent(event);
CommonEventSubscribeInfo subscriberInfo(matchingSkills);
std::shared_ptr<EventSubscriber> subscriber =
std::make_shared<EventSubscriber>(subscriberInfo, callback, event);
if (subscriber == nullptr) {
LOGE("subscriber is nullptr %s", event.c_str());
return false;
}
if (!CommonEventManager::SubscribeCommonEvent(subscriber)) {
LOGE("Subscribe service event failed: %s", event.c_str());
return false;
}
std::unique_lock<std::mutex> mutexLock(eventSubscriberMutex_);
dmEventSubscriber_[event] = subscriber;
return true;
}
bool DmCommonEventManager::UnsubscribeServiceEvent(const std::string &event)
{
LOGI("UnSubscribe event: %s", event.c_str());
if (dmEventSubscriber_.find(event) == dmEventSubscriber_.end()) {
LOGE("UnSubscribe event: %s not been exist", event.c_str());
return false;
}
if (!CommonEventManager::UnSubscribeCommonEvent(dmEventSubscriber_[event])) {
LOGE("Unsubscribe service event failed: %s", event.c_str());
return false;
}
std::unique_lock<std::mutex> mutexLock(eventSubscriberMutex_);
dmEventSubscriber_.erase(event);
return true;
}
void DmCommonEventManager::EventSubscriber::OnReceiveEvent(const CommonEventData &data)
{
std::string receiveEvent = data.GetWant().GetAction();
LOGI("Received event: %s", receiveEvent.c_str());
if (receiveEvent != event_) {
LOGE("Received event is error");
return;
}
int32_t userId = data.GetCode();
if (userId <= 0) {
LOGE("userId is less zero");
return;
}
std::unique_lock<std::mutex> callbackQueueMutexLock(callbackQueueMutex_);
if (callbackQueue_.size() > COMMON_CALLBACK_MAX_SIZE) {
LOGE("event callback Queue is too long");
return;
}
CommomEventCallbackNode node {userId, callback_};
callbackQueue_.push_back(node);
notEmpty_.notify_one();
}
}
}