M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +9 -1
@@ 107,8 107,10 @@ namespace app::manager
blockingTimer{std::make_unique<sys::Timer>(
timerBlock, this, std::numeric_limits<sys::ms>::max(), sys::Timer::Type::SingleShot)},
shutdownDelay{std::make_unique<sys::Timer>(timerShutdownDelay, this, shutdown_delay_ms)},
- settings(std::make_unique<settings::Settings>(this))
+ settings(std::make_unique<settings::Settings>(this)),
+ phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
{
+ bus.channels.push_back(sys::BusChannel::PhoneModeChanges);
registerMessageHandlers();
blockingTimer->connect([this](sys::Timer &) { onPhoneLocked(); });
}
@@ 195,6 197,12 @@ namespace app::manager
void ApplicationManager::registerMessageHandlers()
{
+ phoneModeObserver->connect(this);
+ phoneModeObserver->subscribe(
+ [](sys::phone_modes::PhoneMode phoneMode, sys::phone_modes::Tethering tetheringMode) {
+ LOG_INFO("Phone mode changed.");
+ });
+
connect(typeid(ApplicationStatusRequest), [this](sys::Message *request) {
auto msg = static_cast<ApplicationStatusRequest *>(request);
return std::make_shared<ApplicationStatusResponse>(msg->checkAppName,
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +2 -0
@@ 14,6 14,7 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
+#include <PhoneModes/Observer.hpp>
#include <SwitchData.hpp>
#include <deque>
@@ 154,6 155,7 @@ namespace app::manager
std::tuple<ApplicationName, actions::ActionId, actions::ActionParamsPtr> pendingAction;
std::unique_ptr<settings::Settings> settings;
+ std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;
void displayLanguageChanged(std::string value);
void lockTimeChanged(std::string value);
void inputLanguageChanged(std::string value);
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +11 -3
@@ 40,6 40,7 @@
#include <module-apps/messages/AppMessage.hpp>
#include <SystemManager/messages/CpuFrequencyMessage.hpp>
#include <common_data/EventStore.hpp>
+#include <SystemManager/messages/PhoneModeRequest.hpp>
EventManager::EventManager(const std::string &name)
: sys::Service(name), screenLightControl(std::make_unique<screen_light_control::ScreenLightControl>(this))
@@ 102,9 103,16 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
auto message = std::make_shared<sevm::KbdMessage>();
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);
+ if (message->key.state == RawKey::State::Pressed) {
+ const auto code = message->key.key_code;
+ if (code == bsp::KeyCodes::FnRight) {
+ bus.sendUnicast(message, service::name::system_manager);
+ }
+ else if (code == bsp::KeyCodes::SSwitchUp || code == bsp::KeyCodes::SSwitchMid ||
+ code == bsp::KeyCodes::SSwitchDown) {
+ const auto mode = sys::SystemManager::translateSliderState(message->key);
+ bus.sendUnicast(std::make_shared<sys::PhoneModeRequest>(mode), service::name::system_manager);
+ }
}
// send key to focused application
M module-sys/CMakeLists.txt => module-sys/CMakeLists.txt +2 -0
@@ 14,6 14,8 @@ set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/Service/Service.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Service/Timer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Service/CpuSentinel.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/PhoneModes/Subject.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/PhoneModes/Observer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/SystemManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/DependencyGraph.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/PowerManager.cpp
A module-sys/PhoneModes/Common.hpp => module-sys/PhoneModes/Common.hpp +49 -0
@@ 0,0 1,49 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Service/Message.hpp>
+
+namespace sys::phone_modes
+{
+ enum class PhoneMode
+ {
+ Connected,
+ DoNotDisturb,
+ Offline
+ };
+
+ enum class Tethering
+ {
+ Off,
+ On
+ };
+
+ class PhoneModeChanged : public DataMessage
+ {
+ public:
+ PhoneModeChanged(PhoneMode phoneMode, Tethering tetheringMode)
+ : DataMessage{MessageType::MessageTypeUninitialized}, phoneMode{phoneMode}, tethering{tetheringMode}
+ {}
+
+ [[nodiscard]] auto getPhoneMode() const noexcept
+ {
+ return phoneMode;
+ }
+ [[nodiscard]] auto getTetheringMode() const noexcept
+ {
+ return tethering;
+ }
+
+ private:
+ PhoneMode phoneMode;
+ Tethering tethering;
+ };
+
+ class PhoneModeChangedSuccessfully : public ResponseMessage
+ {};
+
+ class PhoneModeChangeFailed : public ResponseMessage
+ {};
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Observer.cpp => module-sys/PhoneModes/Observer.cpp +70 -0
@@ 0,0 1,70 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "Observer.hpp"
+
+#include <Service/Service.hpp>
+
+namespace sys::phone_modes
+{
+ void Observer::connect(Service *owner)
+ {
+ owner->connect(typeid(PhoneModeChanged), [this](sys::Message *request) -> sys::MessagePointer {
+ return handlePhoneModeChange(static_cast<PhoneModeChanged *>(request));
+ });
+ }
+
+ void Observer::subscribe(OnChangeCallback &&onChange,
+ OnCompleteCallback &&onComplete,
+ OnErrorCallback &&onError) noexcept
+ {
+ onChangeCallback = std::move(onChange);
+ onCompleteCallback = std::move(onComplete);
+ onErrorCallback = std::move(onError);
+ }
+
+ bool Observer::isInMode(PhoneMode mode) const noexcept
+ {
+ return phoneMode == mode;
+ }
+
+ bool Observer::isTetheringOn() const noexcept
+ {
+ return tetheringMode == Tethering::On;
+ }
+
+ sys::MessagePointer Observer::handlePhoneModeChange(PhoneModeChanged *message)
+ {
+ phoneMode = message->getPhoneMode();
+ tetheringMode = message->getTetheringMode();
+
+ try {
+ onPhoneModeChanged();
+ }
+ catch (const std::exception &) {
+ return std::make_shared<PhoneModeChangeFailed>();
+ }
+ return std::make_shared<PhoneModeChangedSuccessfully>();
+ }
+
+ void Observer::onPhoneModeChanged()
+ {
+ if (!onChangeCallback) {
+ LOG_WARN("No subscriber on phone mode change.");
+ return;
+ }
+
+ try {
+ onChangeCallback(phoneMode, tetheringMode);
+ if (onCompleteCallback) {
+ onCompleteCallback();
+ }
+ }
+ catch (const std::exception &error) {
+ if (onErrorCallback) {
+ onErrorCallback(error);
+ }
+ throw;
+ }
+ }
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Observer.hpp => module-sys/PhoneModes/Observer.hpp +43 -0
@@ 0,0 1,43 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <functional>
+#include <stdexcept>
+
+#include "Common.hpp"
+
+namespace sys
+{
+ class Service; // Forward declaration
+} // namespace sys
+
+namespace sys::phone_modes
+{
+ class Observer
+ {
+ public:
+ using OnChangeCallback = std::function<void(PhoneMode, Tethering)>;
+ using OnCompleteCallback = std::function<void()>;
+ using OnErrorCallback = std::function<void(const std::exception &)>;
+
+ void connect(Service *owner);
+ void subscribe(OnChangeCallback &&onChange,
+ OnCompleteCallback &&onComplete = {},
+ OnErrorCallback &&onError = {}) noexcept;
+
+ bool isInMode(PhoneMode mode) const noexcept;
+ bool isTetheringOn() const noexcept;
+
+ private:
+ sys::MessagePointer handlePhoneModeChange(PhoneModeChanged *message);
+ void onPhoneModeChanged();
+
+ OnChangeCallback onChangeCallback;
+ OnCompleteCallback onCompleteCallback;
+ OnErrorCallback onErrorCallback;
+ PhoneMode phoneMode = PhoneMode::Connected;
+ Tethering tetheringMode = Tethering::Off;
+ };
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Subject.cpp => module-sys/PhoneModes/Subject.cpp +61 -0
@@ 0,0 1,61 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "Subject.hpp"
+
+#include <Service/Service.hpp>
+
+#include <module-utils/magic_enum/include/magic_enum.hpp>
+
+#include <stdexcept>
+#include <utility>
+
+namespace sys::phone_modes
+{
+ Subject::Subject(Service *owner) : owner{owner}
+ {
+ if (owner == nullptr) {
+ throw std::invalid_argument{"Subject's owner is invalid"};
+ }
+ }
+
+ void Subject::setMode(PhoneMode _phoneMode, Tethering _tetheringMode)
+ {
+ if (const bool changed = changePhoneMode(_phoneMode) || changeTetheringMode(_tetheringMode); changed) {
+ notifyChange();
+ }
+ }
+
+ void Subject::setPhoneMode(PhoneMode mode)
+ {
+ if (const auto changed = changePhoneMode(mode); changed) {
+ notifyChange();
+ }
+ }
+
+ bool Subject::changePhoneMode(PhoneMode mode) noexcept
+ {
+ return std::exchange(phoneMode, mode) != mode;
+ }
+
+ void Subject::setTetheringMode(Tethering mode)
+ {
+ if (const auto changed = changeTetheringMode(mode); changed) {
+ notifyChange();
+ }
+ }
+
+ bool Subject::changeTetheringMode(Tethering mode) noexcept
+ {
+ return std::exchange(tetheringMode, mode) != mode;
+ }
+
+ void Subject::notifyChange()
+ {
+ LOG_INFO("Phone modes changed: Phone mode: [%s]; Tethering: [%s]. Notifying phone modes observers.",
+ magic_enum::enum_name(phoneMode).data(),
+ magic_enum::enum_name(tetheringMode).data());
+ auto message = std::make_shared<PhoneModeChanged>(phoneMode, tetheringMode);
+ owner->bus.sendMulticast(std::move(message), BusChannel::PhoneModeChanges);
+ }
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Subject.hpp => module-sys/PhoneModes/Subject.hpp +33 -0
@@ 0,0 1,33 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "Common.hpp"
+
+namespace sys
+{
+ class Service; // Forward declaration
+} // namespace sys
+
+namespace sys::phone_modes
+{
+ class Subject
+ {
+ public:
+ explicit Subject(Service *owner);
+
+ void setMode(PhoneMode _phoneMode, Tethering _tetheringMode);
+ void setPhoneMode(PhoneMode mode);
+ void setTetheringMode(Tethering mode);
+
+ private:
+ void notifyChange();
+ bool changePhoneMode(PhoneMode mode) noexcept;
+ bool changeTetheringMode(Tethering mode) noexcept;
+
+ Service *owner;
+ PhoneMode phoneMode = PhoneMode::Connected;
+ Tethering tetheringMode = Tethering::Off;
+ };
+} // namespace sys::phone_modes
M module-sys/Service/Common.hpp => module-sys/Service/Common.hpp +4 -1
@@ 21,7 21,8 @@ namespace sys
ServiceFotaNotifications,
AntennaNotifications,
ServiceEvtmgrNotifications,
- CalendarNotifications
+ CalendarNotifications,
+ PhoneModeChanges,
};
enum class ServicePriority
@@ 111,6 112,8 @@ inline const char *c_str(sys::BusChannel channel)
return "ServiceEvtmgrNotifications";
case sys::BusChannel::CalendarNotifications:
return "CalendarNotifications";
+ case sys::BusChannel::PhoneModeChanges:
+ return "PhoneModeChanges";
}
return "";
}
M module-sys/SystemManager/SystemManager.cpp => module-sys/SystemManager/SystemManager.cpp +31 -0
@@ 25,12 25,20 @@
#include "messages/DeviceRegistrationMessage.hpp"
#include "messages/SentinelRegistrationMessage.hpp"
#include "messages/RequestCpuFrequencyMessage.hpp"
+#include "messages/PhoneModeRequest.hpp"
#include <time/ScopedTime.hpp>
const inline size_t systemManagerStack = 4096 * 2;
namespace sys
{
+ namespace
+ {
+ const std::map<bsp::KeyCodes, phone_modes::PhoneMode> SliderStateToPhoneModeMapping = {
+ {bsp::KeyCodes::SSwitchUp, phone_modes::PhoneMode::Connected},
+ {bsp::KeyCodes::SSwitchMid, phone_modes::PhoneMode::DoNotDisturb},
+ {bsp::KeyCodes::SSwitchDown, phone_modes::PhoneMode::Offline}};
+ } // namespace
using namespace cpp_freertos;
using namespace std;
@@ 146,6 154,7 @@ namespace sys
powerManager = std::make_unique<PowerManager>();
cpuStatistics = std::make_unique<CpuStatistics>();
deviceManager = std::make_unique<DeviceManager>();
+ phoneModeSubject = std::make_unique<phone_modes::Subject>(this);
systemInit = std::move(sysInit);
userInit = std::move(appSpaceInit);
@@ 370,6 379,11 @@ namespace sys
return sys::MessageNone{};
});
+ connect(typeid(PhoneModeRequest), [this](sys::Message *message) -> sys::MessagePointer {
+ auto request = static_cast<PhoneModeRequest *>(message);
+ return handlePhoneModeRequest(request);
+ });
+
deviceManager->RegisterNewDevice(powerManager->getExternalRamDevice());
return ReturnCodes::Success;
@@ 476,6 490,23 @@ namespace sys
powerManager->UpdateCpuFrequency(cpuStatistics->GetPercentageCpuLoad());
}
+ phone_modes::PhoneMode SystemManager::translateSliderState(const RawKey &key)
+ {
+ const auto code = key.key_code;
+ if (code != bsp::KeyCodes::SSwitchUp && code != bsp::KeyCodes::SSwitchMid &&
+ code != bsp::KeyCodes::SSwitchDown) {
+ throw std::invalid_argument{"Invalid key code passed."};
+ }
+ return SliderStateToPhoneModeMapping.at(code);
+ }
+
+ MessagePointer SystemManager::handlePhoneModeRequest(PhoneModeRequest *request)
+ {
+ LOG_INFO("Phone mode change requested.");
+ phoneModeSubject->setPhoneMode(request->getPhoneMode());
+ return MessageNone{};
+ }
+
std::vector<std::shared_ptr<Service>> SystemManager::servicesList;
cpp_freertos::MutexStandard SystemManager::destroyMutex;
std::unique_ptr<PowerManager> SystemManager::powerManager;
M module-sys/SystemManager/SystemManager.hpp => module-sys/SystemManager/SystemManager.hpp +12 -0
@@ 19,6 19,8 @@
#include "Service/Service.hpp"
#include "Service/ServiceCreator.hpp"
#include "PowerManager.hpp"
+#include "PhoneModes/Subject.hpp"
+#include <common_data/RawKey.hpp>
#include "Constants.hpp"
#include "CpuStatistics.hpp"
#include "DeviceManager.hpp"
@@ 34,6 36,8 @@ namespace sys
inline constexpr std::chrono::milliseconds timerPeriodInterval{100ms};
} // namespace constants
+ class PhoneModeRequest; // Forward declaration
+
enum class Code
{
CloseSystem,
@@ 92,6 96,11 @@ namespace sys
/// @note there is no fallback
static bool DestroyService(const std::string &name, Service *caller, TickType_t timeout = 5000);
+ /// Translates a slider state into a phone mode.
+ /// \param key Slider button state
+ /// \return Phone mode.
+ static phone_modes::PhoneMode translateSliderState(const RawKey &key);
+
/// Kill service
/// @note - this is final, it straight takes service, calls it's close callback and it's gone
/// please mind that services & apps not registered in SystemManager cant be killed - these should be handled by
@@ 143,10 152,13 @@ namespace sys
/// periodic update of cpu statistics
void CpuStatisticsTimerHandler();
+ MessagePointer handlePhoneModeRequest(PhoneModeRequest *request);
+
bool cpuStatisticsTimerInit{false};
std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
std::unique_ptr<sys::Timer> cpuStatisticsTimer;
+ std::unique_ptr<phone_modes::Subject> phoneModeSubject;
InitFunction userInit;
InitFunction systemInit;
A module-sys/SystemManager/messages/PhoneModeRequest.hpp => module-sys/SystemManager/messages/PhoneModeRequest.hpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-sys/PhoneModes/Common.hpp>
+
+namespace sys
+{
+ class PhoneModeRequest : public sys::DataMessage
+ {
+ public:
+ explicit PhoneModeRequest(phone_modes::PhoneMode mode)
+ : sys::DataMessage(MessageType::MessageTypeUninitialized), mode{mode}
+ {}
+
+ [[nodiscard]] auto getPhoneMode() const noexcept -> phone_modes::PhoneMode
+ {
+ return mode;
+ }
+
+ private:
+ phone_modes::PhoneMode mode;
+ };
+} // namespace sys