~aleteoryx/muditaos

25ba341e6cdfcc788bde7594b16536c7e6ff5312 — Przemyslaw Brudny 4 years ago c478d0a
[EGD-5884] Added Lock Screen popup handling

Moved lock screen window to popup. Split DesktopMainWindow into
two parts (popup and regular). Added LockPhoneHandler into
ApplicationManager.
50 files changed, 938 insertions(+), 398 deletions(-)

M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp
M module-apps/application-antenna/ApplicationAntenna.cpp
M module-apps/application-calculator/ApplicationCalculator.cpp
M module-apps/application-calendar/ApplicationCalendar.cpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-calllog/ApplicationCallLog.cpp
M module-apps/application-clock/ApplicationClock.cpp
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/CMakeLists.txt
M module-apps/application-desktop/windows/DesktopMainWindow.cpp
M module-apps/application-desktop/windows/DesktopMainWindow.hpp
M module-apps/application-desktop/windows/LockedInfoWindow.cpp
M module-apps/application-desktop/windows/Names.hpp
M module-apps/application-desktop/windows/PostUpdateWindow.cpp
M module-apps/application-desktop/windows/Reboot.hpp
M module-apps/application-desktop/windows/Update.cpp
M module-apps/application-meditation/ApplicationMeditation.cpp
M module-apps/application-messages/ApplicationMessages.cpp
M module-apps/application-music-player/ApplicationMusicPlayer.cpp
M module-apps/application-notes/ApplicationNotes.cpp
M module-apps/application-onboarding/ApplicationOnBoarding.cpp
M module-apps/application-phonebook/ApplicationPhonebook.cpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/locks/CMakeLists.txt
A module-apps/locks/data/LockMessages.hpp
A module-apps/locks/handlers/PhoneLockHandler.cpp
A module-apps/locks/handlers/PhoneLockHandler.hpp
A module-apps/locks/handlers/PhoneLockSubject.cpp
A module-apps/locks/handlers/PhoneLockSubject.hpp
M module-apps/locks/widgets/Lock.hpp
M module-apps/popups/CMakeLists.txt
M module-apps/popups/Popups.cpp
M module-apps/popups/Popups.hpp
R module-apps/{application-desktop/windows => popups}/PowerOffWindow.cpp
R module-apps/{application-desktop/windows => popups}/PowerOffWindow.hpp
M module-apps/popups/data/PopupRequestParams.hpp
A module-apps/popups/lock-popups/PhoneLockedInfoWindow.cpp
R module-apps/{application-desktop/windows/LockedInfoWindow => popups/lock-popups/PhoneLockedInfoWindow}.hpp
A module-apps/popups/lock-popups/PhoneLockedWindow.cpp
A module-apps/popups/lock-popups/PhoneLockedWindow.hpp
A module-apps/popups/lock-popups/PhoneUnLockWindow.cpp
A module-apps/popups/lock-popups/PhoneUnLockWindow.hpp
R module-apps/{application-desktop => popups}/presenter/PowerOffPresenter.cpp
R module-apps/{application-desktop => popups}/presenter/PowerOffPresenter.hpp
M module-apps/windows/AppWindow.cpp
M module-services/service-appmgr/model/ApplicationManager.cpp
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp
M module-apps/Application.cpp => module-apps/Application.cpp +52 -8
@@ 6,12 6,9 @@
#include "GuiTimer.hpp"    // for GuiTimer
#include "Item.hpp"        // for Item
#include "MessageType.hpp" // for MessageType
#include "module-apps/popups/data/PopupRequestParams.hpp"
#include "module-apps/popups/data/PhoneModeParams.hpp"
#include "module-sys/Timers/TimerFactory.hpp" // for Timer
#include "TopBar.hpp"
#include "TopBar/Time.hpp"
#include "popups/TetheringConfirmationPopup.hpp"
#include "Translator.hpp"                // for KeyInputSim...
#include "common_data/EventStore.hpp"    // for Battery
#include "common_data/RawKey.hpp"        // for RawKey, key...


@@ 40,10 37,21 @@
#include <module-utils/Utils.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <module-utils/time/DateAndTimeSettings.hpp>

#include <service-audio/AudioServiceAPI.hpp> // for GetOutputVolume

#include <popups/VolumeWindow.hpp>
#include <popups/HomeModesWindow.hpp>
#include <popups/TetheringPhoneModePopup.hpp>
#include "popups/data/PopupData.hpp"
#include <popups/TetheringConfirmationPopup.hpp>
#include <popups/PowerOffWindow.hpp>
#include <popups/presenter/PowerOffPresenter.hpp>
#include <popups/lock-popups/PhoneLockedWindow.hpp>
#include <popups/lock-popups/PhoneLockedInfoWindow.hpp>
#include <popups/lock-popups/PhoneUnLockWindow.hpp>
#include <popups/data/PopupData.hpp>
#include <popups/data/PopupRequestParams.hpp>
#include <popups/data/PhoneModeParams.hpp>
#include <locks/data/LockData.hpp>

namespace gui
{


@@ 94,7 102,7 @@ namespace app
          default_window(gui::name::window::main_window), windowsStack(this),
          keyTranslator{std::make_unique<gui::KeyInputSimpleTranslation>()}, startInBackground{startInBackground},
          callbackStorage{std::make_unique<CallbackStorage>()}, topBarManager{std::make_unique<TopBarManager>()},
          settings(std::make_unique<settings::Settings>(this)), phoneMode{mode}
          settings(std::make_unique<settings::Settings>(this)), phoneMode{mode}, phoneLockSubject(this)
    {
        topBarManager->enableIndicators({gui::top_bar::Indicator::Time});
        using TimeMode = gui::top_bar::TimeConfiguration::TimeMode;


@@ 732,13 740,12 @@ namespace app
                });
                break;
            case ID::Tethering:
            case ID::TetheringPhoneModeChangeProhibited:
                windowsFactory.attach(window::tethering_confirmation_window,
                                      [](Application *app, const std::string &name) {
                                          return std::make_unique<gui::TetheringConfirmationPopup>(
                                              app, window::tethering_confirmation_window);
                                      });
                break;
            case ID::TetheringPhoneModeChangeProhibited:
                windowsFactory.attach(window::tethering_phonemode_change_window,
                                      [](Application *app, const std::string &name) {
                                          return std::make_unique<gui::TetheringPhoneModePopup>(


@@ 752,6 759,22 @@ namespace app
                break;
            case ID::Brightness:
                break;
            case ID::PhoneLock:
            case ID::InputLock:
                windowsFactory.attach(window::phone_lock_window, [](Application *app, const std::string &name) {
                    return std::make_unique<gui::PhoneLockedWindow>(app, window::phone_lock_window);
                });
                windowsFactory.attach(window::phone_lock_info_window, [](Application *app, const std::string &name) {
                    return std::make_unique<gui::PhoneLockedInfoWindow>(app, window::phone_lock_info_window);
                });
                windowsFactory.attach(window::input_lock_window, [](Application *app, const std::string &name) {
                    return std::make_unique<gui::PhoneUnlockWindow>(app, window::input_lock_window);
                });
                windowsFactory.attach(window::power_off_window, [](Application *app, const std::string &name) {
                    auto presenter = std::make_unique<gui::PowerOffPresenter>(app);
                    return std::make_unique<gui::PowerOffWindow>(app, std::move(presenter));
                });
                break;
            }
        }
    }


@@ 770,6 793,11 @@ namespace app
                     std::to_string(volumeParams->getVolume()).c_str());
            handleVolumeChanged(volumeParams->getVolume(), volumeParams->getAudioContext());
        }
        else if (id == ID::InputLock) {
            auto popupParams = static_cast<const gui::PhoneUnlockInputRequestParams *>(params);

            switchWindow(gui::popup::resolveWindowName(id), std::make_unique<locks::LockData>(popupParams->getLock()));
        }
        else {
            switchWindow(gui::popup::resolveWindowName(id));
        }


@@ 778,6 806,7 @@ namespace app
    void Application::abortPopup(gui::popup::ID id)
    {
        const auto popupName = gui::popup::resolveWindowName(id);

        if (getCurrentWindow()->getName() == popupName) {
            returnToPreviousWindow();
        }


@@ 884,6 913,21 @@ namespace app
        callbackStorage->removeAll(receiver);
    }

    void Application::handlePhoneLock()
    {
        phoneLockSubject.lock();
    }

    void Application::handlePhoneUnLock()
    {
        phoneLockSubject.unlock();
    }

    void Application::verifyPhoneLockInput(const std::vector<unsigned int> &inputData)
    {
        phoneLockSubject.verifyInput(inputData);
    }

    void Application::setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept
    {
        lockScreenPasscodeIsOn = screenPasscodeOn;

M module-apps/Application.hpp => module-apps/Application.hpp +9 -2
@@ 27,10 27,11 @@
#include <string>   // for string
#include <utility>  // for move, pair
#include <vector>   // for vector
#include "TopBarManager.hpp"
#include <TopBarManager.hpp>
#include <popups/Popups.hpp>
#include <locks/handlers/PhoneLockSubject.hpp>
#include "WindowsFactory.hpp"
#include "WindowsStack.hpp"
#include "popups/Popups.hpp"

namespace app
{


@@ 397,7 398,13 @@ namespace app
        std::unique_ptr<settings::Settings> settings;
        sys::phone_modes::PhoneMode phoneMode;

        lock::PhoneLockSubject phoneLockSubject;

      public:
        void handlePhoneLock();
        void handlePhoneUnLock();
        void verifyPhoneLockInput(const std::vector<unsigned int> &inputData);

        void setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept;
        bool isLockScreenPasscodeOn() const noexcept;
        const gui::top_bar::Configuration &getTopBarConfiguration() const noexcept;

M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp => module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +2 -4
@@ 108,10 108,8 @@ namespace app
            style::alarmClock::window::name::dialogYesNo,
            [](Application *app, const std::string &name) { return std::make_unique<gui::DialogYesNo>(app, name); });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationAlarmClock::destroyUserInterface()

M module-apps/application-antenna/ApplicationAntenna.cpp => module-apps/application-antenna/ApplicationAntenna.cpp +2 -4
@@ 166,10 166,8 @@ namespace app
            return std::make_unique<gui::AlgoParamsWindow>(app);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationAntenna::destroyUserInterface()

M module-apps/application-calculator/ApplicationCalculator.cpp => module-apps/application-calculator/ApplicationCalculator.cpp +2 -4
@@ 42,10 42,8 @@ namespace app
            return std::make_unique<gui::CalculatorMainWindow>(app, name);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationCalculator::destroyUserInterface()

M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +2 -4
@@ 144,10 144,8 @@ namespace app
            return std::make_unique<gui::EventReminderWindow>(app, event_reminder_window);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationCalendar::destroyUserInterface()

M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +0 -1
@@ 236,7 236,6 @@ namespace app
        });
        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
    }


M module-apps/application-calllog/ApplicationCallLog.cpp => module-apps/application-calllog/ApplicationCallLog.cpp +2 -4
@@ 100,10 100,8 @@ namespace app
            return std::make_unique<gui::DialogYesNo>(app, name);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationCallLog::destroyUserInterface()

M module-apps/application-clock/ApplicationClock.cpp => module-apps/application-clock/ApplicationClock.cpp +2 -4
@@ 87,10 87,8 @@ namespace app
            return std::make_unique<gui::ClockMainWindow>(app, name);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationClock::destroyUserInterface()

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +3 -15
@@ 7,11 7,9 @@
#include "windows/DesktopMainWindow.hpp"
#include "windows/MenuWindow.hpp"
#include "locks/windows/PinLockWindow.hpp"
#include "windows/PowerOffWindow.hpp"
#include "windows/DeadBatteryWindow.hpp"
#include "windows/LogoWindow.hpp"
#include "windows/ChargingBatteryWindow.hpp"
#include "windows/LockedInfoWindow.hpp"
#include "windows/Reboot.hpp"
#include "windows/Update.hpp"
#include "windows/UpdateProgress.hpp"


@@ 19,13 17,12 @@
#include "windows/MmiPullWindow.hpp"
#include "windows/MmiPushWindow.hpp"
#include "windows/MmiInternalMsgWindow.hpp"
#include "presenter/PowerOffPresenter.hpp"
#include <popups/presenter/PowerOffPresenter.hpp>
#include <windows/Dialog.hpp>
#include <windows/DialogMetadata.hpp>
#include <messages/DialogMetadataMessage.hpp>

#include "AppWindow.hpp"
#include "locks/data/LockData.hpp"
#include "data/DesktopData.hpp"
#include "models/ActiveNotificationsModel.hpp"



@@ 470,10 467,6 @@ namespace app
        windowsFactory.attach(desktop_menu, [](Application *app, const std::string newname) {
            return std::make_unique<gui::MenuWindow>(app);
        });
        windowsFactory.attach(desktop_poweroff, [](Application *app, const std::string newname) {
            auto presenter = std::make_unique<gui::PowerOffPresenter>(app);
            return std::make_unique<gui::PowerOffWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(dead_battery, [](Application *app, const std::string newname) {
            return std::make_unique<gui::DeadBatteryWindow>(app);
        });


@@ 483,9 476,6 @@ namespace app
        windowsFactory.attach(charging_battery, [](Application *app, const std::string newname) {
            return std::make_unique<gui::ChargingBatteryWindow>(app);
        });
        windowsFactory.attach(desktop_locked, [](Application *app, const std::string newname) {
            return std::make_unique<gui::LockedInfoWindow>(app);
        });
        windowsFactory.attach(desktop_reboot, [](Application *app, const std::string newname) {
            auto presenter = std::make_unique<gui::PowerOffPresenter>(app);
            return std::make_unique<gui::RebootWindow>(app, std::move(presenter));


@@ 512,10 502,8 @@ namespace app
            return std::make_unique<gui::DialogConfirm>(app, name);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationDesktop::destroyUserInterface()

M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +0 -6
@@ 18,11 18,9 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/widgets/DesktopInputWidget.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/DesktopMainWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MenuWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PowerOffWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/DeadBatteryWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LogoWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/ChargingBatteryWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockedInfoWindow.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/windows/Reboot.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/Update.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/UpdateProgress.cpp"


@@ 30,8 28,6 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPullWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPushWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiInternalMsgWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/UpdateProgress.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/presenter/PowerOffPresenter.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/models/ActiveNotificationsModel.cpp"
	PUBLIC
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationDesktop.hpp"


@@ 41,8 37,6 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/widgets/DesktopInputWidget.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/DesktopMainWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MenuWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PowerOffWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockedInfoWindow.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/windows/Reboot.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/Update.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/UpdateProgress.hpp"

M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +28 -96
@@ 3,27 3,17 @@

#include <memory>

#include "Alignment.hpp"
#include "BottomBar.hpp"
#include "DesktopMainWindow.hpp"
#include "GuiTimer.hpp"
#include "application-desktop/ApplicationDesktop.hpp"
#include "locks/data/LockData.hpp"
#include "application-desktop/data/DesktopStyle.hpp"
#include "application-desktop/data/DesktopData.hpp"
#include "application-messages/ApplicationMessages.hpp"
#include "gui/widgets/Image.hpp"
#include <application-desktop/ApplicationDesktop.hpp>
#include <application-desktop/data/DesktopStyle.hpp>
#include <application-desktop/data/DesktopData.hpp>
#include <application-call/data/CallSwitchData.hpp>

#include <service-appmgr/Controller.hpp>
#include <service-time/ServiceTime.hpp>
#include <service-time/TimeMessage.hpp>

#include <i18n/i18n.hpp>
#include "log/log.hpp"

#include <application-settings/ApplicationSettings.hpp>
#include <cassert>
#include <time/time_conversion.hpp>
#include <module-apps/application-call/data/CallSwitchData.hpp>
#include <log/log.hpp>

namespace gui
{


@@ 87,9 77,6 @@ namespace gui

    top_bar::Configuration DesktopMainWindow::configureTopBar(top_bar::Configuration appConfiguration)
    {
        auto app            = getAppDesktop();
        const auto isLocked = app->lockHandler.isScreenLocked();
        appConfiguration.setIndicator(top_bar::Indicator::Lock, isLocked);
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        return appConfiguration;


@@ 115,37 102,23 @@ namespace gui

    void DesktopMainWindow::setVisibleState()
    {
        applyToTopBar(
            [this](top_bar::Configuration configuration) { return configureTopBar(std::move(configuration)); });
        if (auto app = getAppDesktop(); app->lockHandler.isScreenLocked()) {
            bottomBar->setText(BottomBar::Side::CENTER, utils::translate("app_desktop_unlock"));
            bottomBar->setActive(BottomBar::Side::RIGHT, false);
            bottomBar->setText(
                BottomBar::Side::LEFT, utils::translate("app_desktop_emergency"), app->lockHandler.isScreenBlocked());

            inputCallback = nullptr;
            setFocusItem(nullptr);

            application->bus.sendUnicast(std::make_shared<TimersProcessingStopMessage>(), service::name::service_time);
        }
        else {
            setActiveState();
        auto app = getAppDesktop();

            if (osUpdateVer == osCurrentVer && osUpdateVer != updateos::initSysVer &&
                osCurrentVer != updateos::initSysVer) {
                auto data = std::make_unique<CurrentOsVersion>();
                data->setData(osCurrentVer);
                application->switchWindow(app::window::name::desktop_post_update_window, std::move(data));
                getAppDesktop()->setOsUpdateVersion(updateos::initSysVer);
            }
        setActiveState();

            if (app->need_sim_select && Store::GSM::get()->sim == Store::GSM::SIM::SIM_UNKNOWN) {
                app::manager::Controller::sendAction(application, app::manager::actions::SelectSimCard);
            }
        if (osUpdateVer == osCurrentVer && osUpdateVer != updateos::initSysVer &&
            osCurrentVer != updateos::initSysVer) {
            auto data = std::make_unique<CurrentOsVersion>();
            data->setData(osCurrentVer);
            application->switchWindow(app::window::name::desktop_post_update_window, std::move(data));
            getAppDesktop()->setOsUpdateVersion(updateos::initSysVer);
        }

            application->bus.sendUnicast(std::make_shared<TimersProcessingStartMessage>(), service::name::service_time);
        if (app->need_sim_select && Store::GSM::get()->sim == Store::GSM::SIM::SIM_UNKNOWN) {
            app::manager::Controller::sendAction(application, app::manager::actions::SelectSimCard);
        }
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);

        application->bus.sendUnicast(std::make_shared<TimersProcessingStartMessage>(), service::name::service_time);
    }

    void DesktopMainWindow::onBeforeShow(ShowMode mode, SwitchData *data)


@@ 154,25 127,16 @@ namespace gui
        setVisibleState();
    }

    bool DesktopMainWindow::processLongPressEvent(const InputEvent &inputEvent)
    bool DesktopMainWindow::processLongReleaseEvent(const InputEvent &inputEvent)
    {
        auto app = getAppDesktop();

        if (!app->lockHandler.isScreenLocked()) {
            if (inputEvent.is(KeyCode::KEY_PND)) {
                app->lockHandler.lockScreen();
                setVisibleState();
                return true;
            }
            // long press of '0' key is translated to '+'
            else if (inputEvent.is(KeyCode::KEY_0)) {
                return app::manager::Controller::sendAction(
                    application, app::manager::actions::Dial, std::make_unique<app::EnterNumberData>("+"));
            }
        // long press of '0' key is translated to '+'
        if (inputEvent.is(KeyCode::KEY_0)) {
            return app::manager::Controller::sendAction(
                application, app::manager::actions::Dial, std::make_unique<app::EnterNumberData>("+"));
        }

        if (inputEvent.is(KeyCode::KEY_RF)) {
            application->switchWindow(app::window::name::desktop_poweroff);
            application->switchWindow(popup::window::power_off_window);
            return true;
        }
        // check if any of the lower inheritance onInput methods catch the event


@@ 185,7 149,7 @@ namespace gui
        constexpr auto pageLastNotificationIdx  = style::notifications::model::maxNotificationsPerPage - 1;
    } // namespace

    bool DesktopMainWindow::processShortPressEventOnUnlocked(const InputEvent &inputEvent)
    bool DesktopMainWindow::processShortReleaseEvent(const InputEvent &inputEvent)
    {
        auto code = translator.handle(inputEvent.getRawKey(), InputMode({InputMode::phone}).get());
        // if numeric key was pressed record that key and send it to call application


@@ 220,45 184,13 @@ namespace gui
        return false;
    }

    bool DesktopMainWindow::processShortPressEventOnLocked(const InputEvent &inputEvent)
    {
        // if enter was pressed
        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

            getAppDesktop()->lockHandler.unlockScreen();
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
            app::manager::Controller::sendAction(application, app::manager::actions::ShowEmergencyContacts);
            return true;
        }
        else if (enter_cache.storeEnter(inputEvent)) {
            return true;
        }
        // check if any of the lower inheritance onInput methods catch the event
        else if (AppWindow::onInput(inputEvent)) {
            return true;
        }
        application->switchWindow(app::window::name::desktop_locked);
        return true;
    }

    bool DesktopMainWindow::onInput(const InputEvent &inputEvent)
    {
        auto *app = getAppDesktop();

        if (inputEvent.isLongRelease()) {
            return processLongPressEvent(inputEvent);
            return processLongReleaseEvent(inputEvent);
        }
        else if (inputEvent.isShortRelease()) {
            if (app->lockHandler.isScreenLocked()) {
                return processShortPressEventOnLocked(inputEvent);
            }
            else {
                return processShortPressEventOnUnlocked(inputEvent);
            }
            return processShortReleaseEvent(inputEvent);
        }
        return AppWindow::onInput(inputEvent);
    }

M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +5 -45
@@ 3,11 3,9 @@

#pragma once

#include "AppWindow.hpp"
#include "gui/widgets/Label.hpp"
#include "gui/widgets/Window.hpp"

#include "Translator.hpp"
#include <AppWindow.hpp>
#include <gui/widgets/Label.hpp>
#include <Translator.hpp>
#include <notifications/NotificationsModel.hpp>
#include <ListView.hpp>



@@ 27,49 25,11 @@ namespace gui
        gui::ListView *notificationsList                            = nullptr;
        std::shared_ptr<gui::NotificationsModel> notificationsModel = nullptr;

        /// Timed enter value cache, could be templated to any value really
        class EnterCache
        {
            /// to tell if enter was pressed or not
            bool enterPressed = false;
            /// val to check timeout
            uint32_t unlockStartTime = 0;
            /// val to clear start time
            uint32_t unclockTime = 3000;

          public:
            bool storeEnter(const InputEvent &evt)
            {
                enterPressed    = evt.is(KeyCode::KEY_ENTER);
                unlockStartTime = xTaskGetTickCount();
                return enterPressed;
            }

            void clear()
            {
                enterPressed = false;
            }

            bool cached()
            {
                // value timed out -> clear cache
                if (!(xTaskGetTickCount() - unlockStartTime < unclockTime)) {
                    enterPressed = false;
                }
                return enterPressed;
            }
        } enter_cache;
        /**
         * Name of the application that was on top when lock timeout occurred
         */
        std::string lockTimeoutApplilcation = "";

        // method hides or show widgets and sets bars according to provided state
        void setVisibleState();
        auto setActiveState() -> bool;
        bool processLongPressEvent(const InputEvent &inputEvent);
        bool processShortPressEventOnUnlocked(const InputEvent &inputEvent);
        bool processShortPressEventOnLocked(const InputEvent &inputEvent);
        bool processLongReleaseEvent(const InputEvent &inputEvent);
        bool processShortReleaseEvent(const InputEvent &inputEvent);
        app::ApplicationDesktop *getAppDesktop() const;

      public:

M module-apps/application-desktop/windows/LockedInfoWindow.cpp => module-apps/application-desktop/windows/LockedInfoWindow.cpp +0 -101
@@ 1,101 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "LockedInfoWindow.hpp"

#include "service-appmgr/Controller.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "RichTextParser.hpp"
#include "FontManager.hpp"

#include "application-desktop/data/DesktopStyle.hpp"
#include "locks/data/LockStyle.hpp"
#include "Names.hpp"

#include <application-phonebook/ApplicationPhonebook.hpp>
#include <i18n/i18n.hpp>

using namespace gui;

LockedInfoWindow::LockedInfoWindow(app::Application *app) : AppWindow(app, app::window::name::desktop_locked)
{
    buildInterface();
}

void LockedInfoWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
    setVisibleState();
}

void LockedInfoWindow::setVisibleState()
{
    lockImage->setVisible(true);

    bottomBar->setActive(BottomBar::Side::LEFT, true);
    bottomBar->setActive(BottomBar::Side::CENTER, false);
    bottomBar->setActive(BottomBar::Side::RIGHT, true);
}

bool LockedInfoWindow::onInput(const InputEvent &inputEvent)
{
    if (inputEvent.isShortRelease()) {
        if (inputEvent.is(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
            app::manager::Controller::sendAction(application, app::manager::actions::EmergencyDial);
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_RF) && bottomBar->isActive(BottomBar::Side::RIGHT)) {
            application->switchWindow(gui::name::window::main_window);
            return true;
        }
    }
    return AppWindow::onInput(inputEvent);
}

void LockedInfoWindow::rebuild()
{
    destroyInterface();
    buildInterface();
}

top_bar::Configuration LockedInfoWindow::configureTopBar(top_bar::Configuration appConfiguration)
{
    appConfiguration.enable(top_bar::Indicator::Lock);
    appConfiguration.disable(top_bar::Indicator::Time);
    return appConfiguration;
}

void LockedInfoWindow::buildInterface()
{
    namespace lock_style = style::window::pin_lock;
    AppWindow::buildInterface();

    bottomBar->setText(BottomBar::Side::LEFT, utils::translate("app_desktop_emergency"));
    bottomBar->setText(BottomBar::Side::RIGHT, utils::translate("common_back"));

    lockImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, "pin_lock");
    infoText  = new Text(this,
                        lock_style::primary_text::x,
                        lock_style::primary_text::y,
                        lock_style::primary_text::w,
                        lock_style::primary_text::h);

    TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
    text::RichTextParser rtParser;
    auto parsedText = rtParser.parse(utils::translate("app_desktop_press_to_unlock"), &format);

    infoText->setText(std::move(parsedText));
    infoText->setAlignment(Alignment::Horizontal::Center);
}

void LockedInfoWindow::destroyInterface()
{
    erase();
    invalidate();
}

void LockedInfoWindow::invalidate() noexcept
{
    lockImage = nullptr;
    infoText  = nullptr;
}

M module-apps/application-desktop/windows/Names.hpp => module-apps/application-desktop/windows/Names.hpp +2 -4
@@ 1,20 1,18 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "AppWindow.hpp"
#include <AppWindow.hpp>

namespace app::window::name
{
    inline constexpr auto desktop_main_window        = gui::name::window::main_window;
    inline constexpr auto desktop_menu               = "MenuWindow";
    inline constexpr auto desktop_reboot             = "Reboot";
    inline constexpr auto desktop_poweroff           = "PowerOffWindow";
    inline constexpr auto dead_battery               = "DeadBatteryWindow";
    inline constexpr auto charging_battery           = "CharginBatteryWindow";
    inline constexpr auto logo_window                = "LogoWindow";
    inline constexpr auto desktop_pin_lock           = "PinLockWindow";
    inline constexpr auto desktop_locked             = "LockedInfoWindow";
    inline constexpr auto desktop_update             = "Update";
    inline constexpr auto desktop_update_progress    = "UpdateProgress";
    inline constexpr auto desktop_post_update_window = "PostUpdateWindow";

M module-apps/application-desktop/windows/PostUpdateWindow.cpp => module-apps/application-desktop/windows/PostUpdateWindow.cpp +2 -13
@@ 3,21 3,10 @@

#include "PostUpdateWindow.hpp"

#include "service-appmgr/Controller.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "FontManager.hpp"

#include <module-gui/gui/widgets/BottomBar.hpp>
#include <module-gui/gui/widgets/TopBar.hpp>
#include <module-gui/gui/core/FontManager.hpp>

#include <module-apps/application-desktop/data/DesktopStyle.hpp>
#include <module-apps/application-desktop/data/DesktopData.hpp>
#include <locks/data/LockStyle.hpp>
#include <module-apps/application-desktop/windows/Names.hpp>
#include <application-desktop/data/DesktopData.hpp>
#include <application-desktop/windows/Names.hpp>

#include <application-phonebook/ApplicationPhonebook.hpp>
#include <i18n/i18n.hpp>

using namespace gui;

M module-apps/application-desktop/windows/Reboot.hpp => module-apps/application-desktop/windows/Reboot.hpp +5 -4
@@ 1,12 1,13 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <vector>
#include "AppWindow.hpp"
#include <AppWindow.hpp>
#include <Text.hpp>
#include "../presenter/PowerOffPresenter.hpp"
#include <popups/presenter/PowerOffPresenter.hpp>

#include <vector>

namespace gui
{

M module-apps/application-desktop/windows/Update.cpp => module-apps/application-desktop/windows/Update.cpp +1 -1
@@ 22,7 22,7 @@
namespace gui
{

    UpdateWindow::UpdateWindow(app::Application *app) : AppWindow(app, app::window::name::desktop_poweroff)
    UpdateWindow::UpdateWindow(app::Application *app) : AppWindow(app, app::window::name::desktop_update)
    {
        buildInterface();
    }

M module-apps/application-meditation/ApplicationMeditation.cpp => module-apps/application-meditation/ApplicationMeditation.cpp +2 -4
@@ 54,10 54,8 @@ namespace app
            return std::make_unique<gui::PreparationTimeWindow>(app);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationMeditation::destroyUserInterface()

M module-apps/application-messages/ApplicationMessages.cpp => module-apps/application-messages/ApplicationMessages.cpp +2 -4
@@ 163,10 163,8 @@ namespace app
            return std::make_unique<gui::SearchResults>(app);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationMessages::destroyUserInterface()

M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +2 -4
@@ 83,10 83,8 @@ namespace app
            return std::make_unique<gui::MusicPlayerEmptyWindow>(app);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationMusicPlayer::destroyUserInterface()

M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +2 -4
@@ 124,10 124,8 @@ namespace app
            utils::translate("app_phonebook_options_title"),
            [](Application *app, const std::string &name) { return std::make_unique<gui::OptionWindow>(app, name); });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationNotes::destroyUserInterface()

M module-apps/application-onboarding/ApplicationOnBoarding.cpp => module-apps/application-onboarding/ApplicationOnBoarding.cpp +2 -4
@@ 158,10 158,8 @@ namespace app
            return std::make_unique<gui::DialogConfirm>(app, gui::window::name::dialog_confirm);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationOnBoarding::destroyUserInterface()

M module-apps/application-phonebook/ApplicationPhonebook.cpp => module-apps/application-phonebook/ApplicationPhonebook.cpp +2 -4
@@ 149,10 149,8 @@ namespace app
            return std::make_unique<gui::PhonebookNewContact>(app);
        });

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationPhonebook::destroyUserInterface()

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +3 -5
@@ 77,10 77,10 @@
#include <module-services/service-evtmgr/service-evtmgr/EVMessages.hpp>
#include <module-services/service-appmgr/service-appmgr/messages/Message.hpp>
#include <module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp>
#include <locks/windows/PinLockWindow.hpp>
#include <module-apps/application-desktop/windows/Names.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
#include <module-apps/windows/Dialog.hpp>
#include <locks/windows/PinLockWindow.hpp>

#include <i18n/i18n.hpp>



@@ 504,10 504,8 @@ namespace app
        windowsFactory.attach(gui::window::name::connection_frequency, [](Application *app, const std::string &name) {
            return std::make_unique<gui::ConnectionFrequencyWindow>(app, static_cast<ApplicationSettingsNew *>(app));
        });
        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationSettingsNew::destroyUserInterface()

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +2 -4
@@ 164,10 164,8 @@ namespace app
                                  });
        }

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::TetheringPhoneModeChangeProhibited,
                      gui::popup::ID::PhoneModes});
        attachPopups(
            {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
    }

    void ApplicationSettings::destroyUserInterface()

M module-apps/locks/CMakeLists.txt => module-apps/locks/CMakeLists.txt +5 -0
@@ 15,6 15,8 @@ target_sources( ${PROJECT_NAME}

	PRIVATE
		"${CMAKE_CURRENT_LIST_DIR}/handlers/PinLockHandler.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/handlers/PhoneLockHandler.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/handlers/PhoneLockSubject.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockBaseWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockWindow.cpp"


@@ 27,7 29,10 @@ target_sources( ${PROJECT_NAME}
	PRIVATE
		"${CMAKE_CURRENT_LIST_DIR}/data/LockData.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/LockStyle.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/LockMessages.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/handlers/PinLockHandler.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/handlers/PhoneLockHandler.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/handlers/PhoneLockSubject.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockBaseWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockWindow.hpp"

A module-apps/locks/data/LockMessages.hpp => module-apps/locks/data/LockMessages.hpp +39 -0
@@ 0,0 1,39 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Service/Message.hpp>

namespace lock
{
    class UnlockPhone : public sys::DataMessage
    {
      public:
        UnlockPhone() : DataMessage{MessageType::MessageTypeUninitialized}
        {}
    };

    class LockPhone : public sys::DataMessage
    {
      public:
        LockPhone() : DataMessage{MessageType::MessageTypeUninitialized}
        {}
    };

    class LockPhoneInput : public sys::DataMessage
    {
      private:
        std::vector<unsigned int> inputData;

      public:
        explicit LockPhoneInput(std::vector<unsigned int> inputData)
            : DataMessage{MessageType::MessageTypeUninitialized}, inputData(std::move(inputData))
        {}

        [[nodiscard]] auto getInputData() const noexcept
        {
            return inputData;
        }
    };
} // namespace lock

A module-apps/locks/handlers/PhoneLockHandler.cpp => module-apps/locks/handlers/PhoneLockHandler.cpp +120 -0
@@ 0,0 1,120 @@
//// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
//// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneLockHandler.hpp"

#include <service-appmgr/service-appmgr/Controller.hpp>
#include <locks/widgets/LockHash.hpp>
#include <Utils.hpp>
#include <memory>

#include <module-apps/popups/data/PopupRequestParams.hpp>

namespace locks
{
    constexpr unsigned int default_attempts = 4;

    PhoneLockHandler::PhoneLockHandler(sys::Service *owner)
        : owner(owner), lock(Lock::LockState::InputRequired, default_attempts)
    {}

    void PhoneLockHandler::enablePhoneLock(bool _phoneLockEnabled)
    {
        phoneLockEnabled = _phoneLockEnabled;
    }

    void PhoneLockHandler::setPhoneLockHash(const std::string &value)
    {
        if (!value.empty()) {
            phoneLockHash = utils::getNumericValue<unsigned int>(value);
        }
        else {
            phoneLockHash = 0;
        }
    }

    void PhoneLockHandler::PhoneLockAction()
    {
        app::manager::Controller::sendAction(owner,
                                             app::manager::actions::ShowPopup,
                                             std::make_unique<gui::PopupRequestParams>(gui::popup::ID::PhoneLock));
    }

    void PhoneLockHandler::PhoneUnlockAction()
    {
        app::manager::Controller::sendAction(owner,
                                             app::manager::actions::AbortPopup,
                                             std::make_unique<gui::PopupRequestParams>(gui::popup::ID::InputLock));
        app::manager::Controller::sendAction(owner,
                                             app::manager::actions::AbortPopup,
                                             std::make_unique<gui::PopupRequestParams>(gui::popup::ID::PhoneLock));
    }

    void PhoneLockHandler::PhoneInputRequiredAction()
    {
        app::manager::Controller::sendAction(
            owner,
            app::manager::actions::ShowPopup,
            std::make_unique<gui::PhoneUnlockInputRequestParams>(gui::popup::ID::InputLock, lock));
    }

    sys::MessagePointer PhoneLockHandler::handleUnlockRequest()
    {
        // Check if phoneLock has not been disabled by setting
        if (!phoneLockEnabled) {
            PhoneUnlockAction();
            return sys::msgHandled();
        }

        if (lock.isState(Lock::LockState::Unlocked)) {
            PhoneUnlockAction();
        }
        else if (lock.isState(Lock::LockState::Blocked)) {
            PhoneInputRequiredAction();
        }
        else if (!lock.isState(Lock::LockState::Unlocked)) {

            lock.lockState = Lock::LockState::InputRequired;
            PhoneInputRequiredAction();
        }

        return sys::msgHandled();
    }

    sys::MessagePointer PhoneLockHandler::handleLockRequest()
    {
        lock.lockState = Lock::LockState::InputRequired;
        PhoneLockAction();

        return sys::msgHandled();
    }

    sys::MessagePointer PhoneLockHandler::verifyPhoneLockInput(const std::vector<unsigned int> &inputData)
    {
        const uint32_t hash = getHash(inputData);
        lock.attemptsLeft--;

        if (phoneLockHash == hash) {
            lock.lockState    = Lock::LockState::Unlocked;
            lock.attemptsLeft = default_attempts;
            PhoneUnlockAction();
            return sys::msgHandled();
        }
        else if (lock.attemptsLeft > 0) {
            lock.lockState = Lock::LockState::InputInvalidRetryRequired;
        }
        else {
            lock.lockState = Lock::LockState::Blocked;
        }

        PhoneInputRequiredAction();

        return sys::msgHandled();
    }

    bool PhoneLockHandler::isPhoneLocked() const noexcept
    {
        return !lock.isState(Lock::LockState::Unlocked);
    }

} // namespace locks

A module-apps/locks/handlers/PhoneLockHandler.hpp => module-apps/locks/handlers/PhoneLockHandler.hpp +37 -0
@@ 0,0 1,37 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <locks/widgets/Lock.hpp>
#include <locks/data/LockMessages.hpp>

#include <module-sys/Service/Service.hpp>

namespace locks
{
    class PhoneLockHandler
    {
      private:
        sys::Service *owner;
        Lock lock;
        bool phoneLockEnabled      = true;
        unsigned int phoneLockHash = std::numeric_limits<unsigned>::max();

        void PhoneLockAction();
        void PhoneUnlockAction();
        void PhoneInputRequiredAction();

      public:
        explicit PhoneLockHandler(sys::Service *owner);

        sys::MessagePointer handleLockRequest();
        sys::MessagePointer handleUnlockRequest();
        sys::MessagePointer verifyPhoneLockInput(const std::vector<unsigned int> &inputData);

        void enablePhoneLock(bool _phoneLockEnabled);
        void setPhoneLockHash(const std::string &value);
        [[nodiscard]] bool isPhoneLocked() const noexcept;
    };

} // namespace locks

A module-apps/locks/handlers/PhoneLockSubject.cpp => module-apps/locks/handlers/PhoneLockSubject.cpp +33 -0
@@ 0,0 1,33 @@
//// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
//// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneLockSubject.hpp"

#include <service-appmgr/service-appmgr/model/ApplicationManager.hpp>
#include <locks/data/LockMessages.hpp>

namespace lock
{
    PhoneLockSubject::PhoneLockSubject(sys::Service *owner) : owner{owner}
    {
        if (owner == nullptr) {
            throw std::invalid_argument{"Subject's owner is invalid"};
        }
    }

    void PhoneLockSubject::unlock()
    {
        owner->bus.sendUnicast(std::make_shared<UnlockPhone>(), app::manager::ApplicationManager::ServiceName);
    }

    void PhoneLockSubject::lock()
    {
        owner->bus.sendUnicast(std::make_shared<LockPhone>(), app::manager::ApplicationManager::ServiceName);
    }

    void PhoneLockSubject::verifyInput(const std::vector<unsigned int> &inputData)
    {
        owner->bus.sendUnicast(std::make_shared<LockPhoneInput>(inputData),
                               app::manager::ApplicationManager::ServiceName);
    }
} // namespace lock

A module-apps/locks/handlers/PhoneLockSubject.hpp => module-apps/locks/handlers/PhoneLockSubject.hpp +23 -0
@@ 0,0 1,23 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-sys/Service/Service.hpp>

namespace lock
{
    class PhoneLockSubject
    {
      private:
        sys::Service *owner;

      public:
        explicit PhoneLockSubject(sys::Service *owner);

        void unlock();
        void lock();
        void verifyInput(const std::vector<unsigned int> &inputData);
    };

} // namespace lock

M module-apps/locks/widgets/Lock.hpp => module-apps/locks/widgets/Lock.hpp +3 -0
@@ 17,6 17,8 @@ namespace gui

namespace locks
{
    class PhoneLockHandler;

    class Lock
    {
      public:


@@ 139,6 141,7 @@ namespace locks
            maxInputSize = _maxInputSize;
        }

        friend class PhoneLockHandler;
        friend class gui::PinLockHandler;
        friend class gui::ChangePasscodeLockHandler;
    };

M module-apps/popups/CMakeLists.txt => module-apps/popups/CMakeLists.txt +10 -0
@@ 21,6 21,11 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/TetheringConfirmationPopup.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/TetheringNotificationPopup.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/TetheringPhoneModePopup.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/PowerOffWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/presenter/PowerOffPresenter.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockedInfoWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockedWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneUnLockWindow.cpp"

	PRIVATE
		"${CMAKE_CURRENT_LIST_DIR}/Popups.hpp"


@@ 30,5 35,10 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/TetheringConfirmationPopup.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/TetheringNotificationPopup.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/TetheringPhoneModePopup.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/PowerOffWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/presenter/PowerOffPresenter.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/PopupData.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockedInfoWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockedWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneUnLockWindow.hpp"
)

M module-apps/popups/Popups.cpp => module-apps/popups/Popups.cpp +4 -0
@@ 18,6 18,10 @@ namespace gui::popup
            return gui::popup::window::tethering_confirmation_window;
        case ID::TetheringPhoneModeChangeProhibited:
            return gui::popup::window::tethering_phonemode_change_window;
        case ID::PhoneLock:
            return gui::popup::window::phone_lock_window;
        case ID::InputLock:
            return gui::popup::window::input_lock_window;
        }
        return {};
    }

M module-apps/popups/Popups.hpp => module-apps/popups/Popups.hpp +11 -8
@@ 3,9 3,6 @@

#pragma once

#include <module-apps/popups/VolumeWindow.hpp>
#include <module-apps/popups/HomeModesWindow.hpp>

#include <string>

namespace gui


@@ 18,19 15,25 @@ namespace gui
            PhoneModes,
            Brightness,
            Tethering,
            TetheringPhoneModeChangeProhibited
            TetheringPhoneModeChangeProhibited,
            PhoneLock,
            InputLock
        };

        namespace window
        {
            inline constexpr auto volume_window      = "VolumePopup";
            inline constexpr auto phone_modes_window = "PhoneModesPopup";
            inline constexpr auto brightness_window  = "BrightnessPopup";
            inline constexpr auto volume_window                     = "VolumePopup";
            inline constexpr auto phone_modes_window                = "PhoneModesPopup";
            inline constexpr auto brightness_window                 = "BrightnessPopup";
            inline constexpr auto tethering_confirmation_window     = "TetheringConfirmationPopup";
            inline constexpr auto tethering_phonemode_change_window = "TetheringPhoneModeChangeProhibitedPopup";
            inline constexpr auto phone_lock_window                 = "PhoneLockPopup";
            inline constexpr auto phone_lock_info_window            = "PhoneLockInfoPopup";
            inline constexpr auto input_lock_window                 = "InputLockPopup";
            inline constexpr auto power_off_window                  = "PowerOffPopup";

        } // namespace window

        std::string resolveWindowName(ID id);
    }     // namespace popup
    } // namespace popup
} // namespace gui

R module-apps/application-desktop/windows/PowerOffWindow.cpp => module-apps/popups/PowerOffWindow.cpp +6 -17
@@ 1,29 1,15 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "InputEvent.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "log/log.hpp"

// module-utils
#include <i18n/i18n.hpp>

#include "PowerOffWindow.hpp"

// services
#include <service-appmgr/model/ApplicationManager.hpp>
#include <service-appmgr/Controller.hpp>

#include "service-cellular/ServiceCellular.hpp"
#include <Style.hpp>
#include <application-desktop/windows/Names.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
#include <log/log.hpp>
#include <messages/DialogMetadataMessage.hpp>

namespace gui
{
    PowerOffWindow::PowerOffWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter)
        : DialogYesNo(app, app::window::name::desktop_poweroff), presenter(std::move(presenter))
        : DialogYesNo(app, popup::window::power_off_window), presenter(std::move(presenter))
    {
        topBar->configure(std::move(configureTopBar(application->getTopBarConfiguration())));
    }


@@ 52,6 38,9 @@ namespace gui
        metadata.icon  = "turn_off_W_G";
        auto msg       = std::make_unique<DialogMetadataMessage>(std::move(metadata));
        DialogYesNo::onBeforeShow(mode, msg.get());

        bottomBar->setActive(BottomBar::Side::CENTER, false);
        bottomBar->setActive(BottomBar::Side::RIGHT, false);
    }

} /* namespace gui */

R module-apps/application-desktop/windows/PowerOffWindow.hpp => module-apps/popups/PowerOffWindow.hpp +4 -8
@@ 1,21 1,17 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <vector>
#include <module-apps/windows/Dialog.hpp>
#include "gui/widgets/Label.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "../presenter/PowerOffPresenter.hpp"
#include <windows/Dialog.hpp>
#include <popups/presenter/PowerOffPresenter.hpp>

namespace gui
{
    class PowerOffWindow : public DialogYesNo
    {

        std::unique_ptr<PowerOffPresenter> presenter;

      public:
        PowerOffWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;

M module-apps/popups/data/PopupRequestParams.hpp => module-apps/popups/data/PopupRequestParams.hpp +17 -0
@@ 8,6 8,7 @@
#include <service-appmgr/Actions.hpp>
#include <module-sys/PhoneModes/Common.hpp>
#include <module-audio/Audio/AudioCommon.hpp>
#include <locks/widgets/Lock.hpp>

namespace gui
{


@@ 27,6 28,22 @@ namespace gui
        gui::popup::ID popupId;
    };

    class PhoneUnlockInputRequestParams : public PopupRequestParams
    {
      public:
        PhoneUnlockInputRequestParams(gui::popup::ID popupId, locks::Lock lock)
            : PopupRequestParams{popupId}, lock{std::move(lock)}
        {}

        [[nodiscard]] auto getLock() const noexcept
        {
            return lock;
        }

      private:
        locks::Lock lock;
    };

    class PhoneModePopupRequestParams : public PopupRequestParams
    {
      public:

A module-apps/popups/lock-popups/PhoneLockedInfoWindow.cpp => module-apps/popups/lock-popups/PhoneLockedInfoWindow.cpp +74 -0
@@ 0,0 1,74 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneLockedInfoWindow.hpp"

#include <service-appmgr/Controller.hpp>
#include <application-desktop/data/DesktopStyle.hpp>
#include <locks/data/LockStyle.hpp>

#include <i18n/i18n.hpp>

using namespace gui;

PhoneLockedInfoWindow::PhoneLockedInfoWindow(app::Application *app, const std::string &name) : AppWindow(app, name)
{
    buildInterface();
}

void PhoneLockedInfoWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
    setVisibleState();
}

void PhoneLockedInfoWindow::setVisibleState()
{
    lockImage->setVisible(true);

    bottomBar->setActive(BottomBar::Side::LEFT, true);
    bottomBar->setActive(BottomBar::Side::CENTER, false);
    bottomBar->setActive(BottomBar::Side::RIGHT, true);
}

bool PhoneLockedInfoWindow::onInput(const InputEvent &inputEvent)
{
    if (inputEvent.isShortRelease(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
        app::manager::Controller::sendAction(application,
                                             app::manager::actions::EmergencyDial,
                                             std::make_unique<SwitchData>(),
                                             app::manager::OnSwitchBehaviour::RunInBackground);
        return true;
    }
    return AppWindow::onInput(inputEvent);
}

top_bar::Configuration PhoneLockedInfoWindow::configureTopBar(top_bar::Configuration appConfiguration)
{
    appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.disable(top_bar::Indicator::Time);
    appConfiguration.enable(top_bar::Indicator::PhoneMode);
    appConfiguration.enable(top_bar::Indicator::Lock);
    appConfiguration.enable(top_bar::Indicator::Battery);
    appConfiguration.enable(top_bar::Indicator::Signal);
    appConfiguration.enable(top_bar::Indicator::SimCard);
    return appConfiguration;
}

void PhoneLockedInfoWindow::buildInterface()
{
    namespace lock_style = style::window::pin_lock;
    AppWindow::buildInterface();

    bottomBar->setText(BottomBar::Side::LEFT, utils::translate("app_desktop_emergency"));
    bottomBar->setText(BottomBar::Side::RIGHT, utils::translate("common_back"));

    lockImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, "pin_lock");
    infoText  = new Text(this,
                        lock_style::primary_text::x,
                        lock_style::primary_text::y,
                        lock_style::primary_text::w,
                        lock_style::primary_text::h);

    infoText->setRichText(utils::translate("app_desktop_press_to_unlock"));
    infoText->setAlignment(Alignment::Horizontal::Center);
}

R module-apps/application-desktop/windows/LockedInfoWindow.hpp => module-apps/popups/lock-popups/PhoneLockedInfoWindow.hpp +6 -9
@@ 1,30 1,27 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "AppWindow.hpp"
#include "Text.hpp"
#include "gui/widgets/Image.hpp"
#include <AppWindow.hpp>
#include <Text.hpp>
#include <gui/widgets/Image.hpp>

namespace gui
{
    class LockedInfoWindow : public AppWindow
    class PhoneLockedInfoWindow : public AppWindow
    {
        gui::Image *lockImage = nullptr;
        gui::Text *infoText   = nullptr;

        void setVisibleState();
        void invalidate() noexcept;

      public:
        explicit LockedInfoWindow(app::Application *app);
        PhoneLockedInfoWindow(app::Application *app, const std::string &name);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const InputEvent &inputEvent) override;

        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
    };
} /* namespace gui */

A module-apps/popups/lock-popups/PhoneLockedWindow.cpp => module-apps/popups/lock-popups/PhoneLockedWindow.cpp +149 -0
@@ 0,0 1,149 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneLockedWindow.hpp"

#include <application-desktop/data/DesktopStyle.hpp>
#include <module-services/service-appmgr/service-appmgr/Controller.hpp>
#include <service-time/ServiceTime.hpp>
#include <service-time/TimeMessage.hpp>

namespace gui
{
    bool PhoneLockedWindow::LockingTimer::storeEnter(const InputEvent &evt)
    {
        enterPressed    = evt.is(KeyCode::KEY_ENTER);
        unLockStartTime = xTaskGetTickCount();
        return enterPressed;
    }

    void PhoneLockedWindow::LockingTimer::clear() noexcept
    {
        enterPressed = false;
    }

    bool PhoneLockedWindow::LockingTimer::cached() noexcept
    {
        if (xTaskGetTickCount() - unLockStartTime >= unLockTime) {
            clear();
        }
        return enterPressed;
    }

    PhoneLockedWindow::PhoneLockedWindow(app::Application *app, const std::string &name) : AppWindow(app, name)
    {
        buildInterface();

        preBuildDrawListHook = [this](std::list<Command> &cmd) { updateTime(); };
    }

    void PhoneLockedWindow::buildInterface()
    {
        AppWindow::buildInterface();

        using namespace style::desktop;

        time = new gui::Label(this, timeLabel::X, timeLabel::Y, timeLabel::Width, timeLabel::Height);
        time->setFilled(false);
        time->setBorderColor(gui::ColorNoColor);
        time->setFont(style::window::font::supersizemelight);
        time->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));

        dayText = new gui::Label(this, dayLabel::X, dayLabel::Y, dayLabel::Width, dayLabel::Height);
        dayText->setFilled(false);
        dayText->setBorderColor(gui::ColorNoColor);
        dayText->setFont(style::window::font::biglight);
        dayText->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
    }

    top_bar::Configuration PhoneLockedWindow::configureTopBar(top_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.disable(top_bar::Indicator::Time);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(top_bar::Indicator::Lock);
        appConfiguration.enable(top_bar::Indicator::Battery);
        appConfiguration.enable(top_bar::Indicator::Signal);
        appConfiguration.enable(top_bar::Indicator::SimCard);
        return appConfiguration;
    }

    void PhoneLockedWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        bottomBar->setActive(BottomBar::Side::RIGHT, false);
        bottomBar->setText(BottomBar::Side::CENTER, utils::translate("app_desktop_unlock"));
        bottomBar->setActive(BottomBar::Side::LEFT, false);

        application->bus.sendUnicast(std::make_shared<TimersProcessingStopMessage>(), service::name::service_time);

        // To be added
        // buildNotifications(app);
    }

    bool PhoneLockedWindow::processLongReleaseEvent(const InputEvent &inputEvent)
    {
        if (inputEvent.is(KeyCode::KEY_RF)) {

            application->switchWindow(gui::popup::window::power_off_window);
            return true;
        }
        // check if any of the lower inheritance onInput methods catch the event
        return AppWindow::onInput(inputEvent);
    }

    bool PhoneLockedWindow::processShortReleaseEvent(const InputEvent &inputEvent)
    {
        // if enter was pressed
        if (lockingTimer.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

            application->handlePhoneUnLock();
            return true;
        }
        else if (lockingTimer.storeEnter(inputEvent)) {
            return true;
        }
        // back not allowed on blocked screen
        else if (inputEvent.is(KeyCode::KEY_RF)) {
            application->switchWindow(gui::popup::window::phone_lock_info_window);
            return true;
        }
        // check if any of the lower inheritance onInput methods catch the event
        else if (AppWindow::onInput(inputEvent)) {
            return true;
        }

        application->switchWindow(gui::popup::window::phone_lock_info_window);

        return true;
    }

    bool PhoneLockedWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isLongRelease()) {
            return processLongReleaseEvent(inputEvent);
        }
        else if (inputEvent.isShortRelease()) {
            return processShortReleaseEvent(inputEvent);
        }
        return AppWindow::onInput(inputEvent);
    }

    bool PhoneLockedWindow::updateTime()
    {
        using namespace utils::time;
        auto ret       = AppWindow::updateTime();
        auto timestamp = utils::time::Timestamp();
        if (time != nullptr) {
            auto fmt = utils::dateAndTimeSettings.isTimeFormat12()
                           ? Locale::format(Locale::TimeFormat::FormatTime12HShort)
                           : Locale::format(Locale::TimeFormat::FormatTime24H);
            time->setText(timestamp.str(fmt));
        }
        if (dayText != nullptr) {
            dayText->setText(timestamp.str("%A, %d %b"));
        }
        return ret;
    }
} /* namespace gui */

A module-apps/popups/lock-popups/PhoneLockedWindow.hpp => module-apps/popups/lock-popups/PhoneLockedWindow.hpp +50 -0
@@ 0,0 1,50 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <AppWindow.hpp>
#include <gui/widgets/Label.hpp>
#include <Translator.hpp>

namespace app
{
    class ApplicationDesktop;
}

namespace gui
{
    class PhoneLockedWindow : public AppWindow
    {
      protected:
        gui::Label *time    = nullptr;
        gui::Label *dayText = nullptr;

        /// Locking timer on pressing enter
        class LockingTimer
        {
            bool enterPressed        = false;
            uint32_t unLockStartTime = 0;
            uint32_t unLockTime      = 3000;

          public:
            bool storeEnter(const InputEvent &evt);
            void clear() noexcept;
            bool cached() noexcept;
        } lockingTimer;

        bool processLongReleaseEvent(const InputEvent &inputEvent);
        bool processShortReleaseEvent(const InputEvent &inputEvent);

      public:
        PhoneLockedWindow(app::Application *app, const std::string &name);

        bool onInput(const InputEvent &inputEvent) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void buildInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;

        bool updateTime() override;
    };

} /* namespace gui */

A module-apps/popups/lock-popups/PhoneUnLockWindow.cpp => module-apps/popups/lock-popups/PhoneUnLockWindow.cpp +135 -0
@@ 0,0 1,135 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneUnLockWindow.hpp"

#include <service-appmgr/Controller.hpp>
#include <locks/data/LockData.hpp>
#include <locks/widgets/PhoneLockBox.hpp>
#include <popups/data/PopupRequestParams.hpp>

namespace gui
{
    PhoneUnlockWindow::PhoneUnlockWindow(app::Application *app, const std::string &window_name)
        : PinLockBaseWindow(app, window_name)
    {
        buildInterface();
    }

    void PhoneUnlockWindow::rebuild()
    {
        destroyInterface();
        buildInterface();
    }
    void PhoneUnlockWindow::buildInterface()
    {
        AppWindow::buildInterface();
        LockWindow::build();
    }

    void PhoneUnlockWindow::destroyInterface()
    {
        erase();
    }

    void PhoneUnlockWindow::setVisibleState()
    {
        restore();
        if (lock->isState(locks::Lock::LockState::InputRequired)) {
            lockBox->setVisibleStateInputRequired(LockBox::InputActionType::ProvideInput);
        }
        else if (lock->isState(locks::Lock::LockState::InputInvalidRetryRequired)) {
            lockBox->setVisibleStateInputInvalid(LockBox::InputErrorType::InvalidInput, lock->getAttemptsLeft());
        }
        else if (lock->isState(locks::Lock::LockState::Blocked)) {
            lockBox->setVisibleStateBlocked();
        }
    }

    top_bar::Configuration PhoneUnlockWindow::configureTopBar(top_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.disable(top_bar::Indicator::Time);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(top_bar::Indicator::Lock);
        appConfiguration.enable(top_bar::Indicator::Battery);
        appConfiguration.enable(top_bar::Indicator::Signal);
        appConfiguration.enable(top_bar::Indicator::SimCard);
        return appConfiguration;
    }

    void PhoneUnlockWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (auto lockData = dynamic_cast<locks::LockData *>(data)) {

            rebuild();

            lock    = std::make_unique<locks::Lock>(lockData->getLock());
            lockBox = std::make_unique<PhoneLockBox>(this);
            lockBox->buildLockBox(lock->getMaxInputSize());
            setVisibleState();
        }

        // Lock need to exist in that window flow
        assert(lock);
    }

    bool PhoneUnlockWindow::onInput(const InputEvent &inputEvent)
    {
        if (!inputEvent.isShortRelease()) {
            return AppWindow::onInput(inputEvent);
        }
        else if (inputEvent.is(KeyCode::KEY_RF) && bottomBar->isActive(BottomBar::Side::RIGHT)) {
            if (usesNumericKeys()) {
                lock->clearAttempt();
            }
            else if (lock->isState(locks::Lock::LockState::InputInvalidRetryRequired)) {
                lock->consumeState();
            }
            application->returnToPreviousWindow();
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_PND)) {
            if (usesNumericKeys()) {
                lock->popChar();
                lockBox->popChar(lock->getCharCount());
                bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify());
                return true;
            }
        }
        else if (inputEvent.isDigit()) {

            if (usesNumericKeys() && lock->canPut()) {

                lockBox->putChar(lock->getCharCount());
                lock->putNextChar(inputEvent.numericValue());

                if (lock->canVerify()) {
                    application->verifyPhoneLockInput(lock->getInput());
                }

                return true;
            }
        }

        else if (inputEvent.is(KeyCode::KEY_ENTER) && bottomBar->isActive(BottomBar::Side::CENTER)) {
            if (lock->isState(locks::Lock::LockState::Blocked)) {
                application->returnToPreviousWindow();
            }
            else {
                lock->consumeState();
                lock->clearAttempt();
                setVisibleState();
            }
            return true;
        }

        // check if any of the lower inheritance onInput methods catch the event
        return AppWindow::onInput(inputEvent);
    }

    auto PhoneUnlockWindow::usesNumericKeys() const noexcept -> bool
    {
        return lock && (lock->isState(locks::Lock::LockState::InputRequired));
    }
} /* namespace gui */

A module-apps/popups/lock-popups/PhoneUnLockWindow.hpp => module-apps/popups/lock-popups/PhoneUnLockWindow.hpp +30 -0
@@ 0,0 1,30 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <locks/widgets/Lock.hpp>
#include <locks/widgets/LockBox.hpp>
#include <locks/windows/PinLockBaseWindow.hpp>

namespace gui
{
    class PhoneUnlockWindow : public PinLockBaseWindow
    {
        std::unique_ptr<LockBox> lockBox = nullptr;

        void setVisibleState();
        [[nodiscard]] auto usesNumericKeys() const noexcept -> bool;

      public:
        PhoneUnlockWindow(app::Application *app, const std::string &window_name);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const InputEvent &inputEvent) override;

        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
    };

} /* namespace gui */

R module-apps/application-desktop/presenter/PowerOffPresenter.cpp => module-apps/popups/presenter/PowerOffPresenter.cpp +0 -0
R module-apps/application-desktop/presenter/PowerOffPresenter.hpp => module-apps/popups/presenter/PowerOffPresenter.hpp +0 -0
M module-apps/windows/AppWindow.cpp => module-apps/windows/AppWindow.cpp +7 -1
@@ 152,11 152,17 @@ namespace gui
            return true;
        }

        if (inputEvent.isLongRelease() && inputEvent.is(gui::KeyCode::KEY_RF)) {
        if (inputEvent.isLongRelease(gui::KeyCode::KEY_RF)) {
            LOG_INFO("exit to main menu");
            app::manager::Controller::sendAction(application, app::manager::actions::Home);
        }

        if (inputEvent.isLongRelease(gui::KeyCode::KEY_PND)) {
            LOG_INFO("Locking phone");

            application->handlePhoneLock();
        }

        if ((inputEvent.isShortRelease())) {
            switch (inputEvent.getKeyCode()) {
            case KeyCode::HEADSET_VOLUP:

M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +34 -2
@@ 134,7 134,8 @@ namespace app::manager
          ApplicationManagerBase(std::move(launchers)), rootApplicationName{_rootApplicationName},
          actionsRegistry{[this](ActionEntry &action) { return handleAction(action); }}, notificationProvider(this),
          autoLockEnabled(false), settings(std::make_unique<settings::Settings>(this)),
          phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
          phoneModeObserver(std::make_unique<sys::phone_modes::Observer>()),
          phoneLockHandler(locks::PhoneLockHandler(this))
    {
        autoLockTimer = sys::TimerFactory::createSingleShotTimer(
            this, timerBlock, sys::timer::InfiniteTimeout, [this](sys::Timer &) { onPhoneLocked(); });


@@ 149,6 150,22 @@ namespace app::manager
        utils::setDisplayLanguage(
            settings->getValue(settings::SystemProperties::displayLanguage, settings::SettingsScope::Global));

        phoneLockHandler.enablePhoneLock((utils::getNumericValue<bool>(
            settings->getValue(settings::SystemProperties::lockScreenPasscodeIsOn, settings::SettingsScope::Global))));

        phoneLockHandler.setPhoneLockHash(
            settings->getValue(settings::SystemProperties::lockPassHash, settings::SettingsScope::Global));

        settings->registerValueChange(
            settings::SystemProperties::lockScreenPasscodeIsOn,
            [this](const std::string &value) { phoneLockHandler.enablePhoneLock(utils::getNumericValue<bool>(value)); },
            settings::SettingsScope::Global);

        settings->registerValueChange(
            settings::SystemProperties::lockPassHash,
            [this](const std::string &value) { phoneLockHandler.setPhoneLockHash(value); },
            settings::SettingsScope::Global);

        settings->registerValueChange(
            settings::SystemProperties::displayLanguage,
            [this](std::string value) { displayLanguageChanged(value); },


@@ 402,6 419,14 @@ namespace app::manager
            handleDBResponse(response);
            return sys::msgHandled();
        });
        connect(typeid(lock::LockPhone),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleLockRequest(); });
        connect(typeid(lock::UnlockPhone),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleUnlockRequest(); });
        connect(typeid(lock::LockPhoneInput), [&](sys::Message *request) -> sys::MessagePointer {
            auto msg = static_cast<lock::LockPhoneInput *>(request);
            return phoneLockHandler.verifyPhoneLockInput(msg->getInputData());
        });

        connect(typeid(app::manager::DOMRequest), [&](sys::Message *request) { return handleDOMRequest(request); });



@@ 614,10 639,17 @@ namespace app::manager
    auto ApplicationManager::handleHomeAction(ActionEntry &action) -> ActionProcessStatus
    {
        action.setTargetApplication(rootApplicationName);
        SwitchRequest switchRequest(ServiceName, rootApplicationName, gui::name::window::main_window, nullptr);

        SwitchRequest switchRequest(ServiceName, rootApplicationName, resolveHomeWindow(), nullptr);
        return handleSwitchApplication(&switchRequest) ? ActionProcessStatus::Accepted : ActionProcessStatus::Dropped;
    }

    auto ApplicationManager::resolveHomeWindow() -> std::string
    {
        return phoneLockHandler.isPhoneLocked() ? gui::popup::window::phone_lock_window
                                                : gui::name::window::main_window;
    }

    auto ApplicationManager::handleLaunchAction(ActionEntry &action) -> ActionProcessStatus
    {
        auto launchParams = static_cast<ApplicationLaunchData *>(action.params.get());

M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +5 -0
@@ 31,6 31,7 @@
#include <service-eink/Common.hpp>

#include <notifications/NotificationProvider.hpp>
#include <locks/handlers/PhoneLockHandler.hpp>

namespace app
{


@@ 124,6 125,7 @@ namespace app::manager
        auto handleAction(ActionEntry &action) -> ActionProcessStatus;
        void handleActionRequest(ActionRequest *actionMsg);
        auto handleHomeAction(ActionEntry &action) -> ActionProcessStatus;
        auto resolveHomeWindow() -> std::string;
        auto handleLaunchAction(ActionEntry &action) -> ActionProcessStatus;
        auto handleActionOnFocusedApp(ActionEntry &action) -> ActionProcessStatus;
        auto handlePhoneModeChangedAction(ActionEntry &action) -> ActionProcessStatus;


@@ 180,6 182,9 @@ namespace app::manager
                                        // lock screen.
        std::unique_ptr<settings::Settings> settings;
        std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;

        locks::PhoneLockHandler phoneLockHandler;

        void displayLanguageChanged(std::string value);
        void lockTimeChanged(std::string value);
        void inputLanguageChanged(std::string value);