From cb593f45c32f6a2d5f39489674ef60fa63a7f532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kamo=C5=84?= <70628259+mkamonMdt@users.noreply.github.com> Date: Fri, 20 Nov 2020 17:51:22 +0100 Subject: [PATCH] [EGD-4367] sim passcodes flow implementation (#1033) --- changelog.md | 1 + image/assets/lang/lang_en.json | 3 + .../ApplicationDesktop.cpp | 36 ++- .../ApplicationDesktop.hpp | 13 +- .../data/AppDesktopStyle.hpp | 26 +- .../data/LockPhoneData.hpp | 20 +- .../application-desktop/widgets/PinLock.cpp | 80 ++---- .../application-desktop/widgets/PinLock.hpp | 120 ++++---- .../widgets/PinLockHandler.cpp | 269 +++++++++++------- .../widgets/PinLockHandler.hpp | 41 ++- .../windows/DesktopMainWindow.cpp | 104 ++++--- .../windows/DesktopMainWindow.hpp | 4 + .../windows/PinLockBaseWindow.cpp | 30 +- .../windows/PinLockBaseWindow.hpp | 14 +- .../windows/PinLockBox.hpp | 23 +- .../windows/PinLockWindow.cpp | 140 +++++---- .../windows/PinLockWindow.hpp | 9 +- .../windows/PukLockBox.cpp | 119 +++++--- .../windows/PukLockBox.hpp | 17 +- .../windows/ScreenLockBox.cpp | 111 ++++++-- .../windows/ScreenLockBox.hpp | 28 +- .../windows/SimLockBox.cpp | 128 +++++---- .../windows/SimLockBox.hpp | 17 +- module-services/service-appmgr/CMakeLists.txt | 1 + .../service-appmgr/data/SimActionsParams.cpp | 43 +++ .../model/ApplicationManager.cpp | 19 ++ .../service-appmgr/service-appmgr/Actions.hpp | 7 +- .../service-appmgr/data/SimActionsParams.hpp | 59 ++++ .../model/ApplicationManager.hpp | 2 +- .../service-cellular/CellularMessage.hpp | 170 +++++++++++ .../service-desktop/ServiceDesktop.cpp | 1 + 31 files changed, 1151 insertions(+), 504 deletions(-) create mode 100644 module-services/service-appmgr/data/SimActionsParams.cpp create mode 100644 module-services/service-appmgr/service-appmgr/data/SimActionsParams.hpp diff --git a/changelog.md b/changelog.md index e8f2a82a43204b7f6a66f4d676ea7ca5a9df6903..91a114e82d8e44739c3d0e91f77c64a31e5d8308 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,7 @@ ### Added +* `[gui][desktop]` Added SIM PIN basic flow implementation * `[cellular]` Added CLIR, CLIP, COLP, call waiting MMI support ## [0.47.1 2020-11-20] diff --git a/image/assets/lang/lang_en.json b/image/assets/lang/lang_en.json index 82fe8243227ecd6a485793a9553431cb059cadb8..54abad844b01ebd7fb15460e979abda3af505657 100644 --- a/image/assets/lang/lang_en.json +++ b/image/assets/lang/lang_en.json @@ -163,6 +163,8 @@ "app_desktop_sim_card": "card", "app_desktop_sim_type_pin": "please type a PIN code:", "app_desktop_sim_blocked": "The SIM card is blocked.", + "app_desktop_sim_enter_pin": "Enter new PIN code", + "app_desktop_sim_confirm_pin": "Enter new PIN code", "app_desktop_sim_type_puk": "To unblock it, type the PUK code:", "app_desktop_no_pin_lock": "Press Unlock and then #", "app_desktop_sim_wrong_pin": "Wrong PIN code", @@ -175,6 +177,7 @@ "app_desktop_sim_warning3": "have to contact the operator", "app_desktop_sim_blocked_info1": "Sorry, SIM card permanently blocked.", "app_desktop_sim_blocked_info2": "Please contact your service provider", + "app_desktop_sim_cme_error": "SIM card\nCME error:", "app_desktop_unread_messages": "Unread messages", "app_desktop_missed_calls": "Missed calls", diff --git a/module-apps/application-desktop/ApplicationDesktop.cpp b/module-apps/application-desktop/ApplicationDesktop.cpp index 13c0522bb7c4ecb094e0792488cac9c27794f98e..c0e055ae09e852e7e405394fe04cdbe22a0c181a 100644 --- a/module-apps/application-desktop/ApplicationDesktop.cpp +++ b/module-apps/application-desktop/ApplicationDesktop.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,31 @@ namespace app : Application(name, parent, startInBackground), lockHandler(this, settings) { busChannels.push_back(sys::BusChannels::ServiceDBNotifications); + + addActionReceiver(app::manager::actions::RequestPin, [this](auto &&data) { + lockHandler.handlePinRequest(std::move(data)); + return msgHandled(); + }); + + addActionReceiver(app::manager::actions::RequestPuk, [this](auto &&data) { + lockHandler.handlePukRequest(std::move(data)); + return msgHandled(); + }); + + addActionReceiver(app::manager::actions::RequestPinChange, [this](auto &&data) { + lockHandler.handlePinChangeRequest(std::move(data)); + return msgHandled(); + }); + + addActionReceiver(app::manager::actions::BlockSim, [this](auto &&data) { + lockHandler.handleSimBlocked(std::move(data)); + return msgHandled(); + }); + + addActionReceiver(app::manager::actions::DisplayCMEError, [this](auto &&data) { + lockHandler.handleCMEError(std::move(data)); + return msgHandled(); + }); } ApplicationDesktop::~ApplicationDesktop() @@ -63,9 +89,6 @@ namespace app else if (auto msg = dynamic_cast(msgl)) { handled = handle(msg); } - else if (auto msg = dynamic_cast(msgl)) { - handled = lockHandler.handle(msg); - } // handle database response if (resp != nullptr) { @@ -100,7 +123,8 @@ namespace app auto ApplicationDesktop::handle(sdesktop::developerMode::ScreenlockCheckEvent *event) -> bool { if (event != nullptr) { - auto event = std::make_unique(lockHandler.lock.isLocked()); + auto event = + std::make_unique(true); // lockHandler.lock.isLocked()); auto msg = std::make_shared(std::move(event)); sys::Bus::SendUnicast(std::move(msg), service::name::service_desktop, this); } @@ -167,7 +191,7 @@ namespace app { assert(msg); if (msg->request == cellular::State::ST::URCReady) { - if (need_sim_select && !lockHandler.lock.isLocked()) { + if (need_sim_select && !lockHandler.isScreenLocked()) { app::manager::Controller::switchApplication(this, app::name_settings, app::sim_select, nullptr); return true; } @@ -280,7 +304,7 @@ namespace app return std::make_unique(app); }); windowsFactory.attach(desktop_pin_lock, [&](Application *app, const std::string newname) { - return std::make_unique(app, desktop_pin_lock, lockHandler.lock); + return std::make_unique(app, desktop_pin_lock); }); windowsFactory.attach(desktop_menu, [](Application *app, const std::string newname) { return std::make_unique(app); diff --git a/module-apps/application-desktop/ApplicationDesktop.hpp b/module-apps/application-desktop/ApplicationDesktop.hpp index d9b1941a9f88557f95956c3d8f8b866f84285743..883e120ce5533a185de2bd5a52ae245071e0d91c 100644 --- a/module-apps/application-desktop/ApplicationDesktop.hpp +++ b/module-apps/application-desktop/ApplicationDesktop.hpp @@ -15,6 +15,11 @@ #include #include +namespace cellular +{ + class StateChange; +} + namespace app { inline constexpr auto name_desktop = "ApplicationDesktop"; @@ -83,7 +88,13 @@ namespace app { static auto GetManifest() -> manager::ApplicationManifest { - return {{manager::actions::Launch}}; + return {{manager::actions::Launch, + manager::actions::RequestPin, + manager::actions::RequestPuk, + manager::actions::RequestPinChange, + manager::actions::UnlockSim, + manager::actions::BlockSim, + manager::actions::DisplayCMEError}}; } }; diff --git a/module-apps/application-desktop/data/AppDesktopStyle.hpp b/module-apps/application-desktop/data/AppDesktopStyle.hpp index 4208a034eb74be421eb384207fb510d8881c6d24..a12edc8c613eda09af4392ca6d0c4c077acb06b7 100644 --- a/module-apps/application-desktop/data/AppDesktopStyle.hpp +++ b/module-apps/application-desktop/data/AppDesktopStyle.hpp @@ -7,17 +7,17 @@ namespace style::window::pin_lock { - const inline uint32_t image_x = 177; - const inline uint32_t image_y = 132; - const inline uint32_t title_label_y = 60; - const inline uint32_t title_label_h = 40; - const inline uint32_t label_size = 30; - const inline uint32_t label_size_screen = 60; - const inline uint32_t pin_label_x = 85; - const inline uint32_t pin_label_x_screen = 100; - const inline uint32_t pin_label_y = 450; - const inline uint32_t info_text_y = 294; - const inline uint32_t info_text_h_screen = 60; - const inline uint32_t info_text_h_sim = 150; - const inline uint32_t info_text_h_puk = 180; + constexpr inline auto image_x = 177; + constexpr inline auto image_y = 132; + constexpr inline auto title_label_y = 60; + constexpr inline auto title_label_h = 40; + constexpr inline auto label_size = 60; + constexpr inline auto label_margins = 10; + constexpr inline auto pin_label_x = 85; + constexpr inline auto pin_label_y = 450; + constexpr inline auto pin_label_y_screen = 400; + constexpr inline auto info_text_y = 294; + constexpr inline auto info_text_h_screen = 60; + constexpr inline auto info_text_h_sim = 150; + constexpr inline auto info_text_h_puk = 180; } // namespace style::window::pin_lock diff --git a/module-apps/application-desktop/data/LockPhoneData.hpp b/module-apps/application-desktop/data/LockPhoneData.hpp index 80a2aa369c41cf904f6d4b20f46d440be1fb2942..3e76a672a6dc1f60e5474c75642c980854349cbd 100644 --- a/module-apps/application-desktop/data/LockPhoneData.hpp +++ b/module-apps/application-desktop/data/LockPhoneData.hpp @@ -9,6 +9,8 @@ #include #include +#include "application-desktop/widgets/PinLock.hpp" + namespace gui { @@ -16,17 +18,10 @@ namespace gui class LockPhoneData : public gui::SwitchData { std::string previousApplication; - LockPhoneData() = default; + std::unique_ptr lock; public: - enum class Request - { - NoPin, - Pin, - ShowPrompt, - } request; - - LockPhoneData(Request request) : SwitchData(), request(request) + LockPhoneData(std::unique_ptr &&lock) : SwitchData(), lock(std::move(lock)) { description = "LockPhoneData"; } @@ -37,10 +32,15 @@ namespace gui { previousApplication = prevApp; }; - const std::string &getPreviousApplication() + [[nodiscard]] const std::string &getPreviousApplication() { return previousApplication; }; + + [[nodiscard]] std::unique_ptr getLock() + { + return std::make_unique(*lock.get()); + } }; class UpdateSwitchData : public gui::SwitchData diff --git a/module-apps/application-desktop/widgets/PinLock.cpp b/module-apps/application-desktop/widgets/PinLock.cpp index 2a1646dcbfd3377d1a74814ff14a5dc9cded3356..f7ff871b6b67fdef0aee986362b3583f5c5caeb0 100644 --- a/module-apps/application-desktop/widgets/PinLock.cpp +++ b/module-apps/application-desktop/widgets/PinLock.cpp @@ -6,83 +6,53 @@ namespace gui { - PinLock::PinLock(gui::PinLockHandler *handler) : handler(handler) - {} - - void PinLock::consumeInvalidPinState() noexcept + void PinLock::consumeState() noexcept { - if (state == State::InvalidPin) { - state = State::EnterPin; + if (lockState == LockState::PasscodeInvalidRetryRequired) { + lockState = LockState::PasscodeRequired; } - } - - void PinLock::putNextChar(unsigned int c) noexcept - { - if (state == State::EnterPin && charCount < pinValue.size()) { - pinValue[charCount++] = c; + else if (lockState == LockState::NewPasscodeInvalid) { + lockState = LockState::NewPasscodeRequired; } } - void PinLock::verifyPin() noexcept + void PinLock::setNewPasscodeInvalidState() noexcept { - if (charCount == pinValue.size()) { - handler->handle(pinValue); - clearAttempt(); + if (lockState == LockState::NewPasscodeRequired) { + lockState = LockState::NewPasscodeInvalid; } } - void PinLock::popChar() noexcept + void PinLock::putNextChar(unsigned int c) { - if (state == State::EnterPin && charCount > 0) { - charCount--; - pinValue[charCount] = 0; + if (maxPinSize > pinValue.size()) { + pinValue.push_back(c); } - } - - void PinLock::clearAttempt() noexcept - { - for (auto &c : pinValue) { - c = 0; + if (canVerify() && autoActivate && onActivatedCallback != nullptr) { + onActivatedCallback(pinValue); } - charCount = 0; } - bool PinLock::unlock() noexcept + void PinLock::popChar() { - if (state == State::VerifiedPin || pinValue.size() == 0) { - state = State::Unlocked; - return true; + if (pinValue.size() > 0) { + pinValue.pop_back(); } - return false; } - void PinLock::lock() noexcept - { - if (state == State::Unlocked) { - state = State::EnterPin; - } - } - - bool PinLock::isLocked() const noexcept + void PinLock::clearAttempt() noexcept { - return state != State::Unlocked; + pinValue.clear(); } - std::string PinLock::getLockInfo(const InfoName name) const + void PinLock::verify() { - try { - return additionalLockInfo.at(name); + auto pinCopy = std::move(pinValue); + clearAttempt(); + if (!onActivatedCallback) { + LOG_ERROR("Passcode verification callback null"); + return; } - catch (std::out_of_range &) { - return std::string{}; - } - } - - void PinLock::reset(LockType newType, State newState, unsigned int attempts, unsigned int size) noexcept - { - type = newType; - state = newState; - remainingAttempts = attempts; - pinValue = std::vector(size, 0); + onActivatedCallback(pinCopy); } } // namespace gui diff --git a/module-apps/application-desktop/widgets/PinLock.hpp b/module-apps/application-desktop/widgets/PinLock.hpp index 1c696a7bb5b2c269e59639f619ab7caee6ba147e..d84026bf40199ffe6734a5b8b81cf8000f271e74 100644 --- a/module-apps/application-desktop/widgets/PinLock.hpp +++ b/module-apps/application-desktop/widgets/PinLock.hpp @@ -2,8 +2,9 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once - -#include "PhoneNumber.hpp" +#include +#include +#include namespace gui { @@ -14,82 +15,103 @@ namespace gui public: enum class LockType { - Screen, - SIM, - PUK, - Unknown + SimPin, + SimPuk, + Screen }; - enum class InfoName + enum class LockState { - LockName, - PhoneNum + Unlocked, + PasscodeRequired, + PasscodeInvalidRetryRequired, + Blocked, + NewPasscodeRequired, + NewPasscodeInvalid, + ErrorOccurred }; - enum class State + enum class SimCard { - EnterPin, - InvalidPin, - VerifiedPin, - Blocked, - Unlocked + SIM1, + SIM2, + NoCard }; - [[nodiscard]] State getState() const noexcept + [[nodiscard]] LockState getState() const noexcept { - return state; + return lockState; } - [[nodiscard]] unsigned int getPinSize() const noexcept + [[nodiscard]] LockType getLockType() const noexcept { - return pinValue.size(); + return lockType; + } + [[nodiscard]] unsigned int getMaxPinSize() const noexcept + { + return maxPinSize; } /// returns current position of a PIN character to be inserted [[nodiscard]] unsigned int getCharCount() const noexcept { - return charCount; + return pinValue.size(); + } + [[nodiscard]] bool canPut() const noexcept + { + return getCharCount() < getMaxPinSize(); } - [[nodiscard]] unsigned int getRemainingAttempts() const noexcept + [[nodiscard]] bool canVerify() const noexcept { - return remainingAttempts; + return getCharCount() >= minPinSize; } - [[nodiscard]] bool canPut() const noexcept + [[nodiscard]] std::vector getPin() const { - return getCharCount() != getPinSize(); + return pinValue; } - void putNextChar(unsigned int c) noexcept; - void verifyPin() noexcept; + [[nodiscard]] unsigned int getValue() const noexcept + { + return value; + } + + void putNextChar(unsigned int c); /// removes a last character passed to Lock via putNextChar. The last character can not be popped - void popChar() noexcept; + void popChar(); /// clear all characters passed to the Lock void clearAttempt() noexcept; - /// if Lock is in the State::InvalidPin state, changes it's state to the State::EnterPin - void consumeInvalidPinState() noexcept; + /// consumes LockState::PasscodeInvalidRetryRequired state and LockState::NewPasscodeInvalid) + void consumeState() noexcept; + void setNewPasscodeInvalidState() noexcept; - [[nodiscard]] bool isLocked() const noexcept; - bool unlock() noexcept; - void lock() noexcept; + void verify(); - [[nodiscard]] std::string getLockInfo(const InfoName name) const; - [[nodiscard]] LockType getLockType() const noexcept - { - return type; - } - PinLock(gui::PinLockHandler *); + PinLock(SimCard sim, LockState state, LockType type, unsigned int value) + : sim{sim}, lockState{state}, lockType{type}, value{value} + {} + PinLock(const PinLock &other) = default; + + std::function &)> onActivatedCallback = nullptr; private: - /// for PIN verification purposes as PIN storage and management is out of scope of PinLock class - gui::PinLockHandler *handler; + SimCard sim = SimCard::NoCard; + LockState lockState = LockState::Unlocked; + LockType lockType = LockType::Screen; + unsigned int value = 0; - LockType type = LockType::Unknown; - State state = State::EnterPin; - unsigned int remainingAttempts = 0; - /// code of the entered character on specified position std::vector pinValue; - /// flag defines number of entered pin characters - unsigned int charCount = 0; - std::map additionalLockInfo; + unsigned int maxPinSize = defaultPasscodeSize; + unsigned int minPinSize = defaultPasscodeSize; + bool autoActivate = false; + + static constexpr unsigned int defaultPasscodeSize = 4; - void reset(LockType, State, unsigned int remainingAttempts, unsigned int pinSize) noexcept; + void setAutoActivate(bool _autoActivate) + { + autoActivate = _autoActivate; + } + void setPinSizeBounds(unsigned int _minPinSize, unsigned int _maxPinSize) + { + minPinSize = _minPinSize; + maxPinSize = _maxPinSize; + } - friend class gui::PinLockHandler; + friend class PinLockHandler; }; } // namespace gui diff --git a/module-apps/application-desktop/widgets/PinLockHandler.cpp b/module-apps/application-desktop/widgets/PinLockHandler.cpp index 5e3467be58f195f45f4ba7d919d04e631057d604..04bff4805e3de8bb3c9af6f2a9ce7623bfb3be78 100644 --- a/module-apps/application-desktop/widgets/PinLockHandler.cpp +++ b/module-apps/application-desktop/widgets/PinLockHandler.cpp @@ -1,139 +1,218 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md +//// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +//// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "PinLockHandler.hpp" #include "PinHash.hpp" #include "application-desktop/ApplicationDesktop.hpp" -#include +#include "application-desktop/data/LockPhoneData.hpp" +#include "application-desktop/windows/Names.hpp" + +#include + +#include +#include namespace gui { - constexpr unsigned int default_screen_pin_size = 4; - constexpr unsigned int default_screen_attempts = 4; + namespace + { + constexpr unsigned int default_screen_pin_size = 4; + constexpr unsigned int screen_nopin_size = 0; + constexpr unsigned int default_attempts = 4; + constexpr unsigned int blocked_sim_attempts = 0; + constexpr unsigned int sim_max_passcode_size = 8; + constexpr unsigned int sim_min_passcode_size = 4; + } // namespace PinLockHandler::PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings) - : app(app), appSettings(settings), lock(this) + : app(app), appSettings(settings), screenLock(PinLock::SimCard::NoCard, + PinLock::LockState::PasscodeRequired, + PinLock::LockType::Screen, + default_attempts), + simLock(PinLock::SimCard::NoCard, PinLock::LockState::Unlocked, PinLock::LockType::SimPin, default_attempts) { reloadScreenLock(); + screenLock.setAutoActivate(true); + + simLock.setPinSizeBounds(sim_min_passcode_size, sim_max_passcode_size); } - auto PinLockHandler::handle(CellularSimResponseMessage *msg) -> bool + void PinLockHandler::handleScreenPin(const std::vector &pin) { - assert(msg); + if (screenLock.getMaxPinSize() == screen_nopin_size) { + screenLock.lockState = gui::PinLock::LockState::Unlocked; + } + else if (screenLock.value > 0) { + std::hash> hashEngine; + uint32_t hash = hashEngine(pin); + screenLock.value--; + if (hash == appSettings.lockPassHash) { + screenLock.lockState = gui::PinLock::LockState::Unlocked; + screenLock.value = default_attempts; + } + else if (screenLock.value > 0) { + screenLock.lockState = gui::PinLock::LockState::PasscodeInvalidRetryRequired; + } + else { + screenLock.lockState = gui::PinLock::LockState::Blocked; + } + } + } - parseSimCard(msg); - parseSimState(msg); - parseAttemptsAndPinSize(msg); + void PinLockHandler::handleScreenConfirm() + { + simLock.consumeState(); + } - app->getWindow(app::window::name::desktop_pin_lock)->rebuild(); - app->switchWindow(gui::name::window::main_window); - return true; + void PinLockHandler::reloadScreenLock() + { + screenLock.lockState = gui::PinLock::LockState::PasscodeRequired; + unsigned int pinSize = appSettings.lockPassHash == 0 ? screen_nopin_size : default_screen_pin_size; + screenLock.setPinSizeBounds(pinSize, pinSize); + screenLock.value = default_attempts; } - void PinLockHandler::handle(const std::vector &pin) + auto PinLockHandler::handlePasscodeParams(app::manager::actions::ActionParamsPtr &&data) const -> gui::PinLock { - if (lock.getLockType() == gui::PinLock::LockType::Screen) { - handleScreenPin(pin); - } - else { - handleSimPinOrPuk(pin); + auto passcodeData = static_cast(data.get()); + + gui::PinLock lock(parseSimCard(passcodeData->getSim()), + gui::PinLock::LockState::PasscodeRequired, + simLock.getLockType(), + passcodeData->getAttempts()); + + if (simLock.getLockType() == lock.getLockType() && simLock.getState() == lock.getState() && + simLock.getValue() > lock.getValue()) { + lock.lockState = PinLock::LockState::PasscodeInvalidRetryRequired; } + lock.setPinSizeBounds(sim_min_passcode_size, sim_max_passcode_size); + + return lock; } - void PinLockHandler::parseSimState(CellularSimResponseMessage *msg) - { - assert(msg); - switch (msg->getSimState()) { - case CellularSimResponseMessage::SimState::SIMUnlocked: - lock.type = gui::PinLock::LockType::Screen; - lock.state = gui::PinLock::State::EnterPin; - break; - case CellularSimResponseMessage::SimState::PINRequired: - lock.type = gui::PinLock::LockType::SIM; - lock.state = gui::PinLock::State::EnterPin; - break; - case CellularSimResponseMessage::SimState::PINInvalidRetryPossible: - lock.type = gui::PinLock::LockType::SIM; - lock.state = gui::PinLock::State::InvalidPin; - break; - case CellularSimResponseMessage::SimState::PUKRequired: - lock.type = gui::PinLock::LockType::PUK; - lock.state = gui::PinLock::State::EnterPin; - break; - case CellularSimResponseMessage::SimState::PUKInvalidRetryPossible: - lock.type = gui::PinLock::LockType::PUK; - lock.state = gui::PinLock::State::InvalidPin; - break; - case CellularSimResponseMessage::SimState::SIMBlocked: - lock.type = gui::PinLock::LockType::PUK; - lock.state = gui::PinLock::State::Blocked; - break; - } + void PinLockHandler::handlePinRequest(app::manager::actions::ActionParamsPtr &&data) + { + simLock = handlePasscodeParams(std::move(data)); + simLock.lockType = gui::PinLock::LockType::SimPin; + + auto onActivatedCallback = [this](const std::vector &data) { handlePasscode(data); }; + switchToPinlockWindow(onActivatedCallback); } - void PinLockHandler::parseSimCard(CellularSimResponseMessage *msg) - { - assert(msg); - switch (msg->getSimCard()) { - case Store::GSM::SIM::SIM1: - lock.additionalLockInfo[gui::PinLock::InfoName::LockName] = "SIM1"; - break; - case Store::GSM::SIM::SIM2: - lock.additionalLockInfo[gui::PinLock::InfoName::LockName] = "SIM2"; - break; - default: - LOG_ERROR("Unknown SIM"); - break; - } + void PinLockHandler::handlePukRequest(app::manager::actions::ActionParamsPtr &&data) + { + simLock = handlePasscodeParams(std::move(data)); + simLock.lockType = gui::PinLock::LockType::SimPuk; + + auto onActivatedCallback = [this](const std::vector &data) { handlePasscodeChange(data); }; + switchToPinlockWindow(onActivatedCallback); } - void PinLockHandler::parseAttemptsAndPinSize(CellularSimResponseMessage *msg) + void PinLockHandler::switchToPinlockWindow( + std::function &)> onLockActivatedCallback) { - if (msg->getSimState() == CellularSimResponseMessage::SimState::SIMUnlocked) { - reloadScreenLock(); + auto lock = std::make_unique(simLock); + + if (lock->getState() == PinLock::LockState::PasscodeInvalidRetryRequired) { + lock->onActivatedCallback = [this, onLockActivatedCallback](const std::vector &) { + simLock.consumeState(); + switchToPinlockWindow(onLockActivatedCallback); + }; } else { - lock.pinValue = std::vector(msg->getPinSize(), 0); - lock.remainingAttempts = msg->getAttemptsLeft(); + lock->onActivatedCallback = onLockActivatedCallback; } + + app->switchWindow(app::window::name::desktop_pin_lock, + gui::ShowMode::GUI_SHOW_INIT, + std::make_unique(std::move(lock))); } - void PinLockHandler::handleScreenPin(const std::vector &pin) + void PinLockHandler::handlePinChangeRequest(app::manager::actions::ActionParamsPtr &&data) { - if (lock.remainingAttempts > 0) { - std::hash> hashEngine; - uint32_t hash = hashEngine(pin); - lock.remainingAttempts--; - if (hash == appSettings.lockPassHash) { - lock.remainingAttempts = default_screen_attempts; - lock.state = gui::PinLock::State::VerifiedPin; - } - else if (lock.remainingAttempts > 0) { - lock.state = gui::PinLock::State::InvalidPin; - } - else { - lock.state = gui::PinLock::State::Blocked; - } + simLock = handlePasscodeParams(std::move(data)); + simLock.lockType = gui::PinLock::LockType::SimPin; - app->switchWindow(app::window::name::desktop_pin_lock); - } + auto onActivatedCallback = [this](const std::vector &data) { handlePasscodeChange(data); }; + switchToPinlockWindow(onActivatedCallback); } - void PinLockHandler::handleSimPinOrPuk(const std::vector &pin) + void PinLockHandler::handleSimBlocked(app::manager::actions::ActionParamsPtr &&data) { - auto sim = Store::GSM::SIM::SIM1; - sys::Bus::SendUnicast( - std::make_shared(sim, pin), ServiceCellular::serviceName, app); + auto params = static_cast(data.get()); + simLock = PinLock(parseSimCard(params->getSim()), + gui::PinLock::LockState::Blocked, + gui::PinLock::LockType::SimPin, + blocked_sim_attempts); + + auto lock = std::make_unique(simLock); + app->switchWindow(app::window::name::desktop_pin_lock, + gui::ShowMode::GUI_SHOW_INIT, + std::make_unique(std::move(lock))); } - void PinLockHandler::reloadScreenLock() + void PinLockHandler::handleCMEError(app::manager::actions::ActionParamsPtr &&data) const { - lock.type = gui::PinLock::LockType::Screen; - lock.state = gui::PinLock::State::EnterPin; + auto params = static_cast(data.get()); + + auto lock = std::make_unique(parseSimCard(params->getSim()), + PinLock::LockState::ErrorOccurred, + PinLock::LockType::SimPin, + params->getCMECode()); - unsigned int pinSize = appSettings.lockPassHash == 0 ? 0 : default_screen_pin_size; - lock.pinValue = std::vector(pinSize, 0); - lock.remainingAttempts = default_screen_attempts; + app->switchWindow(app::window::name::desktop_pin_lock, + gui::ShowMode::GUI_SHOW_INIT, + std::make_unique(std::move(lock))); + } + + void PinLockHandler::handlePasscode(const std::vector passcode) const + { + if (simLock.getLockType() == PinLock::LockType::SimPin) { + sys::Bus::SendUnicast( + std::make_shared(Store::GSM::SIM::SIM1, passcode), "ServiceCellular", app); + } + else if (simLock.getLockType() == PinLock::LockType::SimPuk) { + handlePasscodeChange(passcode); + } + } + void PinLockHandler::handlePasscodeChange(const std::vector passcode) const + { + auto lock = std::make_unique(simLock); + lock->lockState = PinLock::LockState::NewPasscodeRequired; + + lock->onActivatedCallback = [this, passcode](const std::vector &pin) { + handleNewPasscodeConfirmed(passcode, pin); + }; + + app->switchWindow(app::window::name::desktop_pin_lock, + gui::ShowMode::GUI_SHOW_INIT, + std::make_unique(std::move(lock))); + } + + void PinLockHandler::handleNewPasscodeConfirmed(const std::vector &passcode, + const std::vector &pin) const + { + if (simLock.getLockType() == PinLock::LockType::SimPin) { + sys::Bus::SendUnicast(std::make_shared(Store::GSM::SIM::SIM1, passcode, pin), + "ServiceCellular", + app); + } + else if (simLock.getLockType() == PinLock::LockType::SimPuk) { + sys::Bus::SendUnicast(std::make_shared(Store::GSM::SIM::SIM1, passcode, pin), + "ServiceCellular", + app); + } + } + + auto PinLockHandler::parseSimCard(Store::GSM::SIM sim) const noexcept -> PinLock::SimCard + { + if (sim == Store::GSM::SIM::SIM1) { + return gui::PinLock::SimCard::SIM1; + } + else if (sim == Store::GSM::SIM::SIM2) { + return gui::PinLock::SimCard::SIM2; + } + return gui::PinLock::SimCard::NoCard; } } // namespace gui diff --git a/module-apps/application-desktop/widgets/PinLockHandler.hpp b/module-apps/application-desktop/widgets/PinLockHandler.hpp index f2c66507cb1e232dbfa6b9c920f03044b5bebdfd..40a2b23a0058a730b038445fd7b4b1e783bf0644 100644 --- a/module-apps/application-desktop/widgets/PinLockHandler.hpp +++ b/module-apps/application-desktop/widgets/PinLockHandler.hpp @@ -4,9 +4,12 @@ #pragma once #include "PinLock.hpp" -#include #include "Interface/SettingsRecord.hpp" + +#include +#include + namespace app { class ApplicationDesktop; @@ -19,19 +22,39 @@ namespace gui app::ApplicationDesktop *app = nullptr; const SettingsRecord &appSettings; - void parseSimCard(CellularSimResponseMessage *msg); - void parseSimState(CellularSimResponseMessage *msg); - void parseAttemptsAndPinSize(CellularSimResponseMessage *msg); + auto parseSimCard(Store::GSM::SIM sim) const noexcept -> PinLock::SimCard; - void handleScreenPin(const std::vector &pin); - void handleSimPinOrPuk(const std::vector &pin); + void handlePasscode(const std::vector passcode) const; + void handlePasscodeChange(const std::vector passcode) const; + void handleNewPasscodeConfirmed(const std::vector &passcode, + const std::vector &pin) const; + auto handlePasscodeParams(app::manager::actions::ActionParamsPtr &&data) const -> gui::PinLock; + + void switchToPinlockWindow(std::function &)> onLockActivatedCallback); public: PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings); void reloadScreenLock(); - auto handle(CellularSimResponseMessage *msg) -> bool; - void handle(const std::vector &pin); - gui::PinLock lock; + void handleScreenPin(const std::vector &pin); + void handleScreenConfirm(); + void handlePinRequest(app::manager::actions::ActionParamsPtr &&data); + void handlePukRequest(app::manager::actions::ActionParamsPtr &&data); + void handlePinChangeRequest(app::manager::actions::ActionParamsPtr &&data); + + void handleSimBlocked(app::manager::actions::ActionParamsPtr &&data); + void handleCMEError(app::manager::actions::ActionParamsPtr &&data) const; + + [[nodiscard]] bool isScreenLocked() const noexcept + { + return screenLock.getState() != PinLock::LockState::Unlocked; + } + void lockScreen() noexcept + { + screenLock.lockState = PinLock::LockState::PasscodeRequired; + } + + gui::PinLock screenLock; + gui::PinLock simLock; }; } // namespace gui diff --git a/module-apps/application-desktop/windows/DesktopMainWindow.cpp b/module-apps/application-desktop/windows/DesktopMainWindow.cpp index 5f6f9d6b07284fbf920e4e8e65da3516c7dc0ee3..b7fc04bc0fdacbd6520c5d4902c09107c91b03b0 100644 --- a/module-apps/application-desktop/windows/DesktopMainWindow.cpp +++ b/module-apps/application-desktop/windows/DesktopMainWindow.cpp @@ -89,9 +89,7 @@ namespace gui void DesktopMainWindow::setVisibleState() { auto app = getAppDesktop(); - - if (app->lockHandler.lock.isLocked() && app->lockHandler.lock.getLockType() == PinLock::LockType::Screen) { - + if (app->lockHandler.isScreenLocked()) { bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_desktop_unlock")); bottomBar->setActive(BottomBar::Side::LEFT, false); bottomBar->setActive(BottomBar::Side::RIGHT, false); @@ -103,12 +101,6 @@ namespace gui sys::Bus::SendUnicast( std::make_shared(), service::name::service_time, application); } - else if (app->lockHandler.lock.isLocked()) { - application->switchWindow(app::window::name::desktop_pin_lock); - - sys::Bus::SendUnicast( - std::make_shared(), service::name::service_time, application); - } else { topBar->setActive(TopBar::Elements::LOCK, false); @@ -135,36 +127,47 @@ namespace gui // check if there was a signal to lock the pone due to inactivity. if ((data != nullptr) && (data->getDescription() == "LockPhoneData")) { auto app = getAppDesktop(); - if (app->lockHandler.lock.isLocked()) { + if (app->lockHandler.isScreenLocked()) { return; } - auto *lockData = dynamic_cast(data); lockTimeoutApplilcation = lockData->getPreviousApplication(); - application->setSuspendFlag(true); } + + if (mode == ShowMode::GUI_SHOW_RETURN) { + auto lock = getScreenLock(); + if (lock->getState() == PinLock::LockState::Unlocked) { + setVisibleState(); + return; + } + switchToPinLockWindow(std::move(lock)); + } + setVisibleState(); } bool DesktopMainWindow::processLongPressEvent(const InputEvent &inputEvent) { - auto *app = getAppDesktop(); + auto app = getAppDesktop(); - if (inputEvent.is(KeyCode::KEY_PND) && (!app->lockHandler.lock.isLocked())) { - app->lockHandler.lock.lock(); - setVisibleState(); - application->setSuspendFlag(true); - return true; + if (!app->lockHandler.isScreenLocked()) { + if (inputEvent.is(KeyCode::KEY_PND)) { + app->lockHandler.lockScreen(); + setVisibleState(); + application->setSuspendFlag(true); + return true; + } + // long press of '0' key is translated to '+' + else if (inputEvent.is(KeyCode::KEY_0)) { + return app::prepareCall(application, "+"); + } } - else if (inputEvent.is(KeyCode::KEY_RF)) { + + if (inputEvent.is(KeyCode::KEY_RF)) { application->switchWindow("PowerOffWindow"); return true; } - // long press of '0' key is translated to '+' - else if (inputEvent.is(KeyCode::KEY_0)) { - return app::prepareCall(application, "+"); - } // check if any of the lower inheritance onInput methods catch the event return AppWindow::onInput(inputEvent); } @@ -195,18 +198,16 @@ namespace gui if (enter_cache.cached() && inputEvent.is(KeyCode::KEY_PND)) { // if interval between enter and pnd keys is less than time defined for unlocking // display pin lock screen or simply refresh current window to update labels - std::unique_ptr data = std::make_unique(LockPhoneData::Request::Pin); - // if there was no application on to before closing proceed normally to pin protection - if (lockTimeoutApplilcation.empty()) { - application->switchWindow(app::window::name::desktop_pin_lock, std::move(data)); - return true; - } - else { - data->setPrevApplication(lockTimeoutApplilcation); - lockTimeoutApplilcation = ""; - application->switchWindow(app::window::name::desktop_pin_lock, std::move(data)); + + auto lock = getScreenLock(); + // if there is no pin, + if (lock->getMaxPinSize() == 0) { + lock->verify(); return true; } + + switchToPinLockWindow(std::move(lock)); + return true; } else if (enter_cache.storeEnter(inputEvent)) { return true; @@ -227,7 +228,7 @@ namespace gui return processLongPressEvent(inputEvent); } else if (inputEvent.isShortPress()) { - if (app->lockHandler.lock.isLocked()) { + if (app->lockHandler.isScreenLocked()) { return processShortPressEventOnLocked(inputEvent); } else { @@ -343,4 +344,39 @@ namespace gui assert(app); return app; } + + auto DesktopMainWindow::getScreenLock() -> std::unique_ptr + { + auto lock = std::make_unique(getAppDesktop()->lockHandler.screenLock); + auto app = getAppDesktop(); + if (lock->getState() == PinLock::LockState::PasscodeRequired) { + lock->onActivatedCallback = [app](const std::vector &data) { + app->lockHandler.handleScreenPin(data); + app->switchWindow(app::window::name::desktop_main_window, ShowMode::GUI_SHOW_RETURN); + }; + } + else if (lock->getState() == PinLock::LockState::PasscodeInvalidRetryRequired) { + lock->onActivatedCallback = [app](const std::vector &) { + app->lockHandler.screenLock.consumeState(); + app->switchWindow(app::window::name::desktop_main_window, ShowMode::GUI_SHOW_RETURN); + }; + } + else if (lock->getState() == PinLock::LockState::Blocked) { + lock->onActivatedCallback = [app](const std::vector &) { + app->switchWindow(app::window::name::desktop_main_window, ShowMode::GUI_SHOW_INIT); + }; + } + return lock; + } + + void DesktopMainWindow::switchToPinLockWindow(std::unique_ptr &&lock) + { + auto data = std::make_unique(std::move(lock)); + if (!lockTimeoutApplilcation.empty()) { + // if there was no application on to before closing proceed normally to pin protection + data->setPrevApplication(lockTimeoutApplilcation); + lockTimeoutApplilcation.clear(); + } + application->switchWindow(app::window::name::desktop_pin_lock, std::move(data)); + } } /* namespace gui */ diff --git a/module-apps/application-desktop/windows/DesktopMainWindow.hpp b/module-apps/application-desktop/windows/DesktopMainWindow.hpp index 8c5bf85a00516a14e117543d737de59ca50028d4..3dbcf03a761364de8fb0cb11dd7cdb465855d042 100644 --- a/module-apps/application-desktop/windows/DesktopMainWindow.hpp +++ b/module-apps/application-desktop/windows/DesktopMainWindow.hpp @@ -17,6 +17,7 @@ namespace app namespace gui { class NotificationsBox; + class PinLock; class DesktopMainWindow : public AppWindow { @@ -69,6 +70,9 @@ namespace gui bool processLongPressEvent(const InputEvent &inputEvent); bool processShortPressEventOnUnlocked(const InputEvent &inputEvent); bool processShortPressEventOnLocked(const InputEvent &inputEvent); + + auto getScreenLock() -> std::unique_ptr; + void switchToPinLockWindow(std::unique_ptr &&data); app::ApplicationDesktop *getAppDesktop() const; public: diff --git a/module-apps/application-desktop/windows/PinLockBaseWindow.cpp b/module-apps/application-desktop/windows/PinLockBaseWindow.cpp index 426d110fa017fb7bf8f19060a4a4b0d78d8e897c..ba70ef4ed4f24bbd1ecb73f0a698c050f76e67da 100644 --- a/module-apps/application-desktop/windows/PinLockBaseWindow.cpp +++ b/module-apps/application-desktop/windows/PinLockBaseWindow.cpp @@ -47,24 +47,28 @@ namespace gui infoText->setVisible(true); infoText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top)); } - void PinLockBaseWindow::buildPinLabels(gui::Label *labelsBox, unsigned int pinSize, unsigned int singleLabelWidth) + void PinLockBaseWindow::buildPinLabels(std::function itemBuilder, + unsigned int pinSize, + unsigned int offsetX, + unsigned int offsetY, + unsigned int boxWidth) { - if (pinSize * singleLabelWidth > labelsBox->getWidth()) { - singleLabelWidth = labelsBox->getWidth() / pinSize; + pinLabelsBox = new gui::HBox(this, offsetX, offsetY, boxWidth, lock_style::label_size); + pinLabelsBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center)); + + if (pinSize == 0) { + return; } - const uint32_t pinLabelSpacing = (labelsBox->getWidth() - pinSize * singleLabelWidth) / (pinSize - 1); - uint32_t pinLabelX = 0; for (uint32_t i = 0; i < pinSize; i++) { - gui::Label *label = new gui::Label(labelsBox, pinLabelX, 0, singleLabelWidth, lock_style::label_size); + auto label = itemBuilder(); label->setFilled(false); label->setBorderColor(gui::ColorFullBlack); label->setPenWidth(2); - label->setFont(style::window::font::largelight); - label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Bottom)); + label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center)); label->setVisible(true); - this->pinLabels.push_back(label); - pinLabelX += singleLabelWidth + pinLabelSpacing; + label->activeItem = false; + pinLabelsBox->addWidget(label); } } void PinLockBaseWindow::buildImages(const std::string &lockImg, const std::string &infoImg) @@ -88,10 +92,4 @@ namespace gui { bottomBar->setText(side, txt, false); } - void PinLockBaseWindow::clearPinLabels() - { - for (auto label : pinLabels) { - label->clear(); - } - } } // namespace gui diff --git a/module-apps/application-desktop/windows/PinLockBaseWindow.hpp b/module-apps/application-desktop/windows/PinLockBaseWindow.hpp index ed4c52f9c618373b76a686eaa0e255d55780ed6f..753e0f3127b9ee58b28e8a1ed0759f037bb2c6b8 100644 --- a/module-apps/application-desktop/windows/PinLockBaseWindow.hpp +++ b/module-apps/application-desktop/windows/PinLockBaseWindow.hpp @@ -16,25 +16,27 @@ namespace gui class PinLockBaseWindow : public AppWindow { public: - PinLockBaseWindow(app::Application *app, std::string name, PinLock &lock) : AppWindow(app, name), lock(lock) + PinLockBaseWindow(app::Application *app, std::string name) : AppWindow(app, name) {} void build(); void buildInfoText(unsigned int textHight); - void buildPinLabels(gui::Label *labelBox, unsigned int pinSize, unsigned int singleLabelWidth); + void buildPinLabels(std::function itemBuilder, + unsigned int pinSize, + unsigned int offsetX, + unsigned int offsetY, + unsigned int boxWidth); void buildImages(const std::string &lockImg, const std::string &infoImg); void setBottomBarWidgetsActive(bool left, bool center, bool right); void setImagesVisible(bool lockImg, bool infoImg); void setBottomBarWidgetText(BottomBar::Side side, const UTF8 &txt); - void clearPinLabels(); gui::Label *titleLabel = nullptr; gui::Text *infoText = nullptr; - gui::Label *pinLabel = nullptr; - std::vector pinLabels; gui::Image *lockImage = nullptr; gui::Image *infoImage = nullptr; + gui::HBox *pinLabelsBox = nullptr; - PinLock &lock; + std::unique_ptr lock = nullptr; private: void buildBottomBar(); diff --git a/module-apps/application-desktop/windows/PinLockBox.hpp b/module-apps/application-desktop/windows/PinLockBox.hpp index 2168e013197dae155805880eda91941e13ad0850..78c520e49678a66c760df416c9ba8dee92816a42 100644 --- a/module-apps/application-desktop/windows/PinLockBox.hpp +++ b/module-apps/application-desktop/windows/PinLockBox.hpp @@ -10,12 +10,27 @@ namespace gui class PinLockBox { public: - virtual void popChar(uint32_t charNum) = 0; - virtual void putChar(uint32_t charNum) = 0; + enum class EnterPasscodeType + { + ProvidePasscode, + ProvideNewPasscode, + ConfirmNewPasscode + }; - virtual void setVisibleStateEnterPin() = 0; + enum class PasscodeErrorType + { + InvalidPasscode, + NewPasscodeConfirmFailed, + UnhandledError + }; + + virtual void popChar(unsigned int charNum) = 0; + virtual void putChar(unsigned int charNum) = 0; + virtual void clear() = 0; + + virtual void setVisibleStateEnterPin(EnterPasscodeType type) = 0; virtual void setVisibleStateVerifiedPin() = 0; - virtual void setVisibleStateInvalidPin() = 0; + virtual void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) = 0; virtual void setVisibleStateBlocked() = 0; virtual void buildLockBox(unsigned int pinSize) = 0; diff --git a/module-apps/application-desktop/windows/PinLockWindow.cpp b/module-apps/application-desktop/windows/PinLockWindow.cpp index 8315399f65ebd01cf6993d2e1a47dd8b1fbab0db..90a395a1671001f29461a168a1d668697be0f9b8 100644 --- a/module-apps/application-desktop/windows/PinLockWindow.cpp +++ b/module-apps/application-desktop/windows/PinLockWindow.cpp @@ -19,8 +19,8 @@ namespace gui { - PinLockWindow::PinLockWindow(app::Application *app, const std::string &window_name, PinLock &lock) - : PinLockBaseWindow(app, window_name, lock), this_window_name(window_name) + PinLockWindow::PinLockWindow(app::Application *app, const std::string &window_name) + : PinLockBaseWindow(app, window_name), this_window_name(window_name) { buildInterface(); } @@ -32,14 +32,11 @@ namespace gui buildInterface(); // set state focusItem = nullptr; - setVisibleState(lock.getState()); } void PinLockWindow::buildInterface() { AppWindow::buildInterface(); PinLockBaseWindow::build(); - buildPinLockBox(); - LockBox->buildLockBox(lock.getPinSize()); } void PinLockWindow::destroyInterface() @@ -54,94 +51,127 @@ namespace gui lockImage = nullptr; infoImage = nullptr; infoText = nullptr; - pinLabel = nullptr; - pinLabels.clear(); + pinLabelsBox = nullptr; } - void PinLockWindow::setVisibleState(const PinLock::State state) + void PinLockWindow::setVisibleState(const PinLock::LockState state) { - if (state == PinLock::State::EnterPin) { - LockBox->setVisibleStateEnterPin(); + if (state == PinLock::LockState::PasscodeRequired) { + currentPasscodeType = PinLockBox::EnterPasscodeType::ProvidePasscode; + LockBox->setVisibleStateEnterPin(currentPasscodeType); } - else if (state == PinLock::State::VerifiedPin) { - LockBox->setVisibleStateVerifiedPin(); + else if (state == PinLock::LockState::PasscodeInvalidRetryRequired) { + LockBox->setVisibleStateInvalidPin(PinLockBox::PasscodeErrorType::InvalidPasscode, lock->getValue()); } - else if (state == PinLock::State::InvalidPin) { - LockBox->setVisibleStateInvalidPin(); - } - else if (state == PinLock::State::Blocked) { + else if (state == PinLock::LockState::Blocked) { LockBox->setVisibleStateBlocked(); } + else if (state == PinLock::LockState::NewPasscodeRequired) { + LockBox->setVisibleStateEnterPin(currentPasscodeType); + } + else if (state == PinLock::LockState::NewPasscodeInvalid) { + LockBox->setVisibleStateInvalidPin(PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed, + lock->getValue()); + } + else if (state == PinLock::LockState::ErrorOccurred) { + LockBox->setVisibleStateInvalidPin(PinLockBox::PasscodeErrorType::UnhandledError, lock->getValue()); + } application->refreshWindow(RefreshModes::GUI_REFRESH_FAST); } void PinLockWindow::onBeforeShow(ShowMode mode, SwitchData *data) { + if (mode == ShowMode::GUI_SHOW_INIT) { + rebuild(); + } if (auto lockData = dynamic_cast(data)) { + assert(lockData); lockTimeoutApplication = lockData->getPreviousApplication(); + lock = lockData->getLock(); + assert(lock); + + buildPinLockBox(); + LockBox->buildLockBox(lock->getMaxPinSize()); + + auto state = lock->getState(); + if (state == PinLock::LockState::PasscodeRequired) { + currentPasscodeType = PinLockBox::EnterPasscodeType::ProvidePasscode; + } + else if (state == PinLock::LockState::NewPasscodeRequired) { + currentPasscodeType = PinLockBox::EnterPasscodeType::ProvideNewPasscode; + } + setVisibleState(lock->getState()); } - if (lock.unlock()) { - setVisibleState(PinLock::State::VerifiedPin); - application->switchWindow(gui::name::window::main_window); - } - setVisibleState(lock.getState()); } bool PinLockWindow::onInput(const InputEvent &inputEvent) { - auto state = lock.getState(); - if (!inputEvent.isShortPress() || state == PinLock::State::VerifiedPin) { + auto state = lock->getState(); + if (!inputEvent.isShortPress()) { return AppWindow::onInput(inputEvent); } // accept only LF, enter, RF, #, and numeric values; - if (inputEvent.keyCode == KeyCode::KEY_LF && bottomBar->isActive(BottomBar::Side::LEFT)) { + if (inputEvent.is(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) { app::manager::Controller::switchApplication( application, app::name_phonebook, gui::window::name::ice_contacts, nullptr); return true; } - else if (inputEvent.keyCode == KeyCode::KEY_RF && bottomBar->isActive(BottomBar::Side::RIGHT)) { - if (state == PinLock::State::EnterPin) { - lock.clearAttempt(); - clearPinLabels(); + else if (inputEvent.is(KeyCode::KEY_RF) && bottomBar->isActive(BottomBar::Side::RIGHT)) { + if (state == PinLock::LockState::PasscodeRequired || state == PinLock::LockState::NewPasscodeRequired) { + lock->clearAttempt(); } - else if (state == PinLock::State::InvalidPin) { - LockBox->setVisibleStateInvalidPin(); - lock.consumeInvalidPinState(); + else if (state == PinLock::LockState::PasscodeInvalidRetryRequired) { + lock->consumeState(); } application->switchWindow(gui::name::window::main_window); return true; } - else if (inputEvent.keyCode == KeyCode::KEY_PND) { - if (state == PinLock::State::EnterPin) { - lock.popChar(); - LockBox->popChar(lock.getCharCount()); + else if (inputEvent.is(KeyCode::KEY_PND)) { + if (state == PinLock::LockState::PasscodeRequired || state == PinLock::LockState::NewPasscodeRequired) { + lock->popChar(); + LockBox->popChar(lock->getCharCount()); + bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify()); return true; } } else if (0 <= gui::toNumeric(inputEvent.keyCode) && gui::toNumeric(inputEvent.keyCode) <= 9) { - if (state == PinLock::State::EnterPin && lock.canPut()) { - LockBox->putChar(lock.getCharCount()); - lock.putNextChar(gui::toNumeric(inputEvent.keyCode)); - if (lock.getLockType() == PinLock::LockType::Screen) { - lock.verifyPin(); - } - else if (!lock.canPut()) { - bottomBar->setActive(BottomBar::Side::CENTER, true); - } + if ((state == PinLock::LockState::PasscodeRequired || state == PinLock::LockState::NewPasscodeRequired) && + lock->canPut()) { + LockBox->putChar(lock->getCharCount()); + lock->putNextChar(gui::toNumeric(inputEvent.keyCode)); + bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify()); return true; } } - else if (inputEvent.keyCode == KeyCode::KEY_ENTER && bottomBar->isActive(BottomBar::Side::CENTER)) { - if (state == PinLock::State::InvalidPin) { - lock.consumeInvalidPinState(); - application->switchWindow(this_window_name); + else if (inputEvent.is(KeyCode::KEY_ENTER) && bottomBar->isActive(BottomBar::Side::CENTER)) { + if (state == PinLock::LockState::NewPasscodeInvalid) { + lock->consumeState(); + setVisibleState(lock->getState()); + return true; } - else if (state == PinLock::State::EnterPin) { - lock.verifyPin(); + else if (currentPasscodeType == PinLockBox::EnterPasscodeType::ProvideNewPasscode) { + buffer = lock->getPin(); + lock->clearAttempt(); + LockBox->clear(); + + currentPasscodeType = PinLockBox::EnterPasscodeType::ConfirmNewPasscode; + setVisibleState(lock->getState()); + return true; } - else if (state == PinLock::State::Blocked) { - application->switchWindow(gui::name::window::main_window); + else if (currentPasscodeType == PinLockBox::EnterPasscodeType::ConfirmNewPasscode) { + if (buffer == lock->getPin()) { + lock->verify(); + } + else { + currentPasscodeType = PinLockBox::EnterPasscodeType::ProvideNewPasscode; + lock->clearAttempt(); + lock->setNewPasscodeInvalidState(); + LockBox->clear(); + setVisibleState(lock->getState()); + } + return true; } + lock->verify(); return true; } // check if any of the lower inheritance onInput methods catch the event @@ -150,14 +180,14 @@ namespace gui void PinLockWindow::buildPinLockBox() { - auto lockType = lock.getLockType(); + auto lockType = lock->getLockType(); if (lockType == PinLock::LockType::Screen) { LockBox = std::make_unique(this); } - else if (lockType == PinLock::LockType::PUK) { + else if (lockType == PinLock::LockType::SimPuk) { LockBox = std::make_unique(this); } - else if (lockType == PinLock::LockType::SIM) { + else if (lockType == PinLock::LockType::SimPin) { LockBox = std::make_unique(this); } assert(LockBox != nullptr); diff --git a/module-apps/application-desktop/windows/PinLockWindow.hpp b/module-apps/application-desktop/windows/PinLockWindow.hpp index f0dc1ec72d51694597faa6cc9188a79be8570193..5afcf3ad14eb64b557a5371c71277f0a79b13e26 100644 --- a/module-apps/application-desktop/windows/PinLockWindow.hpp +++ b/module-apps/application-desktop/windows/PinLockWindow.hpp @@ -19,15 +19,18 @@ namespace gui const std::string this_window_name; std::string lockTimeoutApplication = ""; std::unique_ptr LockBox = nullptr; - PinLock::LockType currentLock = PinLock::LockType::Unknown; + PinLockBox::EnterPasscodeType currentPasscodeType = PinLockBox::EnterPasscodeType::ProvidePasscode; + + std::vector buffer; + std::function &)> callbackBuffer = nullptr; // method hides or show widgets and sets bars according to provided state - void setVisibleState(const PinLock::State state); + void setVisibleState(const PinLock::LockState state); void buildPinLockBox(); void invalidate() noexcept; public: - PinLockWindow(app::Application *app, const std::string &window_name, PinLock &lock); + PinLockWindow(app::Application *app, const std::string &window_name); void onBeforeShow(ShowMode mode, SwitchData *data) override; bool onInput(const InputEvent &inputEvent) override; diff --git a/module-apps/application-desktop/windows/PukLockBox.cpp b/module-apps/application-desktop/windows/PukLockBox.cpp index d3ba950abbb879908016383e7ffa71636bce0548..3e96a1204854e0ca4817809f351cd955a3a8c37e 100644 --- a/module-apps/application-desktop/windows/PukLockBox.cpp +++ b/module-apps/application-desktop/windows/PukLockBox.cpp @@ -15,42 +15,58 @@ namespace lock_style = style::window::pin_lock; namespace gui { - void PukLockBox::popChar(uint32_t charNum) + void PukLockBox::popChar(unsigned int charNum) { - LockWindow->pinLabels[charNum]->clear(); + rebuildPinLabels(charNum); } - void PukLockBox::putChar(uint32_t charNum) + void PukLockBox::putChar(unsigned int charNum) { - LockWindow->pinLabels[charNum]->setText("*"); + rebuildPinLabels(++charNum); } void PukLockBox::buildLockBox(unsigned int pinSize) { LockWindow->buildImages("pin_lock", "pin_lock_info"); LockWindow->buildInfoText(lock_style::info_text_h_puk); - buildPinLabels(pinSize); + buildPinLabels(0); } void PukLockBox::buildPinLabels(unsigned int pinSize) { - // labels with stars for displaying entered digits - const uint32_t pinLabelWidth = style::window_width - 2 * lock_style::pin_label_x; - LockWindow->pinLabel = new gui::Label( - LockWindow, lock_style::pin_label_x, lock_style::pin_label_y, pinLabelWidth, lock_style::label_size); - LockWindow->pinLabel->setEdges(RectangleEdge::Bottom); - - LockWindow->buildPinLabels(LockWindow->pinLabel, pinSize, lock_style::label_size); - for (auto label : LockWindow->pinLabels) { - label->setEdges(RectangleEdge::None); - } + auto itemBuilder = []() { + auto label = new gui::Image("dot_12px_hard_alpha_W_G"); + return label; + }; + + LockWindow->buildPinLabels(itemBuilder, + pinSize, + lock_style::pin_label_x, + lock_style::pin_label_y, + style::window_width - 2 * lock_style::pin_label_x); + LockWindow->pinLabelsBox->setEdges(RectangleEdge::Bottom); } - void PukLockBox::setVisibleStateEnterPin() + + void PukLockBox::rebuildPinLabels(unsigned int pinSize) { - LockWindow->clearPinLabels(); - LockWindow->pinLabel->setVisible(true); + LockWindow->pinLabelsBox->erase(); + buildPinLabels(pinSize); + } + void PukLockBox::setVisibleStateEnterPin(EnterPasscodeType type) + { + LockWindow->pinLabelsBox->setVisible(true); LockWindow->infoText->clear(); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_blocked")); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_puk")); + + switch (type) { + case PinLockBox::EnterPasscodeType::ProvidePasscode: + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_blocked")); + LockWindow->infoText->addText("\n"); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_puk")); + break; + case PinLockBox::EnterPasscodeType::ProvideNewPasscode: + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_enter_pin")); + break; + case PinLockBox::EnterPasscodeType::ConfirmNewPasscode: + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_confirm_pin")); + } LockWindow->infoText->setVisible(true); LockWindow->setImagesVisible(true, false); @@ -58,43 +74,52 @@ namespace gui } void PukLockBox::setVisibleStateVerifiedPin() { - LockWindow->clearPinLabels(); - LockWindow->pinLabel->setVisible(false); + LockWindow->pinLabelsBox->setVisible(false); LockWindow->infoText->setVisible(false); } - void PukLockBox::setVisibleStateInvalidPin() + void PukLockBox::setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) { - LockWindow->clearPinLabels(); - LockWindow->pinLabel->setVisible(false); - + LockWindow->pinLabelsBox->setVisible(false); LockWindow->infoText->clear(); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_wrong_puk")); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_you_have")); - LockWindow->infoText->addText(" "); - LockWindow->infoText->addText(std::to_string(LockWindow->lock.getRemainingAttempts())); - LockWindow->infoText->addText(" "); - if (LockWindow->lock.getRemainingAttempts() > 1) { - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural")); - } - else { - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular")); - LockWindow->infoText->addText("\n\n"); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning1")); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning2")); + switch (type) { + case PinLockBox::PasscodeErrorType::InvalidPasscode: + + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_wrong_puk")); LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning3")); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_you_have")); + LockWindow->infoText->addText(" "); + LockWindow->infoText->addText(std::to_string(value)); + LockWindow->infoText->addText(" "); + + if (value > 1) { + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural")); + } + else { + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular")); + LockWindow->infoText->addText("\n\n"); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning1")); + LockWindow->infoText->addText("\n"); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning2")); + LockWindow->infoText->addText("\n"); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_warning3")); + } + break; + case PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed: + LockWindow->infoText->setText(utils::localize.get("app_desktop_sim_wrong_pin")); + break; + case PinLockBox::PasscodeErrorType::UnhandledError: + LOG_ERROR("No use case for UnhandledError in PukLockBox"); + break; } - LockWindow->infoText->setVisible(true); + LockWindow->infoText->setVisible(true); LockWindow->setImagesVisible(false, true); LockWindow->setBottomBarWidgetsActive(true, true, false); } void PukLockBox::setVisibleStateBlocked() { - LockWindow->pinLabel->setVisible(false); + LockWindow->pinLabelsBox->setVisible(false); LockWindow->infoText->clear(); LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_blocked_info1")); @@ -106,4 +131,8 @@ namespace gui LockWindow->setBottomBarWidgetsActive(true, false, false); } + void PukLockBox::clear() + { + rebuildPinLabels(0); + } } // namespace gui diff --git a/module-apps/application-desktop/windows/PukLockBox.hpp b/module-apps/application-desktop/windows/PukLockBox.hpp index c2ecaa955980226635bd2f29cde631adda7a6a3c..6ca72c0b98800c5048a16afb334beb07234c648e 100644 --- a/module-apps/application-desktop/windows/PukLockBox.hpp +++ b/module-apps/application-desktop/windows/PukLockBox.hpp @@ -4,7 +4,6 @@ #pragma once #include "PinLockBox.hpp" -#include "Label.hpp" namespace gui { @@ -21,15 +20,17 @@ namespace gui private: PinLockBaseWindow *LockWindow; - void popChar(uint32_t charNum) override final; - void putChar(uint32_t charNum) override final; + void popChar(unsigned int charNum) final; + void putChar(unsigned int charNum) final; + virtual void clear() final; - void setVisibleStateEnterPin() override final; - void setVisibleStateVerifiedPin() override final; - void setVisibleStateInvalidPin() override final; - void setVisibleStateBlocked() override final; + void setVisibleStateEnterPin(EnterPasscodeType type) final; + void setVisibleStateVerifiedPin() final; + void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final; + void setVisibleStateBlocked() final; - void buildLockBox(unsigned int pinSize) override final; + void buildLockBox(unsigned int pinSize) final; void buildPinLabels(unsigned int pinSize); + void rebuildPinLabels(unsigned int pinSize); }; } // namespace gui diff --git a/module-apps/application-desktop/windows/ScreenLockBox.cpp b/module-apps/application-desktop/windows/ScreenLockBox.cpp index 09cd2f1791f4643f93b6b8451b2657f0c55d461c..719107125fd321e33f7e0ffca0a7d4f2568619ee 100644 --- a/module-apps/application-desktop/windows/ScreenLockBox.cpp +++ b/module-apps/application-desktop/windows/ScreenLockBox.cpp @@ -14,13 +14,34 @@ namespace lock_style = style::window::pin_lock; namespace gui { - void ScreenLockBox::popChar(uint32_t charNum) + + ScreenLockBox::PinLabel::PinLabel(Item *parent, uint32_t w, uint32_t h) : HBox(parent, 0, 0, w, h) + {} + void ScreenLockBox::PinLabel::setVisibleState(bool isImageVisible) { - LockWindow->pinLabels[charNum]->clear(); + if (isImageVisible && image == nullptr) { + image = new gui::Image("dot_12px_hard_alpha_W_G"); + image->setVisible(true); + image->activeItem = false; + addWidget(image); + } + else if (!isImageVisible && image != nullptr) { + erase(image); + image = nullptr; + } } - void ScreenLockBox::putChar(uint32_t charNum) + + void ScreenLockBox::popChar(unsigned int charNum) { - LockWindow->pinLabels[charNum]->setText("*"); + if (charNum < pinLabels.size()) { + pinLabels[charNum]->setVisibleState(false); + } + } + void ScreenLockBox::putChar(unsigned int charNum) + { + if (charNum < pinLabels.size()) { + pinLabels[charNum]->setVisibleState(true); + } } void ScreenLockBox::buildLockBox(unsigned int pinSize) { @@ -30,20 +51,35 @@ namespace gui } void ScreenLockBox::buildPinLabels(unsigned int pinSize) { - // labels with stars for displaying entered digits - const uint32_t pinLabelWidth = style::window_width - 2 * lock_style::pin_label_x_screen; - LockWindow->pinLabel = new gui::Label( - LockWindow, lock_style::pin_label_x_screen, lock_style::pin_label_y, pinLabelWidth, lock_style::label_size); - LockWindow->pinLabel->setEdges(RectangleEdge::None); - - LockWindow->buildPinLabels(LockWindow->pinLabel, pinSize, lock_style::label_size_screen); - for (auto label : LockWindow->pinLabels) { - label->setEdges(RectangleEdge::Bottom); + constexpr auto pinLabelWidth = style::window::default_body_width; + pinLabels.clear(); + + if (pinSize == 0) { + return; + } + + unsigned int singleLabelWidth = lock_style::label_size; + unsigned int maxNoMarginsLabelsWidth = pinLabelWidth - pinSize * 2 * lock_style::label_margins; + + if (pinSize * singleLabelWidth > maxNoMarginsLabelsWidth) { + singleLabelWidth = maxNoMarginsLabelsWidth / pinSize; } + + auto itemBuilder = [this, singleLabelWidth]() { + auto label = new PinLabel(nullptr, singleLabelWidth, lock_style::label_size); + label->setEdges(RectangleEdge::Bottom); + label->setMargins(Margins(lock_style::label_margins, 0, lock_style::label_margins, 0)); + pinLabels.push_back(label); + return label; + }; + + LockWindow->buildPinLabels( + itemBuilder, pinSize, style::window::default_left_margin, lock_style::pin_label_y_screen, pinLabelWidth); + LockWindow->pinLabelsBox->setEdges(RectangleEdge::None); } - void ScreenLockBox::setVisibleStateEnterPin() + void ScreenLockBox::setVisibleStateEnterPin(EnterPasscodeType type) { - LockWindow->pinLabel->setVisible(true); + LockWindow->pinLabelsBox->setVisible(true); LockWindow->infoText->clear(); LockWindow->infoText->addText(utils::localize.get("app_desktop_screen_enter_passcode")); @@ -54,30 +90,42 @@ namespace gui } void ScreenLockBox::setVisibleStateVerifiedPin() { - LockWindow->clearPinLabels(); - LockWindow->pinLabel->setVisible(false); + clear(); + LockWindow->pinLabelsBox->setVisible(false); LockWindow->titleLabel->setVisible(false); } - void ScreenLockBox::setVisibleStateInvalidPin() + void ScreenLockBox::setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) { - LockWindow->clearPinLabels(); - LockWindow->pinLabel->setVisible(false); - + clear(); + LockWindow->pinLabelsBox->setVisible(false); + LockWindow->infoText->clear(); LockWindow->titleLabel->setVisible(true); - LockWindow->titleLabel->setText(utils::localize.get("app_desktop_screen_wrong_pin")); + switch (type) { + case PinLockBox::PasscodeErrorType::InvalidPasscode: + LockWindow->titleLabel->setText(utils::localize.get("app_desktop_screen_wrong_pin")); - LockWindow->infoText->clear(); - LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_screen_allowed_attempts"))); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(std::to_string(LockWindow->lock.getRemainingAttempts())); - LockWindow->infoText->setVisible(true); + LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_you_have"))); + LockWindow->infoText->addText(" "); + LockWindow->infoText->addText(std::to_string(value)); + LockWindow->infoText->addText(" "); + LockWindow->infoText->addText( + utils::localize.get(utils::localize.get("app_desktop_sim_attempt_left_plural"))); + break; + case PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed: + LockWindow->titleLabel->setText(utils::localize.get("app_desktop_screen_wrong_passcode")); + break; + case PinLockBox::PasscodeErrorType::UnhandledError: + LOG_ERROR("No use case for UnhandledError"); + break; + } + LockWindow->infoText->setVisible(true); LockWindow->setImagesVisible(false, true); LockWindow->setBottomBarWidgetsActive(false, true, true); } void ScreenLockBox::setVisibleStateBlocked() { - LockWindow->pinLabel->setVisible(false); + LockWindow->pinLabelsBox->setVisible(false); LockWindow->titleLabel->setVisible(false); LockWindow->infoText->clear(); @@ -87,4 +135,11 @@ namespace gui LockWindow->setImagesVisible(false, true); LockWindow->setBottomBarWidgetsActive(false, true, false); } + + void ScreenLockBox::clear() + { + for (unsigned i = 0; i < pinLabels.size(); i++) { + popChar(i); + } + } } // namespace gui diff --git a/module-apps/application-desktop/windows/ScreenLockBox.hpp b/module-apps/application-desktop/windows/ScreenLockBox.hpp index b00b2ee9eaaa999c1027084fa612a580f1818848..fb88316cea87acef8de9fdc577e079b88123ebf6 100644 --- a/module-apps/application-desktop/windows/ScreenLockBox.hpp +++ b/module-apps/application-desktop/windows/ScreenLockBox.hpp @@ -4,8 +4,8 @@ #pragma once #include "PinLockBox.hpp" -#include "Label.hpp" - +#include "BoxLayout.hpp" +#include "Image.hpp" namespace gui { class PinLockBaseWindow; @@ -20,16 +20,26 @@ namespace gui {} private: + struct PinLabel : public HBox + { + gui::Image *image = nullptr; + PinLabel(Item *parent, uint32_t w, uint32_t h); + void setVisibleState(bool isImageVisible); + }; + + std::vector pinLabels; + PinLockBaseWindow *LockWindow; - void popChar(uint32_t charNum) override final; - void putChar(uint32_t charNum) override final; + void popChar(unsigned int charNum) final; + void putChar(unsigned int charNum) final; + virtual void clear() final; - void setVisibleStateEnterPin() override final; - void setVisibleStateVerifiedPin() override final; - void setVisibleStateInvalidPin() override final; - void setVisibleStateBlocked() override final; + void setVisibleStateEnterPin(EnterPasscodeType type) final; + void setVisibleStateVerifiedPin() final; + void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final; + void setVisibleStateBlocked() final; - void buildLockBox(unsigned int pinSize) override final; + void buildLockBox(unsigned int pinSize) final; void buildPinLabels(unsigned int pinSize); }; } // namespace gui diff --git a/module-apps/application-desktop/windows/SimLockBox.cpp b/module-apps/application-desktop/windows/SimLockBox.cpp index 5c8acfb2a88b323f67e33506a047160cf7fdb000..c5ba913f50e9572f7a3ea6bde61f0a4270150a83 100644 --- a/module-apps/application-desktop/windows/SimLockBox.cpp +++ b/module-apps/application-desktop/windows/SimLockBox.cpp @@ -7,6 +7,9 @@ #include "application-desktop/widgets/PinLock.hpp" #include "application-desktop/data/AppDesktopStyle.hpp" #include "gui/widgets/Label.hpp" +#include "RichTextParser.hpp" +#include "FontManager.hpp" + #include #include @@ -15,50 +18,60 @@ namespace lock_style = style::window::pin_lock; namespace gui { - void SimLockBox::popChar(uint32_t charNum) + void SimLockBox::popChar(unsigned int charNum) { - LockWindow->pinLabels[charNum]->clear(); + rebuildPinLabels(charNum); } - void SimLockBox::putChar(uint32_t charNum) + void SimLockBox::putChar(unsigned int charNum) { - LockWindow->pinLabels[charNum]->setText("*"); + rebuildPinLabels(++charNum); } void SimLockBox::buildLockBox(unsigned int pinSize) { LockWindow->buildImages("pin_lock", "pin_lock_info"); LockWindow->buildInfoText(lock_style::info_text_h_sim); - buildPinLabels(pinSize); + buildPinLabels(0); } void SimLockBox::buildPinLabels(unsigned int pinSize) { - // labels with stars for displaying entered digits - const uint32_t pinLabelWidth = style::window_width - 2 * lock_style::pin_label_x; - LockWindow->pinLabel = new gui::Label( - LockWindow, lock_style::pin_label_x, lock_style::pin_label_y, pinLabelWidth, lock_style::label_size); - LockWindow->pinLabel->setEdges(RectangleEdge::Bottom); - - LockWindow->buildPinLabels(LockWindow->pinLabel, pinSize, lock_style::label_size); - for (auto label : LockWindow->pinLabels) { - label->setEdges(RectangleEdge::None); - } + auto itemBuilder = []() { + auto label = new gui::Image("dot_12px_hard_alpha_W_G"); + return label; + }; + + LockWindow->buildPinLabels(itemBuilder, + pinSize, + lock_style::pin_label_x, + lock_style::pin_label_y, + style::window_width - 2 * lock_style::pin_label_x); + LockWindow->pinLabelsBox->setEdges(RectangleEdge::Bottom); } - void SimLockBox::setVisibleStateEnterPin() + + void SimLockBox::rebuildPinLabels(unsigned int pinSize) { - LockWindow->pinLabel->setVisible(true); + LockWindow->pinLabelsBox->erase(); + buildPinLabels(pinSize); + } + void SimLockBox::setVisibleStateEnterPin(EnterPasscodeType type) + { + LockWindow->pinLabelsBox->setVisible(true); LockWindow->infoText->clear(); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_to_unlock")); - LockWindow->infoText->addText(" "); - LockWindow->infoText->addText(LockWindow->lock.getLockInfo(PinLock::InfoName::LockName)); - LockWindow->infoText->addText(" "); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_card")); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText("( "); - LockWindow->infoText->addText(LockWindow->lock.getLockInfo(PinLock::InfoName::PhoneNum)); - LockWindow->infoText->addText(" )"); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_pin")); + + switch (type) { + case PinLockBox::EnterPasscodeType::ProvidePasscode: + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_to_unlock")); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_card")); + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_type_pin")); + break; + case PinLockBox::EnterPasscodeType::ProvideNewPasscode: + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_enter_pin")); + break; + case PinLockBox::EnterPasscodeType::ConfirmNewPasscode: + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_confirm_pin")); + break; + } LockWindow->infoText->setVisible(true); LockWindow->setImagesVisible(true, false); @@ -66,37 +79,51 @@ namespace gui } void SimLockBox::setVisibleStateVerifiedPin() { - LockWindow->clearPinLabels(); LockWindow->infoText->clear(); LockWindow->infoText->setVisible(false); - LockWindow->pinLabel->setVisible(false); + LockWindow->pinLabelsBox->setVisible(false); } - void SimLockBox::setVisibleStateInvalidPin() + void SimLockBox::setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) { - LockWindow->clearPinLabels(); - LockWindow->pinLabel->setVisible(false); + LockWindow->pinLabelsBox->setVisible(false); LockWindow->infoText->clear(); - LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_wrong_pin"))); - LockWindow->infoText->addText("\n"); - LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_you_have"))); - LockWindow->infoText->addText(" "); - LockWindow->infoText->addText(std::to_string(LockWindow->lock.getRemainingAttempts())); - LockWindow->infoText->addText(" "); - if (LockWindow->lock.getRemainingAttempts() > 1) { - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural")); + + switch (type) { + case PinLockBox::PasscodeErrorType::InvalidPasscode: + LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_wrong_pin"))); + LockWindow->infoText->addText("\n"); + LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_sim_you_have"))); + LockWindow->infoText->addText(" "); + LockWindow->infoText->addText(std::to_string(value)); + LockWindow->infoText->addText(" "); + if (value > 1) { + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_plural")); + } + else { + LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular")); + } + LockWindow->infoText->setVisible(true); + + LockWindow->setImagesVisible(false, true); + LockWindow->setBottomBarWidgetsActive(true, true, true); + break; + case PinLockBox::PasscodeErrorType::NewPasscodeConfirmFailed: + LockWindow->infoText->setText(utils::localize.get("app_desktop_sim_wrong_pin")); + break; + case PinLockBox::PasscodeErrorType::UnhandledError: { + TextFormat format(FontManager::getInstance().getFont(style::window::font::medium)); + text::RichTextParser rtParser; + auto parsedText = rtParser.parse(utils::localize.get("app_desktop_sim_cme_error"), &format); + LockWindow->infoText->setText(std::move(parsedText)); + LockWindow->infoText->addText(std::to_string(value)); + break; } - else { - LockWindow->infoText->addText(utils::localize.get("app_desktop_sim_attempt_left_singular")); } - LockWindow->infoText->setVisible(true); - - LockWindow->setImagesVisible(false, true); - LockWindow->setBottomBarWidgetsActive(true, true, true); } void SimLockBox::setVisibleStateBlocked() { - LockWindow->pinLabel->setVisible(false); + LockWindow->pinLabelsBox->setVisible(false); LockWindow->infoText->clear(); LockWindow->infoText->addText(utils::localize.get(utils::localize.get("app_desktop_puk_lock1"))); LockWindow->infoText->setVisible(true); @@ -104,4 +131,9 @@ namespace gui LockWindow->setImagesVisible(false, true); LockWindow->setBottomBarWidgetsActive(true, true, true); } + + void SimLockBox::clear() + { + rebuildPinLabels(0); + } } // namespace gui diff --git a/module-apps/application-desktop/windows/SimLockBox.hpp b/module-apps/application-desktop/windows/SimLockBox.hpp index 5f9a81879732a55c507c044a120a27fb5ac21e5d..3290409663fadcdae0d51791d4d0605395371748 100644 --- a/module-apps/application-desktop/windows/SimLockBox.hpp +++ b/module-apps/application-desktop/windows/SimLockBox.hpp @@ -4,7 +4,6 @@ #pragma once #include "PinLockBox.hpp" -#include "Label.hpp" namespace gui { @@ -21,15 +20,17 @@ namespace gui private: PinLockBaseWindow *LockWindow; - void popChar(uint32_t charNum) override final; - void putChar(uint32_t charNum) override final; + void popChar(unsigned int charNum) final; + void putChar(unsigned int charNum) final; + virtual void clear() final; - void setVisibleStateEnterPin() override final; - void setVisibleStateVerifiedPin() override final; - void setVisibleStateInvalidPin() override final; - void setVisibleStateBlocked() override final; + void setVisibleStateEnterPin(EnterPasscodeType type) final; + void setVisibleStateVerifiedPin() final; + void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final; + void setVisibleStateBlocked() final; - void buildLockBox(unsigned int pinSize) override final; + void buildLockBox(unsigned int pinSize) final; void buildPinLabels(unsigned int pinSize); + void rebuildPinLabels(unsigned int pinSize); }; } // namespace gui diff --git a/module-services/service-appmgr/CMakeLists.txt b/module-services/service-appmgr/CMakeLists.txt index a5a6b07b22067493ee6c3328a4371ee74b90478d..464287227ab431f2836d6c3fc9b48b478f889318 100644 --- a/module-services/service-appmgr/CMakeLists.txt +++ b/module-services/service-appmgr/CMakeLists.txt @@ -4,6 +4,7 @@ message( "${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}" ) set(SOURCES ApplicationManifest.cpp Controller.cpp + data/SimActionsParams.cpp model/ApplicationManager.cpp model/ApplicationHandle.cpp model/ApplicationsRegistry.cpp diff --git a/module-services/service-appmgr/data/SimActionsParams.cpp b/module-services/service-appmgr/data/SimActionsParams.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4a42be39142e2c4c8cd3b9a4f9c49f9cf821a6e --- /dev/null +++ b/module-services/service-appmgr/data/SimActionsParams.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +using namespace app::manager::actions; + +PasscodeParams::PasscodeParams(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName) + : sim{_sim}, attempts{_attempts}, passcodeName{std::move(_passcodeName)} +{} + +Store::GSM::SIM PasscodeParams::getSim() const noexcept +{ + return sim; +} +unsigned int PasscodeParams::getAttempts() const noexcept +{ + return attempts; +} +const std::string &PasscodeParams::getPasscodeName() const noexcept +{ + return passcodeName; +} + +SimStateParams::SimStateParams(Store::GSM::SIM _sim) : sim{_sim} +{} + +Store::GSM::SIM SimStateParams::getSim() const noexcept +{ + return sim; +} + +UnhandledCMEParams::UnhandledCMEParams(Store::GSM::SIM _sim, unsigned int _cmeCode) : sim{_sim}, cmeCode{_cmeCode} +{} + +Store::GSM::SIM UnhandledCMEParams::getSim() const noexcept +{ + return sim; +} +unsigned int UnhandledCMEParams::getCMECode() const noexcept +{ + return cmeCode; +} diff --git a/module-services/service-appmgr/model/ApplicationManager.cpp b/module-services/service-appmgr/model/ApplicationManager.cpp index b964c158578fdd43a112f2818cd1805f586332ec..75d9e7af2866b90ea308902a066e4080d8328781 100644 --- a/module-services/service-appmgr/model/ApplicationManager.cpp +++ b/module-services/service-appmgr/model/ApplicationManager.cpp @@ -260,6 +260,13 @@ namespace app::manager handleAction(actionMsg); return std::make_shared(); }); + + auto convertibleToActionHandler = [this](sys::Message *request) { return handleMessageAsAction(request); }; + connect(typeid(CellularSimRequestPinMessage), convertibleToActionHandler); + connect(typeid(CellularSimRequestPukMessage), convertibleToActionHandler); + connect(typeid(CellularUnlockSimMessage), convertibleToActionHandler); + connect(typeid(CellularBlockSimMessage), convertibleToActionHandler); + connect(typeid(CellularDisplayCMEMessage), convertibleToActionHandler); } sys::ReturnCodes ApplicationManager::SwitchPowerModeHandler(const sys::ServicePowerMode mode) @@ -643,6 +650,18 @@ namespace app::manager return true; } + auto ApplicationManager::handleMessageAsAction(sys::Message *request) -> std::shared_ptr + { + auto actionMsg = dynamic_cast(request); + if (!actionMsg) { + return std::make_shared(sys::ReturnCodes::Failure); + } + auto action = actionMsg->toAction(); + handleAction(action.get()); + + return std::make_shared(); + } + void ApplicationManager::onPhoneLocked() { #ifdef AUTO_PHONE_LOCK_ENABLED diff --git a/module-services/service-appmgr/service-appmgr/Actions.hpp b/module-services/service-appmgr/service-appmgr/Actions.hpp index 7ad0e8b8020e36133fed1eb81e7702e626afd129..a41b8afc71eb2799077899e7917b19810c3dacd4 100644 --- a/module-services/service-appmgr/service-appmgr/Actions.hpp +++ b/module-services/service-appmgr/service-appmgr/Actions.hpp @@ -24,8 +24,13 @@ namespace app::manager { Launch, Call, + RequestPin, + RequestPuk, + RequestPinChange, + UnlockSim, + BlockSim, + DisplayCMEError, UserAction // The last enumerator in the Action enum. - // All user-defined actions shall have values greater than UserAction. }; class ConvertibleToAction diff --git a/module-services/service-appmgr/service-appmgr/data/SimActionsParams.hpp b/module-services/service-appmgr/service-appmgr/data/SimActionsParams.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0c16744e3d8a822e6725f6336e6b091c1f0929b6 --- /dev/null +++ b/module-services/service-appmgr/service-appmgr/data/SimActionsParams.hpp @@ -0,0 +1,59 @@ +// 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 +#include + +namespace app::manager::actions +{ + /** Action parameters for + * RequestPinAction + * RequestPukAction + * ChangePinAction + */ + class PasscodeParams : public ActionParams + { + Store::GSM::SIM sim; + unsigned int attempts; + /// passcodeName stands for PIN1/PIN2 or PUK1/PUK2 type + std::string passcodeName; + + public: + PasscodeParams(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName); + + [[nodiscard]] Store::GSM::SIM getSim() const noexcept; + [[nodiscard]] unsigned int getAttempts() const noexcept; + [[nodiscard]] const std::string &getPasscodeName() const noexcept; + }; + + /** Action parameters for + * SimUnlockedAction + * SimBlockedAction + */ + class SimStateParams : public ActionParams + { + Store::GSM::SIM sim; + + public: + explicit SimStateParams(Store::GSM::SIM _sim); + + [[nodiscard]] Store::GSM::SIM getSim() const noexcept; + }; + + /** Action parameters for + * UnhandledCMEError + */ + class UnhandledCMEParams : public ActionParams + { + Store::GSM::SIM sim; + unsigned int cmeCode; + + public: + UnhandledCMEParams(Store::GSM::SIM _sim, unsigned int _cmeCode); + + [[nodiscard]] Store::GSM::SIM getSim() const noexcept; + [[nodiscard]] unsigned int getCMECode() const noexcept; + }; +} // namespace app::manager::actions diff --git a/module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp b/module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp index 3a69ba5496461d6c239b06757efacbc1cebeed55..bef2951caf79498de47afd6afbe255050977e086 100644 --- a/module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +++ b/module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp @@ -120,6 +120,7 @@ namespace app::manager auto handleDisplayLanguageChange(DisplayLanguageChangeRequest *msg) -> bool; auto handleInputLanguageChange(InputLanguageChangeRequest *msg) -> bool; auto handlePowerSavingModeInit() -> bool; + auto handleMessageAsAction(sys::Message *request) -> std::shared_ptr; void requestApplicationClose(ApplicationHandle &app, bool isCloseable); void onApplicationSwitch(ApplicationHandle &app, @@ -140,7 +141,6 @@ namespace app::manager // defined in settings database application // manager is sending signal to power manager and changing window to // the desktop window in the blocked state. - // Temporary solution - to be replaced with ActionsMiddleware. std::tuple pendingAction; }; diff --git a/module-services/service-cellular/service-cellular/CellularMessage.hpp b/module-services/service-cellular/service-cellular/CellularMessage.hpp index f894db7a9e3805f760d067162627e13552040498..f51aa7bbc8621e5d19c4d8484715cb06d04cf439 100644 --- a/module-services/service-cellular/service-cellular/CellularMessage.hpp +++ b/module-services/service-cellular/service-cellular/CellularMessage.hpp @@ -17,6 +17,10 @@ #include #include +#include +#include +#include + class CellularMessage : public sys::DataMessage { public: @@ -293,6 +297,172 @@ class CellularSimVerifyPinRequestMessage : public CellularSimMessage std::vector pukValue; }; +class CellularSimPasscodeRequest : public CellularMessage +{ + protected: + app::manager::actions::PasscodeParams params; + + CellularSimPasscodeRequest(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName) + : CellularMessage(MessageType::CellularSimResponse), params(_sim, _attempts, std::move(_passcodeName)) + {} +}; + +class CellularSimRequestPinMessage : public CellularSimPasscodeRequest, + public app::manager::actions::ConvertibleToAction +{ + public: + CellularSimRequestPinMessage(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName) + : CellularSimPasscodeRequest(_sim, _attempts, std::move(_passcodeName)) + {} + + [[nodiscard]] auto toAction() const -> std::unique_ptr + { + return std::make_unique( + sender, app::manager::actions::RequestPin, std::make_unique(params)); + } +}; + +class CellularSimRequestPukMessage : public CellularSimPasscodeRequest, + public app::manager::actions::ConvertibleToAction +{ + public: + CellularSimRequestPukMessage(Store::GSM::SIM _sim, unsigned int _attempts, std::string _passcodeName) + : CellularSimPasscodeRequest(_sim, _attempts, std::move(_passcodeName)) + {} + + [[nodiscard]] auto toAction() const -> std::unique_ptr + { + return std::make_unique( + sender, app::manager::actions::RequestPuk, std::make_unique(params)); + } +}; + +class CellularUnlockSimMessage : public CellularMessage, public app::manager::actions::ConvertibleToAction +{ + app::manager::actions::SimStateParams params; + + public: + CellularUnlockSimMessage(Store::GSM::SIM _sim) : CellularMessage(MessageType::CellularSimResponse), params(_sim) + {} + + [[nodiscard]] auto toAction() const -> std::unique_ptr + { + return std::make_unique( + sender, app::manager::actions::UnlockSim, std::make_unique(params)); + } +}; + +class CellularBlockSimMessage : public CellularMessage, public app::manager::actions::ConvertibleToAction +{ + app::manager::actions::SimStateParams params; + + public: + explicit CellularBlockSimMessage(Store::GSM::SIM _sim) + : CellularMessage(MessageType::CellularSimResponse), params(_sim) + {} + + [[nodiscard]] auto toAction() const -> std::unique_ptr + { + return std::make_unique( + sender, app::manager::actions::BlockSim, std::make_unique(params)); + } +}; + +class CellularDisplayCMEMessage : public CellularMessage, public app::manager::actions::ConvertibleToAction +{ + app::manager::actions::UnhandledCMEParams params; + + public: + CellularDisplayCMEMessage(Store::GSM::SIM _sim, unsigned int _cmeCode) + : CellularMessage(MessageType::CellularSimResponse), params(_sim, _cmeCode) + {} + + [[nodiscard]] auto toAction() const -> std::unique_ptr + { + return std::make_unique( + sender, + app::manager::actions::DisplayCMEError, + std::make_unique(params)); + } +}; + +class CellularSimDataMessage : public CellularMessage +{ + Store::GSM::SIM sim = Store::GSM::SIM::NONE; + + public: + explicit CellularSimDataMessage(Store::GSM::SIM _sim) : CellularMessage{MessageType::CellularSimResponse}, sim{_sim} + {} + [[nodiscard]] Store::GSM::SIM getSim() const noexcept + { + return sim; + } +}; + +class CellularSimPinDataMessage : public CellularSimDataMessage +{ + std::vector pinValue; + + public: + CellularSimPinDataMessage(Store::GSM::SIM _sim, std::vector _pinValue) + : CellularSimDataMessage{_sim}, pinValue{std::move(_pinValue)} + {} + + [[nodiscard]] const std::vector &getPin() const noexcept + { + return pinValue; + } +}; + +class CellularSimNewPinDataMessage : public CellularSimDataMessage +{ + std::vector oldPin; + std::vector newPin; + + public: + CellularSimNewPinDataMessage(Store::GSM::SIM _sim, + std::vector _oldPin, + std::vector _newPin) + : CellularSimDataMessage{_sim}, oldPin{std::move(_oldPin)}, newPin{std::move(_newPin)} + {} + + [[nodiscard]] const std::vector &getOldPin() const noexcept + { + return oldPin; + } + [[nodiscard]] const std::vector &getNewPin() const noexcept + { + return newPin; + } +}; + +class CellularSimPukDataMessage : public CellularSimDataMessage +{ + std::vector puk; + std::vector newPin; + + public: + CellularSimPukDataMessage(Store::GSM::SIM _sim, std::vector _puk, std::vector _newPin) + : CellularSimDataMessage{_sim}, puk{std::move(_puk)}, newPin{std::move(_newPin)} + {} + + [[nodiscard]] const std::vector &getPuk() const noexcept + { + return puk; + } + [[nodiscard]] const std::vector &getNewPin() const noexcept + { + return newPin; + } +}; + +class CellularSimAbortMessage : public CellularSimDataMessage +{ + public: + explicit CellularSimAbortMessage(Store::GSM::SIM _sim) : CellularSimDataMessage{_sim} + {} +}; + class CellularGetChannelMessage : public sys::DataMessage { public: diff --git a/module-services/service-desktop/ServiceDesktop.cpp b/module-services/service-desktop/ServiceDesktop.cpp index 474bf05c45b8d551f34bbc03b450337660136497..6892638d4a9ed3dac611d9dc892242cc9dce4829 100644 --- a/module-services/service-desktop/ServiceDesktop.cpp +++ b/module-services/service-desktop/ServiceDesktop.cpp @@ -4,6 +4,7 @@ #include "service-desktop/DesktopMessages.hpp" #include "service-desktop/ServiceDesktop.hpp" #include "service-desktop/WorkerDesktop.hpp" +#include "service-cellular/CellularMessage.hpp" #include "endpoints/factoryReset/FactoryReset.hpp" #include "endpoints/backup/BackupRestore.hpp" #include "endpoints/update/UpdateMuditaOS.hpp"