~aleteoryx/muditaos

06d16390c21c37457bc875e841bb12039d1123d7 — Lefucjusz 2 years ago 3812cfd
[MOS-1021] Fix blocked passcode behavior

Fix of the issue that after blocking
passcode from Center, Pure would still
display passcode input popup; providing
valid passcode there would result in
phone entering invalid state, where it
behaved as if it was unlocked, but
with blocked passcode.
M module-apps/apps-common/locks/data/PhoneLockMessages.hpp => module-apps/apps-common/locks/data/PhoneLockMessages.hpp +7 -22
@@ 48,13 48,13 @@ namespace locks
    class SkippedSetPhoneLock : public sys::DataMessage
    {};

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

      public:
        explicit UnLockPhoneInput(std::vector<unsigned int> inputData) : inputData(std::move(inputData))
        explicit UnlockPhoneInput(std::vector<unsigned> inputData) : inputData(std::move(inputData))
        {}

        [[nodiscard]] auto getInputData() const noexcept


@@ 88,10 88,10 @@ namespace locks
    class NextPhoneUnlockAttemptLockTime : public sys::DataMessage
    {
      private:
        time_t nextPhoneUnlockAttemptLockTime;
        std::time_t nextPhoneUnlockAttemptLockTime;

      public:
        explicit NextPhoneUnlockAttemptLockTime(time_t nextPhoneUnlockAttemptLockTime)
        explicit NextPhoneUnlockAttemptLockTime(std::time_t nextPhoneUnlockAttemptLockTime)
            : nextPhoneUnlockAttemptLockTime(nextPhoneUnlockAttemptLockTime)
        {}



@@ 101,10 101,10 @@ namespace locks
        }
    };

    class ExternalUnLockPhone : public UnLockPhoneInput
    class ExternalUnlockPhone : public UnlockPhoneInput
    {
      public:
        explicit ExternalUnLockPhone(std::vector<unsigned int> inputData) : UnLockPhoneInput(std::move(inputData))
        explicit ExternalUnlockPhone(std::vector<unsigned> inputData) : UnlockPhoneInput(std::move(inputData))
        {}
    };



@@ 122,19 122,4 @@ namespace locks
            return value;
        }
    };

    class ExternalUnLockPhoneInfo : public sys::DataMessage
    {
      private:
        unsigned int attemptsLeft;

      public:
        explicit ExternalUnLockPhoneInfo(unsigned int attemptsLeft) : attemptsLeft(attemptsLeft)
        {}

        [[nodiscard]] auto getAttemptsLeft() const noexcept
        {
            return attemptsLeft;
        }
    };
} // namespace locks

M module-apps/apps-common/locks/handlers/PhoneLockHandler.cpp => module-apps/apps-common/locks/handlers/PhoneLockHandler.cpp +63 -49
@@ 13,7 13,11 @@

#include <chrono>

using namespace std::chrono_literals;
namespace
{
    using namespace std::chrono_literals;
    constexpr auto secondsPerMinute = std::chrono::duration_cast<std::chrono::seconds>(1min).count();
} // namespace

namespace locks
{


@@ 22,7 26,7 @@ namespace locks
          lock(Lock::LockState::InputRequired, initialNoLockTimeAttemptsLeft)
    {
        phoneLockTimer = sys::TimerFactory::createPeriodicTimer(
            owner, phoneLockTimerName, std::chrono::seconds{(1)}, [this](sys::Timer &) {
            owner, phoneLockTimerName, std::chrono::seconds{1}, [this](sys::Timer &) {
                if (lockedFor == 0) {
                    phoneLockTimer.stop();
                    phoneLockTimeUpdateInfoAction(LockTimerState::Stop);


@@ 32,8 36,7 @@ namespace locks
                if (lockedFor == nextUnlockAttemptLockTime) {
                    phoneLockTimeUpdateInfoAction(LockTimerState::Start);
                }
                else if (lockedFor % std::chrono::duration_cast<std::chrono::seconds>(1min).count() == 0 ||
                         lockedFor <= std::chrono::duration_cast<std::chrono::seconds>(1min).count()) {
                else if (((lockedFor % secondsPerMinute) == 0) || (lockedFor <= secondsPerMinute)) {
                    phoneLockTimeUpdateInfoAction(LockTimerState::Counting);
                }



@@ 53,24 56,26 @@ namespace locks
    void PhoneLockHandler::setPhoneLockHash(const std::string &value)
    {
        if (!value.empty()) {
            phoneLockHash = utils::getNumericValue<unsigned int>(value);
            phoneLockHash = utils::getNumericValue<unsigned>(value);
        }
        else {
            phoneLockHash = 0;
        }
    }

    void PhoneLockHandler::setPhoneLockTime(const time_t time)
    void PhoneLockHandler::setPhoneLockTime(std::time_t time)
    {
        if (time != 0) {
            lockedFor      = time;
            lock.lockState = Lock::LockState::Blocked;
            phoneLockTimeUpdateInfoAction(LockTimerState::Start);
            phoneLockTimer.start();
        if (time == 0) {
            return;
        }

        lockedFor      = time;
        lock.lockState = Lock::LockState::Blocked;
        phoneLockTimeUpdateInfoAction(LockTimerState::Start);
        phoneLockTimer.start();
    }

    void PhoneLockHandler::setNextUnlockAttemptLockTime(time_t time)
    void PhoneLockHandler::setNextUnlockAttemptLockTime(std::time_t time)
    {
        nextUnlockAttemptLockTime = time;
    }


@@ 123,6 128,16 @@ namespace locks
        }
    }

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

    void PhoneLockHandler::phoneUnlockAction()
    {
        phoneState = PhoneState::Unlocked;


@@ 130,12 145,12 @@ namespace locks
        owner->bus.sendMulticast(std::make_shared<locks::UnlockedPhone>(), sys::BusChannel::PhoneLockChanges);
    }

    void PhoneLockHandler::phoneInputRequiredAction(ReasonForRequest reqReason)
    void PhoneLockHandler::phoneInputRequiredAction(RequestReason reqReason)
    {
        auto data = std::make_unique<gui::PhoneUnlockInputRequestParams>(
            gui::popup::ID::PhoneLockInput, lock, phoneLockInputTypeAction);
        // If it's for MTP, don't show the input passcode popup if it's already on the screen
        data->ignoreIfTheSamePopupIsOnTopOfTheStack = (reqReason == ReasonForRequest::MTPUnlock);
        data->ignoreIfTheSamePopupIsOnTopOfTheStack = (reqReason == RequestReason::MTPUnlock);
        app::manager::Controller::sendAction(owner, app::manager::actions::ShowPopup, std::move(data));
    }



@@ 176,31 191,24 @@ namespace locks
                                                 gui::popup::ID::PhoneLockChangeInfo, lock, phoneLockInputTypeAction));
    }

    void PhoneLockHandler::phoneExternalUnlockInfoAction()
    {
        owner->bus.sendMulticast(std::make_shared<locks::ExternalUnLockPhoneInfo>(lock.getAttemptsLeft()),
                                 sys::BusChannel::PhoneLockChanges);
    }

    void PhoneLockHandler::phoneLockTimeUpdateInfoAction(LockTimerState state)
    {
        std::string textToPrint;
        auto rebuildRequired = state == LockTimerState::Start;
        auto rebuildRequired = (state == LockTimerState::Start);

        if (state == LockTimerState::Start || state == LockTimerState::Counting) {
            if (lockedFor <= std::chrono::duration_cast<std::chrono::seconds>(1min).count()) {
            if (lockedFor <= secondsPerMinute) {
                using utils::time::Duration;
                const Duration remainingDuration{static_cast<uint32_t>(std::time_t{lockedFor})};
                const Duration remainingDuration{lockedFor};
                textToPrint = remainingDuration.str(Duration::DisplayedFormat::Fixed0M0S);

                if (lockedFor == std::chrono::duration_cast<std::chrono::seconds>(1min).count()) {
                if (lockedFor == secondsPerMinute) {
                    rebuildRequired = true;
                }
            }
            else {
                textToPrint =
                    std::to_string(lockedFor / std::chrono::duration_cast<std::chrono::seconds>(1min).count()) +
                    utils::translate("phone_lock_blocked_information_minutes");
                textToPrint = std::to_string(lockedFor / secondsPerMinute) +
                              utils::translate("phone_lock_blocked_information_minutes");
            }

            setNextUnlockAttemptFormattedTime();


@@ 222,7 230,7 @@ namespace locks
    {
        phoneLockEnabled = value;
        settings->setValue(settings::SystemProperties::lockScreenPasscodeIsOn,
                           std::to_string(phoneLockEnabled),
                           std::to_string(static_cast<unsigned>(phoneLockEnabled)),
                           settings::SettingsScope::Global);
    }



@@ 253,7 261,7 @@ namespace locks
        saveNoLockTimeAttemptsLeft();
    }

    sys::MessagePointer PhoneLockHandler::handleUnlockRequest(ReasonForRequest reqReason)
    sys::MessagePointer PhoneLockHandler::handleUnlockRequest(RequestReason reqReason)
    {
        setPhoneLockInputTypeAction(PhoneLockInputTypeAction::Unlock);



@@ 262,7 270,13 @@ namespace locks
            phoneUnlockAction();
            return sys::msgHandled();
        }

        if (lock.isState(Lock::LockState::Blocked)) {
            /* Prevent showing invalid window when connecting blocked phone to PC */
            if ((lockedFor != 0) && (reqReason == RequestReason::MTPUnlock)) {
                return sys::msgHandled();
            }

            if (lockedFor == 0) {
                lock.lockState = Lock::LockState::InputRequired;
            }


@@ 361,15 375,15 @@ namespace locks
            checkPhoneLockInputTypeAction(PhoneLockInputTypeAction::Set)) {
            return verifyPhoneLockChangeInput(inputData);
        }
        else {
            return verifyPhoneUnlockInput(inputData);
        }
        return verifyPhoneUnlockInput(inputData);
    }

    void PhoneLockHandler::comparePhoneLockHashCode(LockInput inputData)
    void PhoneLockHandler::processPhoneLockHashCode(LockInput inputData)
    {
        const uint32_t hash = getHash(inputData);
        lock.attemptsLeft   = (lock.attemptsLeft > 0 ? lock.attemptsLeft - 1 : 0);
        const auto hash = getHash(inputData);
        if (lock.attemptsLeft > 0) {
            --lock.attemptsLeft;
        }

        if (phoneLockHash == hash) {
            lock.lockState    = Lock::LockState::Unlocked;


@@ 382,6 396,7 @@ namespace locks
        else {
            increaseLockTime();
            lock.lockState = Lock::LockState::Blocked;
            phoneBlockedPopupsCloseAction();
        }

        broadcastLockTime();


@@ 390,7 405,7 @@ namespace locks

    sys::MessagePointer PhoneLockHandler::verifyPhoneUnlockInput(LockInput inputData)
    {
        comparePhoneLockHashCode(inputData);
        processPhoneLockHashCode(inputData);

        if (lock.isState(Lock::LockState::Unlocked)) {
            resolvePhoneLockAction();


@@ 431,21 446,17 @@ namespace locks
        }

        if (lock.isState(Lock::LockState::Blocked)) {
            phoneExternalUnlockInfoAction();
            broadcastLockTime();
            if (lockedFor != 0) {
                return sys::msgHandled();
            }
        }

        comparePhoneLockHashCode(inputData);
        processPhoneLockHashCode(inputData);

        if (lock.isState(Lock::LockState::Unlocked)) {
            phoneUnlockAction();
        }
        else {
            phoneExternalUnlockInfoAction();
        }

        return sys::msgHandled();
    }


@@ 489,8 500,13 @@ namespace locks

    void PhoneLockHandler::increaseLockTime() noexcept
    {
        nextUnlockAttemptLockTime != 0 ? nextUnlockAttemptLockTime *= locks::phoneLockTimeMultiplier
                                       : nextUnlockAttemptLockTime = initialLockTime;
        if (nextUnlockAttemptLockTime == 0) {
            nextUnlockAttemptLockTime = initialLockTime;
        }
        else {
            nextUnlockAttemptLockTime *= locks::phoneLockTimeMultiplier;
        }

        lockedFor = nextUnlockAttemptLockTime;

        phoneLockTimer.start();


@@ 501,17 517,16 @@ namespace locks

    void PhoneLockHandler::setNextUnlockAttemptFormattedTime() noexcept
    {
        if (lockedFor < std::chrono::duration_cast<std::chrono::seconds>(1min).count()) {
        if (lockedFor < secondsPerMinute) {
            lock.setNextUnlockAttemptFormattedTime(std::to_string(lockedFor) +
                                                   utils::translate("phone_lock_blocked_information_seconds"));
        }
        else if (lockedFor < std::chrono::duration_cast<std::chrono::seconds>(2min).count()) {
        else if (lockedFor < (2 * secondsPerMinute)) {
            lock.setNextUnlockAttemptFormattedTime(utils::translate("phone_lock_blocked_information_minute"));
        }
        else {
            lock.setNextUnlockAttemptFormattedTime(
                std::to_string(lockedFor / std::chrono::duration_cast<std::chrono::seconds>(1min).count()) +
                utils::translate("phone_lock_blocked_information_minutes"));
            lock.setNextUnlockAttemptFormattedTime(std::to_string(lockedFor / secondsPerMinute) +
                                                   utils::translate("phone_lock_blocked_information_minutes"));
        }
    }



@@ 528,5 543,4 @@ namespace locks
            std::make_shared<locks::NextPhoneUnlockAttemptLockTime>(std::time(nullptr) + lockedFor),
            sys::BusChannel::PhoneLockChanges);
    }

} // namespace locks

M module-apps/apps-common/locks/handlers/PhoneLockHandler.hpp => module-apps/apps-common/locks/handlers/PhoneLockHandler.hpp +19 -20
@@ 14,14 14,14 @@
namespace locks
{
    constexpr auto phoneLockTimerName                    = "PhoneLockTimer";
    constexpr unsigned int initialNoLockTimeAttemptsLeft = 3;
    constexpr time_t initialLockTime                     = 15;
    constexpr unsigned int phoneLockTimeMultiplier       = 2;
    constexpr unsigned initialNoLockTimeAttemptsLeft     = 3;
    constexpr std::time_t initialLockTime                = 15;
    constexpr unsigned phoneLockTimeMultiplier           = 2;

    class PhoneLockHandler
    {
      public:
        enum class ReasonForRequest
        enum class RequestReason
        {
            Default = 0, // For default behaviors
            MTPUnlock


@@ 31,17 31,17 @@ namespace locks
        enum class PhoneState
        {
            Locked,
            Unlocked,
            Unlocked
        };

        enum class LockTimerState
        {
            Start,
            Counting,
            Stop,
            Stop
        };

        sys::Service *owner;
        sys::Service *owner = nullptr;
        std::shared_ptr<settings::Settings> settings;
        Lock lock;
        bool phoneLockEnabled = true;


@@ 49,12 49,12 @@ namespace locks
        PhoneState phoneState                             = PhoneState::Locked;
        PhoneLockInputTypeAction phoneLockInputTypeAction = PhoneLockInputTypeAction::Unlock;

        unsigned int phoneLockHash = std::numeric_limits<unsigned>::max();
        std::vector<unsigned int> storedInputData;
        unsigned phoneLockHash = std::numeric_limits<unsigned>::max();
        std::vector<unsigned> storedInputData;

        sys::TimerHandle phoneLockTimer;
        time_t lockedFor                 = 0;
        time_t nextUnlockAttemptLockTime = 0;
        std::time_t lockedFor                 = 0;
        std::time_t nextUnlockAttemptLockTime = 0;

        void setPhoneLockInputTypeAction(PhoneLockInputTypeAction _phoneLockInputTypeAction);
        bool checkPhoneLockInputTypeAction(PhoneLockInputTypeAction _phoneLockInputTypeAction);


@@ 72,24 72,24 @@ namespace locks
        void phoneLockDisableAction();
        void phoneLockChangeAction();
        void phoneLockSetAction();
        void phoneInputRequiredAction(ReasonForRequest reqReason = ReasonForRequest::Default);
        void phoneInputRequiredAction(RequestReason reqReason = RequestReason::Default);
        void phoneUnlockPopupsCloseAction();
        void phoneBlockedPopupsCloseAction();
        void phoneLockChangeInfoAction();
        void phoneExternalUnlockInfoAction();
        void phoneLockTimeUpdateInfoAction(LockTimerState state);

        void checkNewPhoneLock();
        void resolvePhoneLockAction();

        void comparePhoneLockHashCode(LockInput inputData);
        void processPhoneLockHashCode(LockInput inputData);
        sys::MessagePointer verifyPhoneUnlockInput(LockInput inputData);
        sys::MessagePointer verifyPhoneLockChangeInput(LockInput inputData);

      public:
        explicit PhoneLockHandler(sys::Service *owner, std::shared_ptr<settings::Settings> settings);
        PhoneLockHandler(sys::Service *owner, std::shared_ptr<settings::Settings> settings);

        sys::MessagePointer handleLockRequest();
        sys::MessagePointer handleUnlockRequest(ReasonForRequest reqReason = ReasonForRequest::Default);
        sys::MessagePointer handleUnlockRequest(RequestReason reqReason = RequestReason::Default);
        sys::MessagePointer handleUnlockCancelRequest();
        sys::MessagePointer handleEnablePhoneLock();
        sys::MessagePointer handleDisablePhoneLock();


@@ 104,13 104,12 @@ namespace locks
        void setPhoneLockHash(const std::string &value);
        [[nodiscard]] bool isPhoneLocked() const noexcept;

        void setPhoneLockTime(time_t time);
        void setNextUnlockAttemptLockTime(time_t time);
        void setNoLockTimeAttemptsLeft(unsigned int attemptsNumber);
        void setPhoneLockTime(std::time_t time);
        void setNextUnlockAttemptLockTime(std::time_t time);
        void setNoLockTimeAttemptsLeft(unsigned attemptsNumber);
        void increaseLockTime() noexcept;
        void setNextUnlockAttemptFormattedTime() noexcept;
        void resetLockTime() noexcept;
        void broadcastLockTime() noexcept;
    };

} // namespace locks

M module-apps/apps-common/locks/handlers/PhoneLockSubject.cpp => module-apps/apps-common/locks/handlers/PhoneLockSubject.cpp +1 -1
@@ 54,6 54,6 @@ namespace locks

    void PhoneLockSubject::verifyInput(LockInput inputData)
    {
        owner->bus.sendUnicast(std::make_shared<UnLockPhoneInput>(inputData), service::name::appmgr);
        owner->bus.sendUnicast(std::make_shared<UnlockPhoneInput>(inputData), service::name::appmgr);
    }
} // namespace locks

M module-apps/apps-common/locks/widgets/Lock.cpp => module-apps/apps-common/locks/widgets/Lock.cpp +2 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Lock.hpp"


@@ 18,7 18,7 @@ namespace locks
        }
    }

    void Lock::putNextChar(unsigned int c)
    void Lock::putNextChar(unsigned c)
    {
        if (maxInputSize > inputValue.size()) {
            inputValue.push_back(c);


@@ 41,5 41,4 @@ namespace locks
    {
        nextUnlockAttemptFormattedTime = time;
    }

} // namespace locks

M module-apps/apps-common/locks/widgets/Lock.hpp => module-apps/apps-common/locks/widgets/Lock.hpp +15 -15
@@ 1,7 1,8 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <vector>
#include <string>
#include <functional>


@@ 31,12 32,12 @@ namespace locks
        {
            return lockState;
        }
        [[nodiscard]] unsigned int getMaxInputSize() const noexcept
        [[nodiscard]] unsigned getMaxInputSize() const noexcept
        {
            return maxInputSize;
        }
        /// returns current position of a Input character to be inserted
        [[nodiscard]] unsigned int getCharCount() const noexcept
        [[nodiscard]] unsigned getCharCount() const noexcept
        {
            return inputValue.size();
        }


@@ 48,11 49,11 @@ namespace locks
        {
            return getCharCount() >= minInputSize;
        }
        [[nodiscard]] std::vector<unsigned int> getInput() const
        [[nodiscard]] std::vector<unsigned> getInput() const
        {
            return inputValue;
        }
        [[nodiscard]] unsigned int getAttemptsLeft() const noexcept
        [[nodiscard]] unsigned getAttemptsLeft() const noexcept
        {
            return attemptsLeft;
        }


@@ 70,7 71,7 @@ namespace locks
        }
        void setNextUnlockAttemptFormattedTime(const std::string &time);

        void putNextChar(unsigned int c);
        void putNextChar(unsigned c);
        /// removes a last character passed to Lock via putNextChar. The last character can not be popped
        void popChar();
        /// clear all characters passed to the Lock


@@ 78,24 79,24 @@ namespace locks
        /// consumes LockState::InputInvalid state and LockState::NewInputInvalid
        void consumeState() noexcept;

        explicit Lock(LockState state, unsigned int attemptsLeft = unlimitedNumOfAttempts)
        explicit Lock(LockState state, unsigned attemptsLeft = unlimitedNumOfAttempts)
            : lockState{state}, attemptsLeft{attemptsLeft}
        {}

      private:
        std::string lockName;
        LockState lockState       = LockState::Unlocked;
        unsigned int attemptsLeft = 0;
        unsigned attemptsLeft     = 0;
        std::string nextUnlockAttemptFormattedTime;

        std::vector<unsigned int> inputValue;
        unsigned int maxInputSize = defaultInputSize;
        unsigned int minInputSize = defaultInputSize;
        std::vector<unsigned> inputValue;
        unsigned maxInputSize = defaultInputSize;
        unsigned minInputSize = defaultInputSize;

        static constexpr unsigned int defaultInputSize       = 4;
        static constexpr unsigned int unlimitedNumOfAttempts = std::numeric_limits<unsigned int>::max();
        static constexpr unsigned defaultInputSize       = 4;
        static constexpr unsigned unlimitedNumOfAttempts = std::numeric_limits<unsigned>::max();

        void setInputSizeBounds(unsigned int _minInputSize, unsigned int _maxInputSize)
        void setInputSizeBounds(unsigned _minInputSize, unsigned _maxInputSize)
        {
            minInputSize = _minInputSize;
            maxInputSize = _maxInputSize;


@@ 104,5 105,4 @@ namespace locks
        friend class PhoneLockHandler;
        friend class SimLockHandler;
    };

} // namespace locks

M module-apps/apps-common/locks/widgets/PhoneLockBox.cpp => module-apps/apps-common/locks/widgets/PhoneLockBox.cpp +3 -6
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Lock.hpp"


@@ 69,14 69,12 @@ namespace gui
        LockWindow->pinLabelsBox->setVisible(true);

        switch (type) {
        case LockBox::InputActionType::ProvideInput: {
        case LockBox::InputActionType::ProvideInput:
            LockWindow->setText(textForInputRequired, LockInputWindow::TextType::Primary);
            break;
        }
        case LockBox::InputActionType::ProvideNewInput: {
        case LockBox::InputActionType::ProvideNewInput:
            LockWindow->setText(textForProvideNewInput, LockInputWindow::TextType::Primary);
            break;
        }
        case LockBox::InputActionType::ConfirmNewInput:
            LockWindow->setText(textForConfirmNewInput, LockInputWindow::TextType::Primary);
            break;


@@ 90,7 88,6 @@ namespace gui
    {
        switch (type) {
        case LockBox::InputErrorType::InvalidInput:

            LockWindow->setText(textForInvalidInput,
                                LockInputWindow::TextType::Primary,
                                {{LockWindow->getToken(LockInputWindow::Token::Attempts), static_cast<int>(value)}});

M module-apps/apps-common/notifications/NotificationsModel.cpp => module-apps/apps-common/notifications/NotificationsModel.cpp +2 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NotificationsModel.hpp"


@@ 8,7 8,6 @@ using namespace gui;

namespace
{

    bool hasTetheringNotification(app::manager::actions::NotificationsChangedParams *params)
    {
        const auto &notifications = params->getNotifications();


@@ 38,7 37,7 @@ NotificationsModel::NotificationsModel(NotificationsListPlacement listPlacement)

void NotificationsModel::attachPresenter(std::shared_ptr<NotificationsPresenter> notificationsPresenter)
{
    this->notificationsPresenter = notificationsPresenter;
    this->notificationsPresenter = std::move(notificationsPresenter);
}

bool NotificationsModel::hasDismissibleNotification() const noexcept

M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp => module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp +12 -13
@@ 34,12 34,10 @@ namespace gui

    void PhoneLockedWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        auto notificationsModel = wallpaperPresenter->getNotificationsModel();
        auto notificationData   = dynamic_cast<app::manager::actions::NotificationsChangedParams *>(data);
        if (notificationData) {
            notificationsModel->updateData(notificationData);
        }
        else {
        const auto notificationsModel = wallpaperPresenter->getNotificationsModel();
        const auto notificationData   = dynamic_cast<app::manager::actions::NotificationsChangedParams *>(data);

        if (notificationData == nullptr) {
            navBar->setActive(nav_bar::Side::Left, false);
            navBar->setActive(nav_bar::Side::Center, false);
            navBar->setActive(nav_bar::Side::Right, false);


@@ 47,11 45,11 @@ namespace gui
            return;
        }

        notificationsModel->updateData(notificationData);

        if (notificationsModel->isPhoneTimeLock()) {
            wallpaperPresenter->forceClockWallpaper();
            if (notificationData) {
                notificationsModel->updateData(notificationData);
            }
            notificationsModel->updateData(notificationData);

            if (!refreshedOnPhoneLockTimeLock) {
                application->refreshWindow(RefreshModes::GUI_REFRESH_DEEP);


@@ 63,7 61,7 @@ namespace gui
            navBar->setActive(nav_bar::Side::Right, false);
        }
        else {
            if (wallpaperPresenter->switchBackWallpaper() && notificationData) {
            if (wallpaperPresenter->switchBackWallpaper()) {
                notificationsModel->updateData(notificationData);
            }
            navBar->setActive(nav_bar::Side::Left, false);


@@ 104,7 102,6 @@ namespace gui
    bool PhoneLockedWindow::processLongReleaseEvent(const InputEvent &inputEvent)
    {
        if (inputEvent.is(KeyCode::KEY_RF)) {

            application->switchWindow(gui::popup::window::power_off_window);
        }
        return true;


@@ 120,14 117,16 @@ namespace gui
        if (inputEvent.isLongRelease()) {
            return processLongReleaseEvent(inputEvent);
        }
        else if (inputEvent.isShortRelease() && navBar->isActive(nav_bar::Side::Center)) {

        if (inputEvent.isShortRelease() && navBar->isActive(nav_bar::Side::Center)) {
            const auto requiredStage = (inputEvent.is(KeyCode::KEY_ENTER)) ? PhoneLockedInfoData::Stage::Waiting
                                                                           : PhoneLockedInfoData::Stage::Idle;
            application->switchWindow(gui::popup::window::phone_lock_info_window,
                                      std::make_unique<PhoneLockedInfoData>(requiredStage));
            return true;
        }
        else if (inputEvent.isShortRelease(KeyCode::KEY_LF) && navBar->isActive(nav_bar::Side::Left)) {

        if (inputEvent.isShortRelease(KeyCode::KEY_LF) && navBar->isActive(nav_bar::Side::Left)) {
            app::manager::Controller::sendAction(application,
                                                 app::manager::actions::EmergencyDial,
                                                 std::make_unique<SwitchData>(),

M module-services/service-desktop/endpoints/security/SecurityEndpointHelper.cpp => module-services/service-desktop/endpoints/security/SecurityEndpointHelper.cpp +1 -1
@@ 107,7 107,7 @@ namespace sdesktop::endpoints

        if (passCode.size() == PasscodeLength) {
            try {
                auto msg = std::make_shared<locks::ExternalUnLockPhone>(passCodeArrayToVecOfInts(passCode));
                auto msg = std::make_shared<locks::ExternalUnlockPhone>(passCodeArrayToVecOfInts(passCode));
                status   = owner->bus.sendUnicast(std::move(msg), service::name::appmgr)
                               ? http::Code::NoContent
                               : http::Code::InternalServerError;

M products/PurePhone/services/appmgr/ApplicationManager.cpp => products/PurePhone/services/appmgr/ApplicationManager.cpp +29 -24
@@ 181,51 181,56 @@ namespace app::manager
        });

        // PhoneLock connects
        connect(typeid(locks::LockPhone),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleLockRequest(); });
        connect(typeid(locks::UnlockPhone),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleUnlockRequest(); });
        connect(typeid(locks::UnlockPhoneForMTP), [&](sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleUnlockRequest(locks::PhoneLockHandler::ReasonForRequest::MTPUnlock);
        });
        connect(typeid(locks::CancelUnlockPhone), [&](sys::Message *request) -> sys::MessagePointer {
        connect(typeid(locks::LockPhone), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleLockRequest();
        });
        connect(typeid(locks::UnlockPhone), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleUnlockRequest();
        });
        connect(typeid(locks::UnlockPhoneForMTP), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleUnlockRequest(locks::PhoneLockHandler::RequestReason::MTPUnlock);
        });
        connect(typeid(locks::CancelUnlockPhone), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleUnlockCancelRequest();
        });
        connect(typeid(locks::UnLockPhoneInput), [&](sys::Message *request) -> sys::MessagePointer {
            auto data = static_cast<locks::UnLockPhoneInput *>(request);
        connect(typeid(locks::UnlockPhoneInput), [&](sys::Message *request) -> sys::MessagePointer {
            const auto data = static_cast<locks::UnlockPhoneInput *>(request);
            return phoneLockHandler.handlePhoneLockInput(data->getInputData());
        });
        connect(typeid(locks::EnablePhoneLock),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleEnablePhoneLock(); });
        connect(typeid(locks::DisablePhoneLock), [&](sys::Message *request) -> sys::MessagePointer {
        connect(typeid(locks::EnablePhoneLock), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleEnablePhoneLock();
        });
        connect(typeid(locks::DisablePhoneLock), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleDisablePhoneLock();
        });
        connect(typeid(locks::UnlockedPhone), [&](sys::Message *request) -> sys::MessagePointer {
        connect(typeid(locks::UnlockedPhone), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            autoLockTimer.start();
            return simLockHandler.askForSimUnlocking();
        });
        connect(typeid(locks::ChangePhoneLock),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleChangePhoneLock(); });
        connect(typeid(locks::SetPhoneLock),
                [&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleSetPhoneLock(); });
        connect(typeid(locks::SkipSetPhoneLock), [&](sys::Message *request) -> sys::MessagePointer {
        connect(typeid(locks::ChangePhoneLock), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleChangePhoneLock();
        });
        connect(typeid(locks::SetPhoneLock), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleSetPhoneLock();
        });
        connect(typeid(locks::SkipSetPhoneLock), [&]([[maybe_unused]] sys::Message *request) -> sys::MessagePointer {
            return phoneLockHandler.handleSkipSetPhoneLock();
        });
        connect(typeid(locks::PhoneLockTimeUpdate), [&](sys::Message *request) -> sys::MessagePointer {
            auto req = static_cast<locks::PhoneLockTimeUpdate *>(request);
            const auto req = static_cast<locks::PhoneLockTimeUpdate *>(request);
            notificationProvider.handle(req);
            return sys::msgHandled();
        });
        connect(typeid(SetAutoLockTimeoutRequest), [&](sys::Message *request) -> sys::MessagePointer {
            auto req = static_cast<SetAutoLockTimeoutRequest *>(request);
            const auto req = static_cast<SetAutoLockTimeoutRequest *>(request);
            return handleAutoLockSetRequest(req);
        });
        connect(typeid(locks::ExternalUnLockPhone), [&](sys::Message *request) -> sys::MessagePointer {
            auto data = static_cast<locks::ExternalUnLockPhone *>(request);
        connect(typeid(locks::ExternalUnlockPhone), [&](sys::Message *request) -> sys::MessagePointer {
            const auto data = static_cast<locks::ExternalUnlockPhone *>(request);
            return phoneLockHandler.handleExternalUnlockRequest(data->getInputData());
        });
        connect(typeid(locks::ExternalPhoneLockAvailabilityChange), [&](sys::Message *request) -> sys::MessagePointer {
            auto data = static_cast<locks::ExternalPhoneLockAvailabilityChange *>(request);
            const auto data = static_cast<locks::ExternalPhoneLockAvailabilityChange *>(request);
            return phoneLockHandler.handleExternalAvailabilityChange(data->getAvailability());
        });


M pure_changelog.md => pure_changelog.md +1 -0
@@ 34,6 34,7 @@
* Fixed issue with uneven first screen redraw after turning the phone on
* Fixed issue with bypassing phone lock window after unplugging USB cable on tethering popup
* Fixed Alarm disappearance during end of call window
* Fixed passcode behavior when blocked from Mudita Center

## [1.7.2 2023-07-28]