// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include #include #include #include #include #include #include #include #include #include #include namespace sys { namespace { const std::map SliderStateToPhoneModeMapping = { {bsp::KeyCodes::SSwitchUp, phone_modes::PhoneMode::Connected}, {bsp::KeyCodes::SSwitchMid, phone_modes::PhoneMode::DoNotDisturb}, {bsp::KeyCodes::SSwitchDown, phone_modes::PhoneMode::Offline}}; } // namespace SystemManager::SystemManager(std::vector> &&creators) : SystemManagerCommon(std::move(creators)) {} void SystemManager::StartSystem(InitFunction sysInit, InitFunction appSpaceInit, DeinitFunction sysDeinit) { auto activeSimSelected = []() { const auto storeGsm = Store::GSM::get(); return ((storeGsm->selected == Store::GSM::SelectedSIM::SIM1 || storeGsm->selected == Store::GSM::SelectedSIM::SIM2) && storeGsm->simCardInserted()); }; auto isCallOngoing = [this]() { auto request = async_call(::service::name::cellular); sync(request); return request.getResult().active; }; phoneModeSubject = std::make_unique(this, std::move(activeSimSelected), std::move(isCallOngoing)); SystemManagerCommon::StartSystem(std::move(sysInit), std::move(appSpaceInit), std::move(sysDeinit)); } ReturnCodes SystemManager::InitHandler() { SystemManagerCommon::InitHandler(); connect(typeid(PhoneModeRequest), [this](sys::Message *message) -> sys::MessagePointer { auto request = static_cast(message); return handlePhoneModeRequest(request); }); connect(typeid(TetheringStateRequest), [this](sys::Message *message) -> sys::MessagePointer { auto request = static_cast(message); return handleTetheringStateRequest(request); }); connect(typeid(TetheringEnabledResponse), [this](sys::Message *message) -> sys::MessagePointer { auto response = static_cast(message); return enableTethering(response); }); connect(cellular::CheckIfStartAllowedMessage(), [&](Message *) { switch (Store::Battery::get().levelState) { case Store::Battery::LevelState::Normal: CellularServiceAPI::ChangeModulePowerState(this, cellular::service::State::PowerState::On); break; case Store::Battery::LevelState::CriticalCharging: [[fallthrough]]; case Store::Battery::LevelState::CriticalNotCharging: CellularServiceAPI::ChangeModulePowerState(this, cellular::service::State::PowerState::Off); break; case Store::Battery::LevelState::Shutdown: break; } return MessageNone{}; }); return ReturnCodes::Success; } phone_modes::PhoneMode SystemManager::translateSliderState(const RawKey &key) { const auto code = key.keyCode; 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."); if (phoneModeSubject->isTetheringEnabled()) { LOG_WARN("Changing phone mode when tethering is enabled!"); // display popup bus.sendUnicast(std::make_shared(), service::name::appmgr); return MessageNone{}; } phoneModeSubject->setPhoneMode(request->getPhoneMode()); return MessageNone{}; } MessagePointer SystemManager::handleTetheringStateRequest(TetheringStateRequest *request) { LOG_INFO("Tethering state change requested"); if (Store::Battery::get().levelState != Store::Battery::LevelState::Normal) { LOG_INFO("Tethering state change refused - battery too low"); return MessageNone{}; } if (const auto requestedState = request->getTetheringState(); requestedState == phone_modes::Tethering::On) { if (phoneModeSubject->isTetheringPossible()) { bus.sendUnicast(std::make_shared(), service::name::appmgr); } } else { if (const auto tetheringChanged = phoneModeSubject->setTetheringMode(phone_modes::Tethering::Off); !tetheringChanged) { bus.sendUnicast(std::make_shared(), service::name::appmgr); } else { // Turned on, disabling... LOG_INFO("Disabling tethering"); bus.sendUnicast(std::make_shared(), service::name::evt_manager); } } return MessageNone{}; } MessagePointer SystemManager::enableTethering([[maybe_unused]] TetheringEnabledResponse *response) { phoneModeSubject->setTetheringMode(phone_modes::Tethering::On); return MessageNone{}; } void SystemManager::batteryNormalLevelAction() { SystemManagerCommon::batteryNormalLevelAction(); CellularServiceAPI::ChangeModulePowerState(this, cellular::service::State::PowerState::On); auto msg = std::make_shared( false, Store::Battery::get().state == Store::Battery::State::Charging); bus.sendUnicast(std::move(msg), service::name::appmgr); } void SystemManager::batteryCriticalLevelAction(bool charging) { SystemManagerCommon::batteryCriticalLevelAction(charging); CellularServiceAPI::ChangeModulePowerState(this, cellular::service::State::PowerState::Off); EventManagerServiceAPI::turnOffTorch(this); auto msg = std::make_shared(true, charging); bus.sendUnicast(std::move(msg), service::name::appmgr); } void SystemManager::handleShutdown() { // check if we are discharging - if so -> shutdown if (Store::Battery::get().state == Store::Battery::State::Discharging) { set(State::ShutdownReady); } else { // await from EvtManager for info that red key was pressed / timeout auto msg = mailbox.pop(); if (!msg) { return; } if (msg->sender != service::name::evt_manager) { LOG_ERROR("Ignored msg from: %s on shutdown", msg->sender.c_str()); return; } msg->Execute(this); } } } // namespace sys