// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "service-evtmgr/BatteryMessages.hpp" #include "service-evtmgr/EVMessages.hpp" #include "service-evtmgr/KbdMessage.hpp" #include "service-evtmgr/ScreenLightControlMessage.hpp" #include "service-evtmgr/Constants.hpp" #include "service-evtmgr/EventManager.hpp" #include "service-evtmgr/WorkerEvent.hpp" #include "battery-level-check/BatteryLevelCheck.hpp" #include "screen-light-control/ScreenLightControl.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include EventManager::EventManager(const std::string &name) : sys::Service(name), screenLightControl(std::make_unique(this)) { LOG_INFO("[%s] Initializing", name.c_str()); alarmTimestamp = 0; alarmID = 0; bus.channels.push_back(sys::BusChannel::ServiceDBNotifications); } EventManager::~EventManager() { if (EventWorker != nullptr) { EventWorker->close(); } } // those static functions and variables will be replaced by Settings API static std::string tzSet; static void setSettingsTimeZone(const std::string &timeZone) { tzSet = timeZone; } std::string getSettingsTimeZone() { return tzSet; } // Invoked upon receiving data message sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) { bool handled = false; if (auto msg = dynamic_cast(resp)) { auto event = std::make_unique(msg->response); auto message = std::make_shared(std::move(event)); bus.sendUnicast(message, service::name::service_desktop); handled = true; } if (msgl->messageType == MessageType::DBServiceNotification) { auto *msg = dynamic_cast(msgl); if (msg != nullptr) { if (msg->interface == db::Interface::Name::Alarms) { alarmDBEmpty = false; alarmIsValid = false; handled = true; } } } else if (msgl->messageType == MessageType::EVM_GPIO) { LOG_DEBUG("EVM_GPIO msg"); } else if (msgl->messageType == MessageType::KBDKeyEvent && (msgl->sender == this->GetName() || msgl->sender == service::name::service_desktop)) { auto *msg = dynamic_cast(msgl); assert(msg); auto message = std::make_shared(); message->key = msg->key; if (message->key.state == RawKey::State::Pressed && message->key.key_code == bsp::KeyCodes::FnRight) { // and state == ShutDown bus.sendUnicast(message, service::name::system_manager); } // send key to focused application if (!targetApplication.empty()) { bus.sendUnicast(message, targetApplication); } // notify application manager to prevent screen locking app::manager::Controller::preventBlockingDevice(this); handled = true; } else if (msgl->messageType == MessageType::EVMFocusApplication) { auto *msg = static_cast(msgl); if (msg->sender == "ApplicationManager") { targetApplication = msg->getApplication(); handled = true; LOG_INFO("Switching focus to %s", targetApplication.c_str()); } } else if (msgl->messageType == MessageType::EVMBatteryLevel && msgl->sender == this->GetName()) { auto *msg = static_cast(msgl); auto message = std::make_shared(msg->levelPercents, msg->fullyCharged); if (!targetApplication.empty()) { bus.sendUnicast(message, targetApplication); } handled = true; } else if (msgl->messageType == MessageType::EVMChargerPlugged && msgl->sender == this->GetName()) { auto *msg = static_cast(msgl); auto message = std::make_shared(); message->plugged = msg->plugged; if (!message->plugged) { bus.sendUnicast(message, service::name::system_manager); } if (!targetApplication.empty()) { bus.sendUnicast(message, targetApplication); } handled = true; } else if (msgl->messageType == MessageType::EVMMinuteUpdated && msgl->sender == this->GetName()) { HandleAlarmTrigger(msgl); handled = true; } else if (auto msg = dynamic_cast(msgl); msg /*&& msgl->sender == this->GetName()*/) { AudioServiceAPI::SendEvent(this, msg->getEvent()); handled = true; } else if (!targetApplication.empty() && dynamic_cast(msgl) != nullptr) { bus.sendUnicast(std::make_shared(), targetApplication); } else if (msgl->messageType == MessageType::EVMGetBoard) { using namespace bsp; auto msg = std::make_shared(true); auto board = magnetometer::GetBoard(); msg->board = board; LOG_INFO("Board discovered: %s", c_str(board)); return msg; } else if (msgl->messageType == MessageType::EVMModemStatus) { auto msg = dynamic_cast(msgl); if (msg != nullptr) { auto message = std::make_shared(MessageType::EVMModemStatus); message->state = msg->state; bus.sendUnicast(message, "ServiceCellular"); } handled = true; } else if (msgl->messageType == MessageType::EVMTorchStateMessage) { auto msg = dynamic_cast(msgl); if (msg != nullptr) { auto message = std::make_shared(msg->action); switch (msg->action) { case bsp::torch::Action::getState: std::tie(message->success, message->state) = bsp::torch::getState(); message->colourTemp = bsp::torch::getColorTemp(); break; case bsp::torch::Action::setState: message->success = bsp::torch::turn(msg->state, msg->colourTemp); break; case bsp::torch::Action::toggle: message->success = bsp::torch::toggle(); break; } return message; } } else if (msgl->messageType == MessageType::CellularTimeUpdated) { auto msg = dynamic_cast(msgl); if (msg != nullptr) { if (auto time = msg->getTime(); time) { LOG_INFO("RTC set by network time."); bsp::rtc_SetDateTime(&time.value()); } if (auto timeZoneOffset = msg->getTimeZoneOffset(); timeZoneOffset) { setSettingsTimeZone(msg->getTimeZoneString().value()); utils::time::Time::setTimeZoneOffset(msg->getTimeZoneOffset().value()); } auto notification = std::make_shared(MessageType::EVMTimeUpdated); bus.sendMulticast(notification, sys::BusChannel::ServiceEvtmgrNotifications); } } else if (msgl->messageType == MessageType::EVMRingIndicator) { auto msg = std::make_shared(sys::CpuFrequencyMessage::Action::Increase); bus.sendUnicast(msg, service::name::system_manager); } if (handled) { return std::make_shared(); } else { return std::make_shared(sys::ReturnCodes::Unresolved); } } // Invoked during initialization sys::ReturnCodes EventManager::InitHandler() { connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) { using namespace sdesktop::developerMode; auto req = static_cast(msg); if (typeid(*req->event.get()) == typeid(AppFocusChangeEvent)) { auto event = std::make_unique(targetApplication); auto message = std::make_shared(std::move(event)); bus.sendUnicast(message, service::name::service_desktop); } return std::make_shared(); }); connect(app::AppInputEventMessage(gui::InputEvent(RawKey())), [&](sys::Message *msgl) { auto msg = static_cast(msgl); assert(msg); auto message = std::make_shared(msg->getEvent()); if (!targetApplication.empty()) { bus.sendUnicast(std::move(message), targetApplication); } return std::make_shared(); }); connect(sevm::KeypadBacklightMessage(bsp::keypad_backlight::Action::turnOff), [&](sys::Message *msgl) { auto request = static_cast(msgl); auto response = std::make_shared(); response->success = processKeypadBacklightRequest(request->action); return response; }); connect(sevm::BatterySetCriticalLevel(0), [&](sys::Message *msgl) { auto request = static_cast(msgl); battery_level_check::setBatteryCriticalLevel(request->criticalLevel); return std::make_shared(); }); connect(sevm::BatteryLevelCriticalCheckMessage(), [&](sys::Message *msgl) { EventWorker->checkBatteryLevelCritical(); return std::make_shared(); }); connect(sevm::ScreenLightControlMessage(), [&](sys::Message *msgl) { auto *m = dynamic_cast(msgl); screenLightControl->processRequest(m->action, m->parameters); return std::make_shared(); }); connect(sevm::ScreenLightControlRequestParameters(), [&](sys::Message *msgl) { screen_light_control::Parameters params = {screenLightControl->getBrightnessValue()}; auto msg = std::make_shared( screenLightControl->getLightState(), screenLightControl->getAutoModeState(), params); return msg; }); // initialize keyboard worker EventWorker = std::make_unique(this); // create queues for worker // keyboard irq queue sys::WorkerQueueInfo qIrq = {"qIrq", sizeof(uint8_t), 10}; // headset irq queue sys::WorkerQueueInfo qHeadset = {"qHeadset", sizeof(uint8_t), 10}; // battery manager queue sys::WorkerQueueInfo qBattery = {"qBattery", sizeof(uint8_t), 10}; // RTC irq queue sys::WorkerQueueInfo qRTC = {"qRTC", sizeof(uint8_t), 20}; // sim tray queue sys::WorkerQueueInfo qSIM = {"qSIM", sizeof(uint8_t), 5}; // magnetometer queue sys::WorkerQueueInfo qMagnetometer = {"qMagnetometer", sizeof(uint8_t), 5}; // torch driver queue sys::WorkerQueueInfo qTorch = {"qTorch", sizeof(uint8_t), 5}; // light sensor queue sys::WorkerQueueInfo qLightSensor = {"qLightSensor", sizeof(uint8_t), 5}; // charger detector queue sys::WorkerQueueInfo qChargerDetect = {"qChargerDetect", sizeof(uint8_t), 5}; std::list list; list.push_back(qIrq); list.push_back(qHeadset); list.push_back(qBattery); list.push_back(qRTC); list.push_back(qSIM); list.push_back(qMagnetometer); list.push_back(qTorch); list.push_back(qLightSensor); list.push_back(qChargerDetect); EventWorker->init(list); EventWorker->run(); return sys::ReturnCodes::Success; } sys::ReturnCodes EventManager::DeinitHandler() { EventWorker->close(); EventWorker.reset(); EventWorker = nullptr; return sys::ReturnCodes::Success; } sys::ReturnCodes EventManager::SwitchPowerModeHandler(const sys::ServicePowerMode mode) { LOG_FATAL("[ServiceEvtMgr] PowerModeHandler: %s", c_str(mode)); switch (mode) { case sys::ServicePowerMode ::Active: break; case sys::ServicePowerMode ::SuspendToRAM: case sys::ServicePowerMode ::SuspendToNVM: break; } return sys::ReturnCodes::Success; } bool EventManager::messageSetApplication(sys::Service *sender, const std::string &applicationName) { auto msg = std::make_shared(applicationName); return sender->bus.sendUnicast(msg, service::name::evt_manager); } bool EventManager::processKeypadBacklightRequest(bsp::keypad_backlight::Action act) { bool response = false; switch (act) { case bsp::keypad_backlight::Action::turnOn: response = bsp::keypad_backlight::turnOnAll(); break; case bsp::keypad_backlight::Action::turnOff: response = bsp::keypad_backlight::shutdown(); break; case bsp::keypad_backlight::Action::checkState: response = bsp::keypad_backlight::checkState(); break; } return response; } void EventManager::GetNextAlarmTimestamp(time_t timestamp) {}