~aleteoryx/muditaos

5dc42c2be6c5d2037e614ed1a34d1ec80dea41ed — Maciej Janicki 3 years ago 2b2bb13 + 9a6b836
[MOS-296] Merge new master commits into merge-stable-wip

Merge new master commits
115 files changed, 1530 insertions(+), 794 deletions(-)

M doc/adding_unittests.md
M doc/quickstart.md
M doc/setup_ide.md
M image/assets/lang/English.json
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-calllog/ApplicationCallLog.cpp
M module-apps/application-desktop/ApplicationDesktop.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-music-player/presenters/SongsPresenter.cpp
M module-apps/application-notes/ApplicationNotes.cpp
M module-apps/application-phonebook/ApplicationPhonebook.cpp
M module-apps/application-phonebook/models/NewContactModel.cpp
M module-apps/application-phonebook/models/NewContactModel.hpp
M module-apps/application-phonebook/widgets/PhonebookItem.cpp
M module-apps/application-phonebook/widgets/PhonebookItem.hpp
M module-apps/application-phonebook/windows/PhonebookNewContact.cpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/CMakeLists.txt
M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp
M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp
M module-apps/application-settings/widgets/SettingsStyle.hpp
M module-apps/application-settings/windows/WindowNames.hpp
M module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp
D module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.cpp
D module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.hpp
M module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp
A module-apps/apps-common/popups/BluetoothAuthenticatePopup.cpp
A module-apps/apps-common/popups/BluetoothAuthenticatePopup.hpp
A module-apps/apps-common/popups/BluetoothInfoPopup.cpp
A module-apps/apps-common/popups/BluetoothInfoPopup.hpp
M module-apps/apps-common/popups/CMakeLists.txt
M module-apps/apps-common/popups/Popups.cpp
M module-apps/apps-common/popups/Popups.hpp
M module-apps/apps-common/popups/data/PopupRequestParams.hpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp
M module-bluetooth/lib/btstack
M module-bsp/board/linux/CMakeLists.txt
A module-bsp/board/linux/battery_charger/battery_charger.cpp
M module-bsp/board/linux/lpm/PowerProfile.cpp
M module-bsp/board/linux/torch/torch.cpp
M module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp
M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp
M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp
M module-bsp/board/rt1051/bsp/torch/torch.cpp
M module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger.hpp
M module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp
M module-bsp/board/rt1051/puretx/hal/battery_charger/CurrentMeasurementScope.cpp
A module-bsp/bsp/battery_charger/battery_charger.hpp
M module-bsp/bsp/lpm/PowerProfile.hpp
M module-bsp/bsp/lpm/bsp_lpm.hpp
M module-bsp/bsp/torch/torch.hpp
M module-bsp/drivers/semc/DriverSEMC.hpp
M module-services/service-bluetooth/ServiceBluetooth.cpp
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp
A module-services/service-bluetooth/service-bluetooth/messages/Authenticate.hpp
M module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp
D module-services/service-bluetooth/service-bluetooth/messages/Passkey.hpp
M module-services/service-cellular/CMakeLists.txt
A module-services/service-cellular/call/CallDB.cpp
A module-services/service-cellular/call/CallDB.hpp
M module-services/service-cellular/call/CallRingGuard.cpp
M module-services/service-cellular/call/CallRingGuard.hpp
M module-services/service-cellular/call/CellularCall.cpp
M module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp
M module-services/service-cellular/service-cellular/call/CellularCall.hpp
M module-services/service-cellular/src/ServiceCellularPriv.cpp
M module-services/service-evtmgr/api/torch.cpp
M module-sys/Service/Service.cpp
M module-sys/Service/details/bus/Bus.cpp
M module-sys/Service/include/Service/Service.hpp
M module-sys/SystemManager/CMakeLists.txt
M module-sys/SystemManager/CpuGovernor.cpp
M module-sys/SystemManager/CpuLogPrinter.cpp
M module-sys/SystemManager/CpuPackPrinter.cpp
M module-sys/SystemManager/CpuSentinel.cpp
M module-sys/SystemManager/CpuStatistics.cpp
M module-sys/SystemManager/PowerManager.cpp
M module-sys/SystemManager/SystemManagerCommon.cpp
A module-sys/SystemManager/cpu/AlgorithmFactory.cpp
A module-sys/SystemManager/cpu/AlgorithmFactory.hpp
A module-sys/SystemManager/cpu/algorithm/Algorithm.cpp
A module-sys/SystemManager/cpu/algorithm/Algorithm.hpp
A module-sys/SystemManager/cpu/algorithm/AlgorithmID.hpp
A module-sys/SystemManager/cpu/algorithm/FrequencyHold.cpp
A module-sys/SystemManager/cpu/algorithm/FrequencyHold.hpp
A module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp
A module-sys/SystemManager/cpu/algorithm/FrequencyStepping.hpp
A module-sys/SystemManager/cpu/algorithm/ImmediateUpscale.cpp
A module-sys/SystemManager/cpu/algorithm/ImmediateUpscale.hpp
M module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp
M module-sys/SystemManager/include/SystemManager/CpuPrinter.hpp
M module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp
M module-sys/SystemManager/include/SystemManager/CpuStatistics.hpp
M module-sys/SystemManager/include/SystemManager/PowerManager.hpp
A module-sys/SystemManager/include/SystemManager/SentinelView.hpp
M module-sys/SystemManager/include/SystemManager/SysCpuUpdateResult.hpp
M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp
M module-sys/common/include/system/SystemReturnCodes.hpp
A module-sys/common/include/system/messages/HoldCpuFrequency.hpp
M module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp
M products/PurePhone/BinaryAssetsVersions.cmake
M products/PurePhone/apps/Application.cpp
M products/PurePhone/services/appmgr/ApplicationManager.cpp
M products/PurePhone/services/evtmgr/EventManager.cpp
M test/get_os_log.py
M test/harness
M test/pytest/conftest.py
M doc/adding_unittests.md => doc/adding_unittests.md +1 -1
@@ 2,7 2,7 @@

## Unit test framework

For writing test we are using (catch2)[https://github.com/catchorg/Catch2/blob/devel/docs/tutorial.md].
For writing test we are using [catch2](https://github.com/catchorg/Catch2/blob/devel/docs/tutorial.md).
There are few test written in `gtest` but we focus on using `catch2`

## adding unit test

M doc/quickstart.md => doc/quickstart.md +2 -2
@@ 183,7 183,7 @@ git config commit.template .gitmessage
```

This way each time you add a new commit you will see the template that will help
you with the proper message format. More about that in (Development Workflow)[./doc/development_workflow.md#commit-changes]
you with the proper message format. More about that in [Development Workflow](./doc/development_workflow.md#commit-changes)

### Commit message hook
This hooks automatically converts your branch name to commit title


@@ 270,7 270,7 @@ Please be aware that when building custom image you'll have to give it some tag 

## Preparing packages

If you need a package, containing everything needed to run the application, please check (build_targests.md)[./doc/build_targests.md] document.
If you need a package, containing everything needed to run the application, please check [build_targests.md](./doc/build_targests.md) document.

## Generating code coverage reports


M doc/setup_ide.md => doc/setup_ide.md +1 -1
@@ 2,7 2,7 @@

## Table of contents
- [Setting up in Eclipse](#setting-up-in-eclipse)
- [Setting up in CLion](#setting-up-in -clion)
- [Setting up in CLion](#setting-up-in-clion)
- [Additional info](#additional-info)
    + [Prevent Git from suggesting commits](#prevent-git-from-suggesting-commits)
    + [Seperate build folders](#separate-build-folders)

M image/assets/lang/English.json => image/assets/lang/English.json +8 -1
@@ 326,7 326,6 @@
  "app_settings_bluetooth_main": "Bluetooth",
  "app_settings_bluetooth_phone_name": "Phone name",
  "app_settings_bluetooth_phone_visibility": "Phone visibility",
  "app_settings_bluetooth_enter_passkey": "Enter passkey:",
  "app_settings_bluetooth_init_error_message": "<text font='gt_pressura' weight='regular' size='27'>Bluetooth initialization process has failed.</text>",
  "app_settings_bluetooth_pairing_error_message": "<text font='gt_pressura' weight='regular' size='27'>Pairing process has failed.<br></br>Check the device and </text> <text font='gt_pressura' weight='bold' size='27'>TRY AGAIN.</text>",
  "app_settings_bluetooth_unpairing_error_message": "<text font='gt_pressura' weight='regular' size='27'>Unpairing process has failed.<br></br>Check the device and </text> <text font='gt_pressura' weight='bold' size='27'>TRY AGAIN.</text>",


@@ 591,6 590,14 @@
  "tethering_enable_question": "<text>You're connected to the computer.<br />Turn tethering on?<br /><text color='5'>(some functions may be disabled)</text></text>",
  "tethering_phone_mode_change_prohibited": "<text>Tethering is on.<br /><br />Other modes (Connected, DND,<br />Offline) are overriden by this mode<br />and are not working.</text>",
  "tethering_menu_access_decline": "<text>Tethering is on.<br /><br />To access menu,<br />turn tethering off.</text>",
  "bluetooth_popup": "Bluetooth",
  "bluetooth_popup_pin": "Enter PIN:",
  "bluetooth_popup_passkey": "Enter passkey:",
  "bluetooth_popup_pair_cancel": "<text>Device </text><text weight='bold'><token>$DEVICE</token></text><text> would like to pair with your phone</text>",
  "bluetooth_popup_pair": "Pair",
  "bluetooth_popup_cancel": "Cancel",
  "bluetooth_info_popup_success": "<text>Your phone is connected to: <br></br></text><text weight='bold'><token>$DEVICE</token></text>",
  "bluetooth_info_popup_error": "<text>Pairing process with </text><text weight='bold'><token>$DEVICE</token></text><br></br><text> has failed. Error code: <token>$ERROR</token></text>",
  "app_bell_settings_time_units_time_fmt_top_message": "Time format",
  "app_bell_settings_time_units_time_message": "Time",
  "app_bellmain_alarm": "Alarm",

M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp => module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationAlarmClock.hpp"


@@ 111,6 111,7 @@ namespace app

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

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

/*


@@ 162,6 162,7 @@ namespace app

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

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

#include <application-calculator/ApplicationCalculator.hpp>


@@ 39,6 39,7 @@ namespace app

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

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

#include <application-calendar/ApplicationCalendar.hpp>


@@ 45,6 45,7 @@ namespace app

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

M module-apps/application-calllog/ApplicationCallLog.cpp => module-apps/application-calllog/ApplicationCallLog.cpp +1 -0
@@ 99,6 99,7 @@ namespace app

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

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +1 -0
@@ 180,6 180,7 @@ namespace app

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::BluetoothAuthenticate,
                      gui::popup::ID::PhoneModes,
                      gui::popup::ID::PhoneLock,
                      gui::popup::ID::SimLock,

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

#include "ApplicationMeditation.hpp"


@@ 64,6 64,7 @@ namespace app

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

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

#include "ApplicationMessages.hpp"


@@ 154,6 154,7 @@ namespace app

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

M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <application-music-player/ApplicationMusicPlayer.hpp>


@@ 143,6 143,7 @@ namespace app
                              });
        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::BluetoothAuthenticate,
                      gui::popup::ID::PhoneModes,
                      gui::popup::ID::PhoneLock,
                      gui::popup::ID::Alarm});

M module-apps/application-music-player/presenters/SongsPresenter.cpp => module-apps/application-music-player/presenters/SongsPresenter.cpp +5 -0
@@ 43,6 43,11 @@ namespace app::music_player
                          str(retCode).c_str(),
                          token.IsValid());
                refreshView();
                auto nextSongToPlay = songsModelInterface->getNextFilePath(filePath);
                if (nextSongToPlay.empty()) {
                    return;
                }
                play(nextSongToPlay);
                return;
            }


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

#include <application-notes/ApplicationNotes.hpp>


@@ 126,6 126,7 @@ namespace app

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

M module-apps/application-phonebook/ApplicationPhonebook.cpp => module-apps/application-phonebook/ApplicationPhonebook.cpp +1 -0
@@ 143,6 143,7 @@ namespace app

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

M module-apps/application-phonebook/models/NewContactModel.cpp => module-apps/application-phonebook/models/NewContactModel.cpp +0 -7
@@ 116,13 116,6 @@ void NewContactModel::clearData()
    eraseInternalData();
}

void NewContactModel::recreateData()
{
    clearData();
    createData();
    list->rebuildList();
}

bool NewContactModel::verifyData()
{
    for (auto item : internalData) {

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

#pragma once


@@ 23,7 23,6 @@ class NewContactModel : public app::InternalModel<gui::ContactListItem *>, publi
    explicit NewContactModel(app::ApplicationCommon *app);

    void clearData();
    void recreateData();
    void saveData(std::shared_ptr<ContactRecord> contactRecord);
    void loadData(std::shared_ptr<ContactRecord> contactRecord, gui::SwitchData *data);
    void createData();

M module-apps/application-phonebook/widgets/PhonebookItem.cpp => module-apps/application-phonebook/widgets/PhonebookItem.cpp +4 -14
@@ 36,13 36,12 @@ namespace gui
        };
    }

    // sets copy of alarm's
    void PhonebookItem::setContact(std::shared_ptr<ContactRecord> contact)
    void PhonebookItem::setContact(std::shared_ptr<ContactRecord> contactRecord)
    {
        this->contact = contact;
        /* alternativeName is used as Surname or Second name */
        contact = std::move(contactRecord);
        contactName->setText(contact->getFormattedName(ContactRecord::NameFormatType::List));
        markFavourite(contact->isOnFavourites());
        contactName->setFont(style::window::font::big);
        favourite = contact->isOnFavourites();
        markBlocked(contact->isOnBlocked());
    }



@@ 62,15 61,6 @@ namespace gui
        }
    }

    void PhonebookItem::markFavourite(bool val)
    {
        favourite = val;
        if (val)
            contactName->setFont(style::window::font::bigbold);
        else
            contactName->setFont(style::window::font::big);
    }

    void PhonebookItem::markBlocked(bool val)
    {
        if (val) {

M module-apps/application-phonebook/widgets/PhonebookItem.hpp => module-apps/application-phonebook/widgets/PhonebookItem.hpp +1 -2
@@ 20,12 20,11 @@ namespace gui
        gui::HBox *hBox         = nullptr;

        bool favourite = false;
        void markFavourite(bool val);
        void markBlocked(bool val);
        LabelMarkerDisplayMode labelMarkerDisplayMode = LabelMarkerDisplayMode::IncludeFavourites;

      public:
        std::shared_ptr<ContactRecord> contact = nullptr;
        std::shared_ptr<ContactRecord> contact;

        PhonebookItem();
        virtual ~PhonebookItem() = default;

M module-apps/application-phonebook/windows/PhonebookNewContact.cpp => module-apps/application-phonebook/windows/PhonebookNewContact.cpp +4 -6
@@ 42,6 42,8 @@ namespace gui
                                 newContactModel,
                                 listview::ScrollBarType::PreRendered);
        list->setBoundaries(Boundaries::Continuous);
        newContactModel->createData();

        setFocusItem(list);
    }



@@ 52,12 54,8 @@ namespace gui

    void PhonebookNewContact::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (mode != ShowMode::GUI_SHOW_RETURN) {
            newContactModel->recreateData();
        if (mode == ShowMode::GUI_SHOW_INIT && data != nullptr) {
            newContactModel->loadData(contact, data);
        }

        if (mode == ShowMode::GUI_SHOW_INIT) {
            list->rebuildList();
        }



@@ 188,7 186,7 @@ namespace gui

        std::unique_ptr<gui::SwitchData> data =
            std::make_unique<PhonebookItemData>(contact, newContactModel->getRequestType());
        data->ignoreCurrentWindowOnStack      = true;
        data->ignoreCurrentWindowOnStack = true;
        application->switchWindow(gui::window::name::contact, std::move(data));
        return true;
    } // namespace gui

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +1 -26
@@ 15,7 15,6 @@
#include <application-settings/windows/bluetooth/AddDeviceWindow.hpp>
#include <application-settings/windows/bluetooth/AllDevicesWindow.hpp>
#include <application-settings/windows/bluetooth/PhoneNameWindow.hpp>
#include <application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.hpp>
#include <application-settings/windows/network/NetworkWindow.hpp>
#include <application-settings/windows/network/SimPINSettingsWindow.hpp>
#include <application-settings/windows/network/SimCardsWindow.hpp>


@@ 70,7 69,6 @@
#include <service-bluetooth/messages/Connect.hpp>
#include <service-bluetooth/messages/DeviceName.hpp>
#include <service-bluetooth/messages/InitializationResult.hpp>
#include <service-bluetooth/messages/Passkey.hpp>
#include <service-bluetooth/messages/ResponseVisibleDevices.hpp>
#include <service-bluetooth/messages/Status.hpp>
#include <service-bluetooth/messages/Unpair.hpp>


@@ 211,26 209,6 @@ namespace app
            return sys::MessageNone{};
        });

        connect(typeid(BluetoothPairResultMessage), [&](sys::Message *msg) {
            auto bluetoothPairResultMsg = static_cast<BluetoothPairResultMessage *>(msg);
            auto device                 = bluetoothPairResultMsg->getDevice();
            if (bluetoothPairResultMsg->isSucceed()) {
                return sys::MessageNone{};
            }
            auto message = std::make_shared<BluetoothPairMessage>(device);

            switchToAllDevicesViaBtErrorPrompt(std::move(message), "app_settings_bluetooth_pairing_error_message");

            return sys::MessageNone{};
        });

        connect(typeid(::message::bluetooth::RequestPasskey), [&](sys::Message *msg) {
            auto m                               = dynamic_cast<::message::bluetooth::RequestPasskey *>(msg);
            bluetoothSettingsModel->pinRequestor = m->getDevice();
            switchWindow(gui::window::name::bluetooth_check_passkey);
            return sys::MessageNone{};
        });

        connect(typeid(::message::bluetooth::ProfileStatus), [&](sys::Message *msg) { return sys::MessageNone{}; });

        connect(typeid(::message::bluetooth::UnpairResult), [&](sys::Message *msg) {


@@ 397,10 375,6 @@ namespace app
        windowsFactory.attach(gui::window::name::phone_name, [this](ApplicationCommon *app, const std::string &name) {
            return std::make_unique<gui::PhoneNameWindow>(app, bluetoothSettingsModel);
        });
        windowsFactory.attach(
            gui::window::name::bluetooth_check_passkey, [this](ApplicationCommon *app, const std::string &name) {
                return std::make_unique<gui::BluetoothCheckPasskeyWindow>(app, bluetoothSettingsModel);
            });

        // Network
        windowsFactory.attach(gui::window::name::network, [](ApplicationCommon *app, const std::string &name) {


@@ 563,6 537,7 @@ namespace app

        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::BluetoothAuthenticate,
                      gui::popup::ID::PhoneModes,
                      gui::popup::ID::PhoneLock,
                      gui::popup::ID::SimLock,

M module-apps/application-settings/CMakeLists.txt => module-apps/application-settings/CMakeLists.txt +0 -1
@@ 60,7 60,6 @@ target_sources(application-settings
        windows/apps/SoundSelectWindow.cpp
        windows/bluetooth/AddDeviceWindow.cpp
        windows/bluetooth/AllDevicesWindow.cpp
        windows/bluetooth/BluetoothCheckPasskeyWindow.cpp
        windows/bluetooth/BluetoothWindow.cpp
        windows/bluetooth/PhoneNameWindow.cpp
        windows/display-keypad/DisplayAndKeypadWindow.cpp

M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp => module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp +2 -8
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BluetoothSettingsModel.hpp"


@@ 10,7 10,7 @@
#include <service-bluetooth/messages/Disconnect.hpp>
#include <service-bluetooth/messages/SetStatus.hpp>
#include <service-bluetooth/messages/SetDeviceName.hpp>
#include <service-bluetooth/messages/Passkey.hpp>
#include <service-bluetooth/messages/Authenticate.hpp>
#include <service-bluetooth/messages/Unpair.hpp>
#include <service-bluetooth/messages/SyncDevices.hpp>



@@ 68,12 68,6 @@ void BluetoothSettingsModel::requestDeviceUnpair(const Devicei &device)
    service->bus.sendUnicast(std::make_shared<message::bluetooth::Unpair>(device), service::name::bluetooth);
}

void BluetoothSettingsModel::responsePasskey(const std::string &passkey)
{
    service->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey, pinRequestor),
                             service::name::bluetooth);
}

void BluetoothSettingsModel::requestConnection(const Devicei &device)
{
    service->bus.sendUnicast(std::make_shared<message::bluetooth::Connect>(device), service::name::bluetooth);

M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp => module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 26,7 26,6 @@ class BluetoothSettingsModel
    void stopScan();
    void requestDevicePair(const Devicei &device);
    void requestDeviceUnpair(const Devicei &device);
    void responsePasskey(const std::string &passkey);
    void requestConnection(const Devicei &device);
    void requestDisconnection();


M module-apps/application-settings/widgets/SettingsStyle.hpp => module-apps/application-settings/widgets/SettingsStyle.hpp +1 -27
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 50,32 50,6 @@ namespace style
                inline constexpr uint32_t h = style::window_height - y - style::nav_bar::height;
            } // namespace newApn

            namespace bluetooth
            {
                namespace passkey
                {
                    namespace image
                    {
                        inline constexpr auto x = 176;
                        inline constexpr auto y = 132;
                    } // namespace image

                    namespace label
                    {
                        inline constexpr auto x = 150U;
                        inline constexpr auto y = 300U;
                        inline constexpr auto w = 200U;
                    } // namespace label

                    namespace text
                    {
                        inline constexpr auto x = 40U;
                        inline constexpr auto y = 370U;
                        inline constexpr auto w = style::window_width - 2 * x;
                        inline constexpr auto h = 52;
                    } // namespace text
                }     // namespace passkey
            }         // namespace bluetooth

            namespace phone_modes
            {

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

#pragma once


@@ 17,7 17,6 @@ namespace gui::window::name
    inline constexpr auto all_devices             = "AllDevices";
    inline constexpr auto phone_name              = "PhoneName";
    inline constexpr auto add_device              = "AddDevice";
    inline constexpr auto bluetooth_check_passkey = "BluetoothCheckPasskey";

    inline constexpr auto network          = "Network";
    inline constexpr auto sim_cards        = "SimCards";

M module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp => module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp +25 -10
@@ 1,9 1,10 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CPUModeTestWindow.hpp"

#include <system/messages/SentinelRegistrationMessage.hpp>
#include <system/messages/RequestCpuFrequencyMessage.hpp>
#include <application-settings/windows/WindowNames.hpp>
#include <Application.hpp>
#include <TextFixedSize.hpp>


@@ 131,18 132,26 @@ namespace gui

        permanentFreqSpinner = new gui::TextSpinnerBox(permanentFreqBody, {"OFF", "ON"}, Boundaries::Continuous);
        permanentFreqSpinner->setMinimumSize(100, 30);
        permanentFreqSpinner->setCurrentValue(cpuModeTester->isPermanentFrequencyActive() ? "ON" : "OFF");
        auto ret =
            application->async_call<sys::IsCpuPernament, sys::IsCpuPernamentResponse>(service::name::system_manager);
        application->sync(ret);
        permanentFreqSpinner->setCurrentValue(ret.getResult().pernament ? "ON" : "OFF");

        permanentFreqBody->inputCallback = [&](Item &item, const InputEvent &event) {
            auto ret = permanentFreqSpinner->onInput(event);
            if (ret) {
                if (permanentFreqSpinner->getCurrentValue() == "ON") {
                    cpuModeTester->HoldFrequencyPermanently(
                        magic_enum::enum_cast<bsp::CpuFrequencyMHz>(std::stoi(currentFreqSpinner->getCurrentValue()))
                            .value());
                    application->bus.sendUnicastSync(std::make_shared<sys::HoldCpuFrequencyPermanentlyMessage>(
                                                         magic_enum::enum_cast<bsp::CpuFrequencyMHz>(
                                                             std::stoi(currentFreqSpinner->getCurrentValue()))
                                                             .value()),
                                                     service::name::system_manager,
                                                     5000);
                }
                else {
                    cpuModeTester->ReleasePermanentFrequency();
                    application->bus.sendUnicastSync(std::make_shared<sys::ReleaseCpuPermanentFrequencyMessage>(),
                                                     service::name::system_manager,
                                                     5000);
                }
            }



@@ 183,10 192,16 @@ namespace gui
        newFreqBody->inputCallback = [&](Item &item, const InputEvent &event) {
            auto ret = currentFreqSpinner->onInput(event);

            if (cpuModeTester->isPermanentFrequencyActive()) {
                cpuModeTester->HoldFrequencyPermanently(
                    magic_enum::enum_cast<bsp::CpuFrequencyMHz>(std::stoi(currentFreqSpinner->getCurrentValue()))
                        .value());
            auto async = application->async_call<sys::IsCpuPernament, sys::IsCpuPernamentResponse>(
                service::name::system_manager);
            application->sync(async);
            if (async.getResult().pernament) {
                application->bus.sendUnicastSync(
                    std::make_shared<sys::HoldCpuFrequencyPermanentlyMessage>(
                        magic_enum::enum_cast<bsp::CpuFrequencyMHz>(std::stoi(currentFreqSpinner->getCurrentValue()))
                            .value()),
                    service::name::system_manager,
                    5000);
            }

            return ret;

D module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.cpp => module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.cpp +0 -73
@@ 1,73 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 "BluetoothCheckPasskeyWindow.hpp"

#include <application-settings/widgets/SettingsStyle.hpp>
#include <application-settings/windows/WindowNames.hpp>

#include <utility>
#include <widgets/text/Text.hpp>

namespace gui
{
    namespace
    {
        constexpr auto maxPasskeyCharactersCount = 16U;
        constexpr auto minPasskeyCharactersCount = 4U;
    } // namespace
    namespace passkey_style = style::settings::window::bluetooth::passkey;

    BluetoothCheckPasskeyWindow::BluetoothCheckPasskeyWindow(
        app::ApplicationCommon *app, std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel)
        : AppWindow(app, window::name::bluetooth_check_passkey),
          bluetoothSettingsModel(std::move(bluetoothSettingsModel))
    {
        buildInterface();
    }

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

        setTitle(utils::translate("app_settings_bt"));

        navBar->setActive(nav_bar::Side::Center, true);
        navBar->setActive(nav_bar::Side::Right, true);
        navBar->setText(nav_bar::Side::Center, utils::translate(style::strings::common::confirm));
        navBar->setText(nav_bar::Side::Right, utils::translate(style::strings::common::back));

        image = new Image(this, passkey_style::image::x, passkey_style::image::y, 0, 0, "bluetooth_128px_W_G");

        label = new Label(this,
                          passkey_style::label::x,
                          passkey_style::label::y,
                          passkey_style::label::w,
                          style::window::label::default_h);
        label->setFont(style::window::font::big);
        label->setEdges(RectangleEdge::None);
        label->setText(utils::translate("app_settings_bluetooth_enter_passkey"));

        text = new Text(
            this, passkey_style::text::x, passkey_style::text::y, passkey_style::text::w, passkey_style::text::h);
        text->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        text->setTextLimitType(TextLimitType::MaxSignsCount, maxPasskeyCharactersCount);
        text->setEdges(RectangleEdge::Bottom);
        text->setInputMode(new InputMode({InputMode::digit}));
        text->setPenWidth(style::window::default_border_rect_no_focus);
        text->setFont(style::window::font::largelight);

        setFocusItem(text);
    }

    auto BluetoothCheckPasskeyWindow::onInput(const InputEvent &inputEvent) -> bool
    {
        auto passkey = text->getText();
        if (passkey.length() >= minPasskeyCharactersCount && inputEvent.isShortRelease(KeyCode::KEY_ENTER)) {
            bluetoothSettingsModel->responsePasskey(passkey);
            application->returnToPreviousWindow();
            return true;
        }
        return AppWindow::onInput(inputEvent);
    }
} // namespace gui

D module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.hpp => module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.hpp +0 -29
@@ 1,29 0,0 @@
// 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 <application-settings/models/bluetooth/BluetoothSettingsModel.hpp>
#include <AppWindow.hpp>

namespace gui
{
    class Image;
    class Label;
    class Text;
    class BluetoothCheckPasskeyWindow : public AppWindow
    {
      public:
        BluetoothCheckPasskeyWindow(app::ApplicationCommon *app,
                                    std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel);

      private:
        void buildInterface() override;
        auto onInput(const InputEvent &inputEvent) -> bool override;

        Image *image = nullptr;
        Label *label = nullptr;
        Text *text   = nullptr;
        std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel;
    };
} // namespace gui

M module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp => module-apps/apps-common/ApplicationCommonPopupBlueprints.cpp +21 -0
@@ 13,6 13,7 @@ namespace app
    void ApplicationCommon::registerPopupBlueprints()
    {
        using namespace gui::popup;

        popupBlueprint.registerBlueprint(
            ID::PhoneModes, [&](gui::popup::ID /*id*/, std::unique_ptr<gui::PopupRequestParams> &params) {
                auto popupParams = dynamic_cast<gui::PhoneModePopupRequestParams *>(params.get());


@@ 35,6 36,7 @@ namespace app
                }
                return true;
            });

        popupBlueprint.registerBlueprint(
            ID::Volume, [&](gui::popup::ID /*id*/, std::unique_ptr<gui::PopupRequestParams> &params) {
                auto volumeParams = dynamic_cast<const gui::VolumePopupRequestParams *>(params.get());


@@ 57,6 59,24 @@ namespace app
                }
                return true;
            });

        popupBlueprint.registerBlueprint(
            ID::BluetoothAuthenticate, [&](gui::popup::ID id, std::unique_ptr<gui::PopupRequestParams> &params) {
                switchWindowPopup(resolveWindowName(id),
                                  gui::popup::popupDisposition(id, gui::popup::Disposition::Priority::High),
                                  std::move(params),
                                  SwitchReason::Popup);
                return true;
            });
        popupBlueprint.registerBlueprint(
            ID::BluetoothInfo, [&](gui::popup::ID id, std::unique_ptr<gui::PopupRequestParams> &params) {
                switchWindowPopup(resolveWindowName(id),
                                  gui::popup::popupDisposition(id, gui::popup::Disposition::Priority::High),
                                  std::move(params),
                                  SwitchReason::Popup);
                return true;
            });

        popupBlueprint.registerBlueprint(
            ID::PhoneLock, [&](gui::popup::ID id, std::unique_ptr<gui::PopupRequestParams> & /*params*/) {
                switchWindowPopup(resolveWindowName(id),


@@ 83,6 103,7 @@ namespace app
        };
        popupBlueprint.registerBlueprint(ID::PhoneLockInput, phoneLockBlueprint);
        popupBlueprint.registerBlueprint(ID::PhoneLockChangeInfo, phoneLockBlueprint);

        auto simLockBlueprint = [&](gui::popup::ID id, std::unique_ptr<gui::PopupRequestParams> &params) {
            auto popupParams = dynamic_cast<const gui::SimUnlockInputRequestParams *>(params.get());
            if (popupParams == nullptr) {

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

#include "BluetoothAuthenticatePopup.hpp"

#include <ApplicationCommon.hpp>
#include <i18n/i18n.hpp>

namespace gui
{
    namespace bluetooth::authenticate
    {
        inline constexpr auto option_box_top_margin = 40U;

        inline constexpr auto max_passkey_signs_count = 16U;
        inline constexpr auto min_passkey_signs_count = 4U;
        inline constexpr auto passkey_input_w         = 300U;
        inline constexpr auto passkey_input_h         = 60U;

        inline constexpr auto buttons_input_w = 150U;
        inline constexpr auto buttons_input_h = 75U;
        inline constexpr auto buttons_margin  = 30U;

        enum ButtonsOptions
        {
            Pair,
            Cancel,
        };

    } // namespace bluetooth::authenticate

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

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

        setTitle(utils::translate("bluetooth_popup"));

        navBar->setText(nav_bar::Side::Right, utils::translate(style::strings::common::back));

        infoIcon = new gui::Icon(this,
                                 style::window::default_left_margin,
                                 style::window::default_vertical_pos,
                                 style::window::default_body_width,
                                 style::window::default_body_height,
                                 "bluetooth_128px_W_G",
                                 utils::translate(""));
        infoIcon->setAlignment(Alignment::Horizontal::Center);
    }

    void BluetoothAuthenticatePopup::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        auto temp          = dynamic_cast<BluetoothAuthenticateRequestParams *>(data);
        authenticateParams = new BluetoothAuthenticateRequestParams(temp->getDevice(), temp->getAuthenticateType());

        if (authenticateParams == nullptr) {
            LOG_ERROR("No authenticate data received");
            return;
        }

        switch (authenticateParams->getAuthenticateType()) {
        case ::bluetooth::AuthenticateType::Pin:
        case ::bluetooth::AuthenticateType::Passkey:
            createTextAuthenticateInput();
            break;
        case ::bluetooth::AuthenticateType::PairCancel:
            createButtonsAuthenticateInput();
            break;
        }
    }

    void BluetoothAuthenticatePopup::createTextAuthenticateInput()
    {
        inputText = new TextFixedSize(infoIcon, 0, 0, 0, 0);
        inputText->drawUnderline(false);
        inputText->setTextType(TextType::SingleLine);
        inputText->setTextEllipsisType(TextEllipsis::Both);
        inputText->setFont(style::window::font::largelight);
        inputText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        inputText->setEdges(RectangleEdge::Bottom);
        inputText->setInputMode(new InputMode({InputMode::digit}));
        inputText->setPenWidth(style::window::default_border_rect_no_focus);
        inputText->setMinimumSize(bluetooth::authenticate::passkey_input_w, bluetooth::authenticate::passkey_input_h);
        inputText->setMargins({0, bluetooth::authenticate::option_box_top_margin, 0, 0});

        if (authenticateParams->getAuthenticateType() == ::bluetooth::AuthenticateType::Passkey) {
            infoIcon->text->setText(utils::translate("bluetooth_popup_passkey"));
            inputText->setTextLimitType(TextLimitType::MaxSignsCount, bluetooth::authenticate::max_passkey_signs_count);

            inputText->activatedCallback = [&](Item &) -> bool {
                auto passkey = inputText->getText();
                if (passkey.length() >= bluetooth::authenticate::min_passkey_signs_count) {
                    application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponseAuthenticatePasskey>(
                                                     passkey, authenticateParams->getDevice()),
                                                 service::name::bluetooth);
                    return true;
                }
                return false;
            };
        }
        else if (authenticateParams->getAuthenticateType() == ::bluetooth::AuthenticateType::Pin) {
            infoIcon->text->setText(utils::translate("bluetooth_popup_pin"));
            inputText->setTextLimitType(TextLimitType::MaxSignsCount, bluetooth::authenticate::min_passkey_signs_count);

            inputText->activatedCallback = [&](Item &) -> bool {
                auto pin = inputText->getText();
                if (pin.length() == bluetooth::authenticate::min_passkey_signs_count) {
                    application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponseAuthenticatePin>(
                                                     pin, authenticateParams->getDevice()),
                                                 service::name::bluetooth);
                    return true;
                }
                return false;
            };
        }

        infoIcon->resizeItems();

        setFocusItem(inputText);
    }

    auto BluetoothAuthenticatePopup::onInput(const InputEvent &inputEvent) -> bool
    {
        auto ret = AppWindow::onInput(inputEvent);

        if (authenticateParams->getAuthenticateType() == ::bluetooth::AuthenticateType::Passkey ||
            authenticateParams->getAuthenticateType() == ::bluetooth::AuthenticateType::Pin) {

            if (inputText->getText().length() >= bluetooth::authenticate::min_passkey_signs_count) {
                navBar->setText(nav_bar::Side::Center, utils::translate(style::strings::common::confirm));
            }
            else {
                navBar->setActive(nav_bar::Side::Center, false);
            }
        }
        return ret;
    }

    void BluetoothAuthenticatePopup::createButtonsAuthenticateInput()
    {
        infoIcon->text->setRichText(utils::translate("bluetooth_popup_pair_cancel"),
                                    {{"$DEVICE", std::string(authenticateParams->getDevice().name.data())}});
        navBar->setText(nav_bar::Side::Center, utils::translate(style::strings::common::confirm));

        auto hBox = new HBox(infoIcon, 0, 0, 0, 0);
        hBox->setMinimumSize(style::window::default_body_width, bluetooth::authenticate::buttons_input_h);
        hBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
        hBox->setEdges(RectangleEdge::None);
        hBox->setMargins({0, bluetooth::authenticate::option_box_top_margin, 0, 0});

        auto createButton = [&](gui::bluetooth::authenticate::ButtonsOptions optionName) {
            Label *option = new Label(hBox, 0, 0, 0, 0, "");

            if (optionName == gui::bluetooth::authenticate::ButtonsOptions::Pair) {
                option->setText(utils::translate(style::strings::common::yes));
                option->activatedCallback = [&](Item &) -> bool {
                    application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponseAuthenticatePairCancel>(
                                                     true, authenticateParams->getDevice()),
                                                 service::name::bluetooth);
                    return true;
                };
            }
            else if (optionName == gui::bluetooth::authenticate::ButtonsOptions::Cancel) {
                option->setText(utils::translate(style::strings::common::no));
                option->setMargins({0, 0, gui::bluetooth::authenticate::buttons_margin, 0});
                option->activatedCallback = [=](Item &) -> bool {
                    application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponseAuthenticatePairCancel>(
                                                     false, authenticateParams->getDevice()),
                                                 service::name::bluetooth);
                    application->returnToPreviousWindow();
                    return true;
                };
            }

            option->setMinimumSize(bluetooth::authenticate::buttons_input_w, bluetooth::authenticate::buttons_input_h);
            option->setPenWidth(0);
            option->setPenFocusWidth(3);
            option->setEdges(RectangleEdge::Bottom | RectangleEdge::Top);
            option->setFont(style::window::font::big);
            option->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

            return option;
        };

        createButton(bluetooth::authenticate::Cancel);
        createButton(bluetooth::authenticate::Pair);

        infoIcon->resizeItems();

        setFocusItem(hBox);
    }

} // namespace gui

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

#pragma once

#include "Popups.hpp"
#include "data/PopupRequestParams.hpp"

#include <TextFixedSize.hpp>
#include <Icon.hpp>
#include <AppWindow.hpp>

namespace gui
{
    class BluetoothAuthenticatePopup : public AppWindow
    {
      public:
        BluetoothAuthenticatePopup(app::ApplicationCommon *app, const std::string &name);

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

        void createTextAuthenticateInput();
        void createButtonsAuthenticateInput();

        BluetoothAuthenticateRequestParams *authenticateParams = nullptr;
        Icon *infoIcon                                         = nullptr;
        TextFixedSize *inputText                               = nullptr;
    };
} // namespace gui

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

#include "BluetoothInfoPopup.hpp"
#include "data/PopupRequestParams.hpp"

#include <service-appmgr/Controller.hpp>
#include <ApplicationCommon.hpp>
#include <i18n/i18n.hpp>

using namespace gui;

BluetoothInfoPopup::BluetoothInfoPopup(app::ApplicationCommon *app, const std::string &name)
    : WindowWithTimer(app, name)
{
    buildInterface();
}

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

    setTitle(utils::translate("bluetooth_popup"));

    navBar->setText(nav_bar::Side::Center, utils::translate(style::strings::common::ok));

    infoIcon = new gui::Icon(this,
                             style::window::default_left_margin,
                             style::window::default_vertical_pos,
                             style::window::default_body_width,
                             style::window::default_body_height,
                             "",
                             utils::translate(""));
    infoIcon->setAlignment(Alignment::Horizontal::Center);
}

void BluetoothInfoPopup::onBeforeShow(ShowMode mode, SwitchData *data)
{
    auto infoData = dynamic_cast<BluetoothInfoParams *>(data);

    if (infoData == nullptr) {
        LOG_ERROR("No info data received");
        return;
    }

    if (infoData->isSucceed()) {
        infoIcon->image->set("success_128px_W_G");
        infoIcon->text->setRichText(utils::translate("bluetooth_info_popup_success"),
                                    {{"$DEVICE", std::string(infoData->getDevice().name.data())}});

        timerCallback = [this](Item &, sys::Timer &timer) {
            closePopups();
            return true;
        };
        resetTimer();
    }
    else {
        infoIcon->image->set("fail_128px_W_G");
        infoIcon->text->setRichText(utils::translate("bluetooth_info_popup_error"),
                                    {{"$DEVICE", std::string(infoData->getDevice().name.data())},
                                     {"$ERROR", std::string(infoData->getErrorCode())}});
    }
}

bool BluetoothInfoPopup::onInput(const InputEvent &inputEvent)
{
    if (inputEvent.isShortRelease(KeyCode::KEY_ENTER)) {
        closePopups();
        return true;
    }
    return false;
}

void BluetoothInfoPopup::closePopups()
{
    app::manager::Controller::sendAction(
        application,
        app::manager::actions::AbortPopup,
        std::make_unique<gui::PopupRequestParams>(gui::popup::ID::BluetoothAuthenticate));
    app::manager::Controller::sendAction(application,
                                         app::manager::actions::AbortPopup,
                                         std::make_unique<gui::PopupRequestParams>(gui::popup::ID::BluetoothInfo));
}

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

#pragma once

#include <popups/WindowWithTimer.hpp>
#include <gui/widgets/Icon.hpp>

namespace gui
{
    class BluetoothInfoPopup : public WindowWithTimer
    {
      private:
        Icon *infoIcon = nullptr;
        void closePopups();

      public:
        BluetoothInfoPopup(app::ApplicationCommon *app, const std::string &name);

        void buildInterface() override;
        bool onInput(const InputEvent &inputEvent) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };
} /* namespace gui */

M module-apps/apps-common/popups/CMakeLists.txt => module-apps/apps-common/popups/CMakeLists.txt +4 -0
@@ 15,6 15,8 @@ target_sources(apps-common
		TetheringNotificationPopup.cpp
		TetheringPhoneModePopup.cpp
		TetheringOffPopup.cpp
		BluetoothAuthenticatePopup.cpp
		BluetoothInfoPopup.cpp
		VolumeWindow.cpp
		WindowWithTimer.cpp
		lock-popups/PhoneLockedInfoWindow.cpp


@@ 41,6 43,8 @@ target_sources(apps-common
		TetheringConfirmationPopup.hpp
		TetheringNotificationPopup.hpp
		TetheringPhoneModePopup.hpp
		BluetoothAuthenticatePopup.hpp
		BluetoothInfoPopup.hpp
		VolumeWindow.hpp
		WindowWithTimer.hpp
		data/PopupData.hpp

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

#include "Popups.hpp"


@@ 20,6 20,10 @@ namespace gui::popup
            return gui::popup::window::tethering_confirmation_window;
        case ID::TetheringPhoneModeChangeProhibited:
            return gui::popup::window::tethering_phonemode_change_window;
        case ID::BluetoothAuthenticate:
            return gui::popup::window::bluetooth_authenticate;
        case ID::BluetoothInfo:
            return gui::popup::window::bluetooth_info;
        case ID::PhoneLock:
            return gui::popup::window::phone_lock_window;
        case ID::PhoneLockInput:

M module-apps/apps-common/popups/Popups.hpp => module-apps/apps-common/popups/Popups.hpp +4 -0
@@ 16,6 16,8 @@ namespace gui
            Brightness,
            Tethering,
            TetheringPhoneModeChangeProhibited,
            BluetoothAuthenticate,
            BluetoothInfo,
            PhoneLock,
            PhoneLockInput,
            PhoneLockInfo,


@@ 40,6 42,8 @@ namespace gui
            inline constexpr auto tethering_confirmation_window     = "TetheringConfirmationPopup";
            inline constexpr auto tethering_phonemode_change_window = "TetheringPhoneModeChangeProhibitedPopup";
            inline constexpr auto tethering_off_window              = "TetheringOffPopup";
            inline constexpr auto bluetooth_authenticate            = "BluetoothAuthenticatePopup";
            inline constexpr auto bluetooth_info                    = "BluetoothInfoPopup";
            inline constexpr auto phone_lock_window                 = "PhoneLockPopup";
            inline constexpr auto phone_lock_info_window            = "PhoneLockInfoPopup";
            inline constexpr auto phone_lock_input_window           = "PhoneLockInputPopup";

M module-apps/apps-common/popups/data/PopupRequestParams.hpp => module-apps/apps-common/popups/data/PopupRequestParams.hpp +50 -0
@@ 8,6 8,7 @@

#include <PhoneModes/Common.hpp>
#include <module-audio/Audio/AudioCommon.hpp>
#include <service-bluetooth/messages/Authenticate.hpp>
#include <locks/widgets/Lock.hpp>
#include <locks/data/LockData.hpp>



@@ 85,6 86,55 @@ namespace gui
        sys::phone_modes::PhoneMode phoneMode;
    };

    class BluetoothAuthenticateRequestParams : public PopupRequestParams
    {
      private:
        Devicei device;
        bluetooth::AuthenticateType type;

      public:
        explicit BluetoothAuthenticateRequestParams(const Devicei &dev, bluetooth::AuthenticateType type)
            : PopupRequestParams{gui::popup::ID::BluetoothAuthenticate}, device{dev}, type{type}
        {}

        [[nodiscard]] auto getDevice() const noexcept
        {
            return device;
        }

        [[nodiscard]] auto getAuthenticateType() const noexcept
        {
            return type;
        }
    };

    class BluetoothInfoParams : public PopupRequestParams
    {
      private:
        Devicei device;
        bool succeed;
        std::string errorCode;

      public:
        explicit BluetoothInfoParams(const Devicei &dev, bool succeed, std::string errorCode = "")
            : PopupRequestParams{gui::popup::ID::BluetoothInfo}, device{dev}, succeed{succeed}, errorCode{errorCode}
        {}

        [[nodiscard]] auto getDevice() const noexcept
        {
            return device;
        }

        [[nodiscard]] auto isSucceed() const noexcept -> bool
        {
            return succeed;
        }
        [[nodiscard]] auto getErrorCode() const noexcept -> std::string
        {
            return errorCode;
        }
    };

    class VolumePopupRequestParams : public PopupRequestParams
    {
      public:

M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp +13 -23
@@ 42,6 42,11 @@ namespace bluetooth
            AVRCP::mediaTracker.avrcp_cid = local_cid;
            avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);

            avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED);
            avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED);
            avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid,
                                       AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);

            avrcp_target_set_now_playing_info(
                AVRCP::mediaTracker.avrcp_cid, NULL, sizeof(AVRCP::tracks) / sizeof(avrcp_track_t));
            avrcp_target_set_unit_info(AVRCP::mediaTracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, AVRCP::companyId);


@@ 49,11 54,6 @@ namespace bluetooth
                                          AVRCP_SUBUNIT_TYPE_AUDIO,
                                          (uint8_t *)AVRCP::subunitInfo,
                                          sizeof(AVRCP::subunitInfo));

            avrcp_controller_get_supported_events(AVRCP::mediaTracker.avrcp_cid);

            LOG_INFO("AVRCP: Channel successfully opened:  A2DP::mediaTracker.avrcp_cid 0x%02x\n",
                     AVRCP::mediaTracker.avrcp_cid);
            return;

        case AVRCP_SUBEVENT_CONNECTION_RELEASED:


@@ 91,18 91,6 @@ namespace bluetooth
                     AVRCP::mediaTracker.volume * 127 / 100,
                     AVRCP::mediaTracker.volume);
            break;
        case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
            status = avrcp_target_supported_events(AVRCP::mediaTracker.avrcp_cid,
                                                   AVRCP::eventsNum,
                                                   const_cast<uint8_t *>(AVRCP::events),
                                                   sizeof(AVRCP::events));
            break;
        case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
            status = avrcp_target_supported_companies(AVRCP::mediaTracker.avrcp_cid,
                                                      AVRCP::companiesNum,
                                                      const_cast<uint8_t *>(AVRCP::companies),
                                                      sizeof(AVRCP::companies));
            break;
        case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
            status = avrcp_target_play_status(AVRCP::mediaTracker.avrcp_cid,
                                              AVRCP::playInfo.song_length_ms,


@@ 175,13 163,15 @@ namespace bluetooth
            busProxy.sendUnicast(std::make_shared<message::bluetooth::A2DPVolume>(volume), service::name::bluetooth);
            LOG_INFO("AVRCP Controller: notification absolute volume changed %d %%\n", volume * 100 / 127);
        } break;
        case AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID:
            LOG_INFO("Remote supports EVENT_ID 0x%02x\n", avrcp_subevent_get_capability_event_id_get_event_id(packet));
        case AVRCP_SUBEVENT_NOTIFICATION_EVENT_BATT_STATUS_CHANGED:
            // see avrcp_battery_status_t
            LOG_INFO("AVRCP Controller: Notification Battery Status %d\n",
                     avrcp_subevent_notification_event_batt_status_changed_get_battery_status(packet));
            break;
        case AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE:
            LOG_INFO("automatically enable notifications\n");
            avrcp_controller_enable_notification(AVRCP::mediaTracker.avrcp_cid,
                                                 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
        case AVRCP_SUBEVENT_NOTIFICATION_STATE:
            LOG_INFO("AVRCP Controller: Notification %s - %s\n",
                     avrcp_event2str(avrcp_subevent_notification_state_get_event_id(packet)),
                     avrcp_subevent_notification_state_get_enabled(packet) != 0 ? "enabled" : "disabled");
            break;
        default:
            break;

M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp +10 -6
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "GAP.hpp"


@@ 9,7 9,7 @@
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-bluetooth/messages/ResponseVisibleDevices.hpp>
#include <service-bluetooth/messages/Unpair.hpp>
#include <service-bluetooth/messages/Passkey.hpp>
#include <service-bluetooth/messages/Authenticate.hpp>
#include <service-bluetooth/Constants.hpp>
#include <log/log.hpp>
#include <memory>


@@ 97,7 97,6 @@ namespace bluetooth
        return false;
    }


    void GAP::sendDevices()
    {
        auto msg = std::make_shared<message::bluetooth::ResponseVisibleDevices>(devices().getList());


@@ 258,7 257,9 @@ namespace bluetooth
            }
            it->isPairingSSP = false;

            auto msg = std::make_shared<::message::bluetooth::RequestPasskey>(*it);
            /// TODO additional authenticate types to be added in next PRs.
            auto msg =
                std::make_shared<::message::bluetooth::RequestAuthenticate>(*it, bluetooth::AuthenticateType::Passkey);
            ownerService->bus.sendMulticast(std::move(msg), sys::BusChannel::BluetoothNotifications);
        } break;



@@ 289,8 290,11 @@ namespace bluetooth
                it = devices().put(addr);
            }
            it->isPairingSSP = true;
            ownerService->bus.sendMulticast(std::make_shared<::message::bluetooth::RequestPasskey>(*it),
                                            sys::BusChannel::BluetoothNotifications);

            /// TODO additional authenticate types to be added in next PRs.
            ownerService->bus.sendMulticast(
                std::make_shared<::message::bluetooth::RequestAuthenticate>(*it, bluetooth::AuthenticateType::Passkey),
                sys::BusChannel::BluetoothNotifications);
        } break;
        case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: {
            bd_addr_t addr;

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +9 -14
@@ 182,20 182,15 @@ namespace bluetooth
            }
            isConnected = true;
            break;
        case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
            if (hsp_subevent_rfcomm_disconnection_complete_get_status(event) != 0u) {
                LOG_DEBUG("RFCOMM disconnection failed with status %u.\n",
                          hsp_subevent_rfcomm_disconnection_complete_get_status(event));
            }
            else {
                LOG_DEBUG("RFCOMM disconnected.\n");
                sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
                auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
                busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
                                     service::name::bluetooth);
            }
        case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: {
            LOG_DEBUG("RFCOMM disconnected.\n");
            sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
            auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
            busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
                                 service::name::bluetooth);

            isConnected = false;
            break;
        } break;
        case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
            if (hsp_subevent_audio_connection_complete_get_status(event) != 0u) {
                LOG_DEBUG("Audio connection establishment failed with status %u\n",


@@ 205,7 200,7 @@ namespace bluetooth
                audioDevice.reset();
            }
            else {
                scoHandle = hsp_subevent_audio_connection_complete_get_handle(event);
                scoHandle = hsp_subevent_audio_connection_complete_get_sco_handle(event);
                LOG_DEBUG("Audio connection established with SCO handle 0x%04x.\n", scoHandle);
                callAnswered = true;
                hci_request_sco_can_send_now_event();

M module-bluetooth/lib/btstack => module-bluetooth/lib/btstack +1 -1
@@ 1,1 1,1 @@
Subproject commit 0338cd047da606046f136fea3ebec4a27473a985
Subproject commit e20f13fc58a9c227c4f7bc4b1267a072ba2e5e30

M module-bsp/board/linux/CMakeLists.txt => module-bsp/board/linux/CMakeLists.txt +1 -0
@@ 4,6 4,7 @@ target_sources(module-bsp
        PRIVATE
                board.cpp

                battery_charger/battery_charger.cpp
                bluetooth/Bluetooth.cpp
                bluetooth/test/bsp_bt.cpp
                cellular/linux_cellular.cpp

A module-bsp/board/linux/battery_charger/battery_charger.cpp => module-bsp/board/linux/battery_charger/battery_charger.cpp +16 -0
@@ 0,0 1,16 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "battery_charger/battery_charger.hpp"

namespace bsp::battery_charger
{
    int getAvgCurrent()
    {
        return 0;
    }
    int getCurrentMeasurement()
    {
        return 0;
    }
} // namespace bsp::battery_charger

M module-bsp/board/linux/lpm/PowerProfile.cpp => module-bsp/board/linux/lpm/PowerProfile.cpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <bsp/lpm/PowerProfile.hpp>


@@ 15,7 15,6 @@ namespace bsp
        linuxPowerProfile.maxBelowThresholdInRowCount       = 10;
        linuxPowerProfile.maxAboveThresholdCount            = 3;
        linuxPowerProfile.minimalFrequency                  = CpuFrequencyMHz::Level_1;
        linuxPowerProfile.frequencyIncreaseIntermediateStep = false;

        return linuxPowerProfile;
    }

M module-bsp/board/linux/torch/torch.cpp => module-bsp/board/linux/torch/torch.cpp +4 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "bsp/torch/torch.hpp"


@@ 48,9 48,9 @@ namespace bsp
            return true;
        }

        std::pair<bool, State> getState()
        State getState()
        {
            return std::make_pair(true, state_simulated);
            return state_simulated;
        }

        ColourTemperature getColorTemp()


@@ 60,7 60,7 @@ namespace bsp

        bool toggle()
        {
            return turn(getState().second == State::off ? State::on : State::off);
            return turn(getState() == State::off ? State::on : State::off);
        };

        bool setCurrent(const unsigned short mA)

M module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp => module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <bsp/lpm/PowerProfile.hpp>


@@ 15,7 15,6 @@ namespace bsp
        bellPowerProfile.maxBelowThresholdInRowCount       = 1;
        bellPowerProfile.maxAboveThresholdCount            = 2;
        bellPowerProfile.minimalFrequency                  = CpuFrequencyMHz::Level_0;
        bellPowerProfile.frequencyIncreaseIntermediateStep = true;

        return bellPowerProfile;
    }

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp +63 -1
@@ 14,6 14,7 @@
#include "ClockState.hpp"
#include "Oscillator.hpp"
#include "critical.hpp"
#include "drivers/semc/DriverSEMC.hpp"

namespace bsp
{


@@ 22,6 23,7 @@ namespace bsp

    RT1051LPM::RT1051LPM()
    {
        driverSEMC = drivers::DriverSEMC::Create(drivers::name::ExternalRAM);
        gpio_1 = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::POWER_SWITCH_HOLD_GPIO),
                                    DriverGPIOParams{});
        gpio_2 = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::DCDC_INVERTER_MODE_GPIO),


@@ 72,9 74,64 @@ namespace bsp
        return 0;
    }

    enum class Change
    {
        Up,
        Down
    };

    CpuFrequencyMHz RT1051LPM::onChangeUp(CpuFrequencyMHz freq, bsp::CpuFrequencyMHz newFrequency)
    {
        if ((freq <= CpuFrequencyMHz::Level_1) && (newFrequency > CpuFrequencyMHz::Level_1)) {
            // connect internal the load resistor
            ConnectInternalLoadResistor();
            // turn off power save mode for DCDC inverter
            DisableDcdcPowerSaveMode();
            // Switch DCDC to full throttle during oscillator switch
            SetHighestCoreVoltage();
            // Enable regular 2P5 and 1P1 LDO and Turn off weak 2P5 and 1P1 LDO
            SwitchToRegularModeLDO();
            // switch oscillator source
            SwitchOscillatorSource(LowPowerMode::OscillatorSource::External);
            // then switch external RAM clock source
            if (driverSEMC) {
                driverSEMC->SwitchToPLL2ClockSource();
            }
            // Add intermediate step in frequency
            if (newFrequency > CpuFrequencyMHz::Level_4)
                return CpuFrequencyMHz::Level_4;
        }
        return newFrequency;
    }

    void RT1051LPM::onChangeDown(CpuFrequencyMHz newFrequency)
    {
        if (newFrequency <= bsp::CpuFrequencyMHz::Level_1) {
            // Enable weak 2P5 and 1P1 LDO and Turn off regular 2P5 and 1P1 LDO
            SwitchToLowPowerModeLDO();
            // then switch osc source
            SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::Internal);
            // and switch external RAM clock source
            if (driverSEMC) {
                driverSEMC->SwitchToPeripheralClockSource();
            }
            // turn on power save mode for DCDC inverter
            EnableDcdcPowerSaveMode();

            // disconnect internal the load resistor
            DisconnectInternalLoadResistor();
        }
    }

    void RT1051LPM::SetCpuFrequency(bsp::CpuFrequencyMHz freq)
    {
        currentFrequency = freq;
        if (currentFrequency == freq) {
            return;
        }
        Change change = currentFrequency < freq ? Change::Up : Change::Down;
        if (Change::Up == change) {
            freq = onChangeUp(currentFrequency, freq);
        }
        switch (freq) {
        case bsp::CpuFrequencyMHz::Level_0:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_4_Mhz);


@@ 98,7 155,12 @@ namespace bsp
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_528_Mhz);
            break;
        }

        if (Change::Down == change) {
            onChangeDown(freq);
        }
        LOG_INFO("CPU frequency changed to %lu", CLOCK_GetFreq(kCLOCK_CpuClk));
        currentFrequency = freq;
    }

    void RT1051LPM::SetHighestCoreVoltage()

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp +4 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef PUREPHONE_RT1051LPM_HPP


@@ 32,9 32,12 @@ namespace bsp
        void SwitchToLowPowerModeLDO() final;

      private:
        CpuFrequencyMHz onChangeUp(CpuFrequencyMHz freq, CpuFrequencyMHz newFrequency);
        void onChangeDown(bsp::CpuFrequencyMHz freq);
        std::shared_ptr<drivers::DriverGPIO> gpio_1;
        std::shared_ptr<drivers::DriverGPIO> gpio_2;
        std::unique_ptr<bsp::CpuFreqLPM> CpuFreq;
        std::shared_ptr<drivers::DriverSEMC> driverSEMC;
    };

} // namespace bsp

M module-bsp/board/rt1051/bsp/torch/torch.cpp => module-bsp/board/rt1051/bsp/torch/torch.cpp +20 -25
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "bsp/torch/torch.hpp"


@@ 47,12 47,10 @@ namespace bsp
            gpio->WritePin(static_cast<uint32_t>(BoardDefinitions::TORCH_DRIVER_EN), 1);
            vTaskDelay(pdMS_TO_TICKS(5));

            if (isPresent()) {
                turn(State::off);
                setCurrent(max_current_mA);
                return kStatus_Success;
            }
            return kStatus_Fail;
            auto present = isPresent();
            turn(State::off);

            return present ? kStatus_Success : kStatus_Fail;
        }

        void deinit()


@@ 95,6 93,11 @@ namespace bsp
        };
        bool turn(State state, ColourTemperature colourTemp)
        {
            if (state == State::on) {
                gpio->WritePin(static_cast<uint32_t>(BoardDefinitions::TORCH_DRIVER_EN), 1);
                setCurrent(max_current_mA);
            }

            if (colourTemp != ColourTemperature::noChange) {
                currentColourTemp = colourTemp;
            }


@@ 114,24 117,21 @@ namespace bsp
                .tx_pin_en     = 0,
            };
            auto wrote = i2c->Write(addr, (uint8_t *)(&en_reg), 1);

            if (state == State::off) {
                gpio->WritePin(static_cast<uint32_t>(BoardDefinitions::TORCH_DRIVER_EN), 0);
            }

            if (wrote != 1) {
                return false;
            }
            return true;
        }

        std::pair<bool, State> getState()
        State getState()
        {
            addr.subAddress = AL3644TT_ENABLE_REG;
            al3644tt_enable_reg en_reg;
            auto read = i2c->Read(addr, (uint8_t *)(&en_reg), 1);
            if (read != 1) {
                return std::make_pair(false, State::off); // invalid
            }
            return std::make_pair(true,
                                  (en_reg.led1_en == AL3644TT_LED_ENABLED || en_reg.led2_en == AL3644TT_LED_ENABLED)
                                      ? State::on
                                      : State::off);
            auto read = gpio->ReadPin(static_cast<uint32_t>(BoardDefinitions::TORCH_DRIVER_EN));
            return read ? State::on : State::off;
        }

        ColourTemperature getColorTemp()


@@ 141,13 141,8 @@ namespace bsp

        bool toggle()
        {
            auto [success, state] = getState();
            if (success == false) {
                return false;
            }
            else {
                return turn(state == State::off ? State::on : State::off);
            }
            auto state = getState();
            return turn(state == State::off ? State::on : State::off);
        }
    } // namespace torch
} // namespace bsp

M module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger.hpp => module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger.hpp +0 -4
@@ 83,10 83,6 @@ namespace bsp::battery_charger

    int getVoltageFilteredMeasurement();

    int getAvgCurrent();

    int getCurrentMeasurement();

    MaxMinVolt getMaxMinVolt();

    void printFuelGaugeInfo();

M module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp => module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <bsp/lpm/PowerProfile.hpp>


@@ 15,7 15,6 @@ namespace bsp
        purePowerProfile.maxBelowThresholdInRowCount       = 1;
        purePowerProfile.maxAboveThresholdCount            = 2;
        purePowerProfile.minimalFrequency                  = CpuFrequencyMHz::Level_0;
        purePowerProfile.frequencyIncreaseIntermediateStep = true;

        return purePowerProfile;
    }

M module-bsp/board/rt1051/puretx/hal/battery_charger/CurrentMeasurementScope.cpp => module-bsp/board/rt1051/puretx/hal/battery_charger/CurrentMeasurementScope.cpp +1 -1
@@ 8,7 8,7 @@ extern "C"
#include "FreeRTOS.h"
}
#include <timers.h>
#include <bsp/battery_charger/battery_charger.hpp>
#include <battery_charger/battery_charger.hpp>
#include <ticks.hpp>

#include <chrono>

A module-bsp/bsp/battery_charger/battery_charger.hpp => module-bsp/bsp/battery_charger/battery_charger.hpp +6 -0
@@ 0,0 1,6 @@
#pragma once

namespace bsp::battery_charger {
    int getAvgCurrent();
    int getCurrentMeasurement();
}

M module-bsp/bsp/lpm/PowerProfile.hpp => module-bsp/bsp/lpm/PowerProfile.hpp +0 -1
@@ 16,7 16,6 @@ namespace bsp
        std::uint32_t maxBelowThresholdInRowCount;
        std::uint32_t maxAboveThresholdCount;
        CpuFrequencyMHz minimalFrequency;
        bool frequencyIncreaseIntermediateStep;
    };

    const PowerProfile getPowerProfile();

M module-bsp/bsp/lpm/bsp_lpm.hpp => module-bsp/bsp/lpm/bsp_lpm.hpp +5 -0
@@ 7,6 7,11 @@
#include <memory>
#include <bsp/common.hpp>

namespace drivers
{
    class DriverSEMC;
}

namespace bsp
{


M module-bsp/bsp/torch/torch.hpp => module-bsp/bsp/torch/torch.hpp +1 -1
@@ 33,7 33,7 @@ namespace bsp::torch
    bool isPresent(void);

    bool turn(State state, ColourTemperature = ColourTemperature::noChange);
    std::pair<bool, State> getState();
    State getState();
    ColourTemperature getColorTemp();
    bool toggle();
    bool setCurrent(const unsigned short mA);

M module-bsp/drivers/semc/DriverSEMC.hpp => module-bsp/drivers/semc/DriverSEMC.hpp +5 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 8,6 8,10 @@

namespace drivers
{
    namespace name
    {
        constexpr auto ExternalRAM = "ExternalRAM";
    }

    class DriverSEMC : public devices::Device
    {

M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +21 -4
@@ 37,7 37,7 @@
#include <BtKeysStorage.hpp>
#include <Timers/TimerFactory.hpp>
#include <typeinfo>
#include <service-bluetooth/messages/Passkey.hpp>
#include <service-bluetooth/messages/Authenticate.hpp>
#include <GAP/GAP.hpp>
#include <service-cellular/CellularMessage.hpp>



@@ 106,7 106,9 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
    connectHandler<message::bluetooth::SetStatus>();
    connectHandler<message::bluetooth::Unpair>();
    connectHandler<sdesktop::developerMode::DeveloperModeRequest>();
    connectHandler<message::bluetooth::ResponsePasskey>();
    connectHandler<message::bluetooth::ResponseAuthenticatePin>();
    connectHandler<message::bluetooth::ResponseAuthenticatePasskey>();
    connectHandler<message::bluetooth::ResponseAuthenticatePairCancel>();
    connectHandler<CellularCallerIdMessage>();
    connectHandler<CellularCallActiveNotification>();



@@ 241,6 243,7 @@ auto ServiceBluetooth::handle(BluetoothPairResultMessage *msg) -> std::shared_pt

    bluetoothDevicesModel->syncDevicesWithApp();

    /// TODO error code handing added in next PRs
    bus.sendMulticast(std::make_shared<BluetoothPairResultMessage>(msg->getDevice(), msg->isSucceed()),
                      sys::BusChannel::BluetoothNotifications);



@@ 295,7 298,7 @@ auto ServiceBluetooth::handle(message::bluetooth::Connect *msg) -> std::shared_p
auto ServiceBluetooth::handle(message::bluetooth::ConnectResult *msg) -> std::shared_ptr<sys::Message>
{
    if (msg->isSucceed()) {
        auto device        = msg->getDevice();
        auto device = msg->getDevice();
        bluetoothDevicesModel->mergeInternalDeviceState(device);

        settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, bd_addr_to_str(device.address));


@@ 348,13 351,27 @@ auto ServiceBluetooth::handle(message::bluetooth::DisconnectResult *msg) -> std:
    return sys::MessageNone{};
}

auto ServiceBluetooth::handle(message::bluetooth::ResponsePasskey *msg) -> std::shared_ptr<sys::Message>
auto ServiceBluetooth::handle(message::bluetooth::ResponseAuthenticatePin *msg) -> std::shared_ptr<sys::Message>
{
    /// TODO to be added in next PRs
    auto pin = msg->getPin();
    bluetooth::GAP::respondPinCode(pin, msg->getDevice());
    return sys::MessageNone{};
}

auto ServiceBluetooth::handle(message::bluetooth::ResponseAuthenticatePasskey *msg) -> std::shared_ptr<sys::Message>
{
    auto passKey = msg->getPasskey();
    bluetooth::GAP::respondPinCode(passKey, msg->getDevice());
    return sys::MessageNone{};
}

auto ServiceBluetooth::handle(message::bluetooth::ResponseAuthenticatePairCancel *msg) -> std::shared_ptr<sys::Message>
{
    /// TODO to be added in next PRs
    return sys::MessageNone{};
}

auto ServiceBluetooth::handle(BluetoothMessage *msg) -> std::shared_ptr<sys::Message>
{
    LOG_INFO("Bluetooth request!");

M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +9 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 50,8 50,9 @@ class BluetoothMessage : public sys::DataMessage
class BluetoothPairResultMessage : public sys::DataMessage
{
  public:
    explicit BluetoothPairResultMessage(const Devicei device, bool succeed)
        : sys::DataMessage(MessageType::BluetoothPairResult), device(device), succeed(succeed)
    explicit BluetoothPairResultMessage(const Devicei &device, bool succeed, std::string errorCode = "")
        : sys::DataMessage(MessageType::BluetoothPairResult), device(device), succeed(succeed),
          errorCode(std::move(errorCode))
    {}
    [[nodiscard]] auto getDevice() const -> Devicei
    {


@@ 61,10 62,15 @@ class BluetoothPairResultMessage : public sys::DataMessage
    {
        return succeed;
    }
    [[nodiscard]] auto getErrorCode() const noexcept -> std::string
    {
        return errorCode;
    }

  private:
    Devicei device;
    bool succeed;
    std::string errorCode;
};

class BluetoothAddrMessage : public sys::DataMessage

M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +5 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 19,7 19,7 @@
#include <memory> // for unique_ptr
namespace message::bluetooth
{
    class ResponsePasskey;
    class ResponseAuthenticate;
}
class BluetoothWorker;
namespace settings


@@ 112,7 112,9 @@ class ServiceBluetooth : public sys::Service
    [[nodiscard]] auto handle(message::bluetooth::HFPVolume *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::Ring *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::StartAudioRouting *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::ResponsePasskey *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePin *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePasskey *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePairCancel *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularCallerIdMessage *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularCallActiveNotification *msg) -> std::shared_ptr<sys::Message>;
};

A module-services/service-bluetooth/service-bluetooth/messages/Authenticate.hpp => module-services/service-bluetooth/service-bluetooth/messages/Authenticate.hpp +105 -0
@@ 0,0 1,105 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "service-bluetooth/BluetoothMessage.hpp"

namespace bluetooth
{
    enum class AuthenticateType
    {
        Pin,
        Passkey,
        PairCancel
    };
}

namespace message::bluetooth
{

    class RequestAuthenticate : public BluetoothMessage
    {
      private:
        Devicei device;
        ::bluetooth::AuthenticateType type;

      public:
        RequestAuthenticate(const Devicei &dev, ::bluetooth::AuthenticateType type) : device(dev), type(type)
        {}

        [[nodiscard]] auto getDevice()
        {
            return device;
        }

        [[nodiscard]] auto getAuthenticateType()
        {
            return type;
        }
    };

    class ResponseAuthenticate : public BluetoothMessage
    {
      private:
        Devicei device;

      protected:
        explicit ResponseAuthenticate(const Devicei &dev) : device(dev)
        {}

      public:
        [[nodiscard]] auto getDevice()
        {
            return device;
        }
    };

    class ResponseAuthenticatePin : public ResponseAuthenticate
    {
      private:
        std::string pin;

      public:
        ResponseAuthenticatePin(std::string pin, const Devicei &dev) : ResponseAuthenticate(dev), pin(std::move(pin))
        {}

        [[nodiscard]] auto getPin() const -> std::string
        {
            return pin;
        }
    };

    class ResponseAuthenticatePasskey : public ResponseAuthenticate
    {
      private:
        std::string passkey;

      public:
        ResponseAuthenticatePasskey(std::string passkey, const Devicei &dev)
            : ResponseAuthenticate(dev), passkey(std::move(passkey))
        {}

        [[nodiscard]] auto getPasskey() const -> std::string
        {
            return passkey;
        }
    };

    class ResponseAuthenticatePairCancel : public ResponseAuthenticate
    {
      private:
        bool pairApproved = false;

      public:
        ResponseAuthenticatePairCancel(bool pairApproved, const Devicei &dev)
            : ResponseAuthenticate(dev), pairApproved(pairApproved)
        {}

        [[nodiscard]] auto getPairApproved() const -> bool
        {
            return pairApproved;
        }
    };

} // namespace message::bluetooth

M module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp => module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

D module-services/service-bluetooth/service-bluetooth/messages/Passkey.hpp => module-services/service-bluetooth/service-bluetooth/messages/Passkey.hpp +0 -45
@@ 1,45 0,0 @@
// 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-bluetooth/BluetoothMessage.hpp"

namespace message::bluetooth
{
    class RequestPasskey : public BluetoothMessage
    {
        Devicei device;

      public:
        explicit RequestPasskey(const Devicei &dev) : device(dev)
        {}

        [[nodiscard]] auto getDevice()
        {
            return device;
        }
    };

    class ResponsePasskey : public BluetoothMessage
    {
        Devicei device;

      public:
        ResponsePasskey(std::string passkey, const Devicei &dev) : device(dev), passkey(std::move(passkey))
        {}

        [[nodiscard]] auto getPasskey() const -> std::string
        {
            return passkey;
        }

        [[nodiscard]] auto getDevice()
        {
            return device;
        }

      private:
        std::string passkey;
    };
} // namespace message::bluetooth

M module-services/service-cellular/CMakeLists.txt => module-services/service-cellular/CMakeLists.txt +1 -0
@@ 19,6 19,7 @@ set(SOURCES
    call/CellularCall.cpp
    call/CallAudio.cpp
    call/CallGUI.cpp
    call/CallDB.cpp
    call/CallRingGuard.cpp
    CellularServiceAPI.cpp
    CellularUrcHandler.cpp

A module-services/service-cellular/call/CallDB.cpp => module-services/service-cellular/call/CallDB.cpp +18 -0
@@ 0,0 1,18 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CallDB.hpp"
#include "service-appmgr/data/CallActionsParams.hpp"
#include <queries/notifications/QueryNotificationsIncrement.hpp>
#include <service-appmgr/Controller.hpp>

CallDB::CallDB(sys::Service &s) : owner(s)
{}

void CallDB::incrementNotAnsweredCallsNotification(const utils::PhoneNumber::View &number)
{
    DBServiceAPI::GetQuery(
        &owner,
        db::Interface::Name::Notifications,
        std::make_unique<db::query::notifications::Increment>(NotificationsRecord::Key::Calls, number));
}

A module-services/service-cellular/call/CallDB.hpp => module-services/service-cellular/call/CallDB.hpp +21 -0
@@ 0,0 1,21 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <PhoneNumber.hpp>

namespace sys
{
    class Service;
}

class CallDB
{
    sys::Service &owner;

  public:
    explicit CallDB(sys::Service &);

    void incrementNotAnsweredCallsNotification(const utils::PhoneNumber::View &number);
};

M module-services/service-cellular/call/CallRingGuard.cpp => module-services/service-cellular/call/CallRingGuard.cpp +5 -0
@@ 14,3 14,8 @@ bool callClipGuard(CellularCall::Call &call)
    return call.mode == sys::phone_modes::PhoneMode::DoNotDisturb && call.operations.areCallsFromFavouritesEnabled() &&
           call.operations.isNumberInFavourites();
}

bool callDNDGuard(CellularCall::Call &call)
{
    return call.mode == sys::phone_modes::PhoneMode::DoNotDisturb;
}

M module-services/service-cellular/call/CallRingGuard.hpp => module-services/service-cellular/call/CallRingGuard.hpp +8 -0
@@ 24,3 24,11 @@ bool callRingGuard(CellularCall::Call &call);
/// - we have this somebody phone number via CLIP URC
/// It wont be ever called for private numbers
bool callClipGuard(CellularCall::Call &call);

/// Guard to check if we should place missed call notification
/// This flow is when:
/// - We are in do not disturb mode
/// - somebody calls
/// - we have this somebody phone number via CLIP/RING URC
/// It wont be ever called for private numbers
bool callDNDGuard(CellularCall::Call &call);

M module-services/service-cellular/call/CellularCall.cpp => module-services/service-cellular/call/CellularCall.cpp +7 -1
@@ 6,6 6,7 @@
#include "service-cellular/ServiceCellular.hpp"
#include "service-db/agents/settings/SystemSettings.hpp"

#include <queries/notifications/QueryNotificationsIncrement.hpp>
#include <CalllogRecord.hpp>
#include <PhoneNumber.hpp>
#include <Utils.hpp>


@@ 21,7 22,7 @@

namespace CellularCall
{
    Call::Call(ServiceCellular &owner) : owner(owner), audio(owner), gui(owner)
    Call::Call(ServiceCellular &owner) : owner(owner), audio(owner), gui(owner), db(owner)
    {
        utils::PhoneNumber::View number = utils::PhoneNumber::View();
        const CallType type             = CallType::CT_NONE;


@@ 60,6 61,11 @@ namespace CellularCall
            gui.notifyCLIP(number);
            return true;
        }

        if (callDNDGuard(*this)) {
            db.incrementNotAnsweredCallsNotification(number);
        }

        return false;
    }


M module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp => module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp +2 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-cellular/service-cellular/connection-manager/ConnectionManagerCellularCommands.hpp>


@@ 100,11 100,9 @@ void ConnectionManagerCellularCommands::stopConnectionTimer()

void ConnectionManagerCellularCommands::holdMinimumCpuFrequency()
{
    auto handle = cellular.getTaskHandle();
    if (cellular.cpuSentinel) {
        cellular.cpuSentinel->HoldMinimumFrequencyAndWait(bsp::CpuFrequencyMHz::Level_4, handle, 2000);
        cellular.cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_4);
    }
    return;
}
void ConnectionManagerCellularCommands::retryPhoneModeChange()
{

M module-services/service-cellular/service-cellular/call/CellularCall.hpp => module-services/service-cellular/service-cellular/call/CellularCall.hpp +2 -0
@@ 5,6 5,7 @@

#include "call/CallAudio.hpp"
#include "call/CallGUI.hpp"
#include "call/CallDB.hpp"
#include "PhoneModes/PhoneMode.hpp"
#include <Interface/CalllogRecord.hpp>
#include <SystemManager/CpuSentinel.hpp>


@@ 63,6 64,7 @@ namespace CellularCall
        ServiceCellular &owner;
        CallRingAudio audio;
        CallGUI gui;
        CallDB db;

      public:
        void setMode(sys::phone_modes::PhoneMode mode)

M module-services/service-cellular/src/ServiceCellularPriv.cpp => module-services/service-cellular/src/ServiceCellularPriv.cpp +3 -9
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ServiceCellularPriv.hpp"


@@ 398,11 398,8 @@ namespace cellular::internal
    void ServiceCellularPriv::initCSQHandler()
    {
        csqHandler->onEnableCsqReporting = [this]() {
            constexpr auto cpuSentinelTimeout = 2000;
            auto handle                       = owner->getTaskHandle();
            if (owner->cpuSentinel) {
                owner->cpuSentinel->HoldMinimumFrequencyAndWait(
                    bsp::CpuFrequencyMHz::Level_4, handle, cpuSentinelTimeout);
                owner->cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_4);
            }

            auto channel = owner->cmux->get(CellularMux::Channel::Commands);


@@ 416,11 413,8 @@ namespace cellular::internal
        };

        csqHandler->onDisableCsqReporting = [this]() {
            constexpr auto cpuSentinelTimeout = 2000;
            auto handle                       = owner->getTaskHandle();
            if (owner->cpuSentinel) {
                owner->cpuSentinel->HoldMinimumFrequencyAndWait(
                    bsp::CpuFrequencyMHz::Level_4, handle, cpuSentinelTimeout);
                owner->cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_4);
            }

            auto channel = owner->cmux->get(CellularMux::Channel::Commands);

M module-services/service-evtmgr/api/torch.cpp => module-services/service-evtmgr/api/torch.cpp +2 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-evtmgr/torch.hpp"


@@ 10,8 10,7 @@ namespace event::service::api
{
    bool isTorchOn()
    {
        auto [works, isOn] = bsp::torch::getState();
        assert(works);
        auto isOn = bsp::torch::getState();
        return isOn == bsp::torch::State::on;
    }
} // namespace event::service::api

M module-sys/Service/Service.cpp => module-sys/Service/Service.cpp +11 -10
@@ 89,22 89,23 @@ namespace sys
    void Service::Run()
    {
        while (enableRunLoop) {
            auto msg = mailbox.pop();
            if (!msg) {
                continue;
            }
            processBus();
        }
        CloseService();
    };

            const bool respond = msg->type != Message::Type::Response && GetName() != msg->sender;
    void Service::processBus()
    {
        if (auto msg = mailbox.pop(); msg) {
            const bool respond  = msg->type != Message::Type::Response && GetName() != msg->sender;
            currentlyProcessing = msg;
            auto response      = msg->Execute(this);
            auto response       = msg->Execute(this);
            if (response == nullptr || !respond) {
                continue;
                return;
            }

            bus.sendResponse(response, msg);
        }
        CloseService();
    };
    }

    auto Service::MessageEntry(Message *message, ResponseMessage *response) -> MessagePointer
    {

M module-sys/Service/details/bus/Bus.cpp => module-sys/Service/details/bus/Bus.cpp +5 -3
@@ 146,9 146,11 @@ namespace sys
        std::vector<std::shared_ptr<Message>> tempMsg;
        tempMsg.reserve(4); // reserve space for 4 elements to avoid costly memory allocations

        uint32_t currentTime   = cpp_freertos::Ticks::GetTicks();
        uint32_t timeoutNeeded = currentTime + timeout;
        uint32_t timeElapsed   = currentTime;
        // NOTE: please mind that timeout + curentTime might overflow 32b
        // especially if we want to wait infinitely
        uint64_t currentTime   = cpp_freertos::Ticks::GetTicks();
        uint64_t timeoutNeeded = currentTime + timeout;
        uint64_t timeElapsed   = currentTime;

        while (1) {
            // timeout

M module-sys/Service/include/Service/Service.hpp => module-sys/Service/include/Service/Service.hpp +9 -5
@@ 30,7 30,7 @@ namespace sys
    class async_fail : public std::runtime_error
    {
      public:
        async_fail() : runtime_error("async failure")
        explicit async_fail(const std::string &reason) : runtime_error(reason)
        {}
    };



@@ 161,7 161,7 @@ namespace sys
            auto request = std::make_shared<Request>(arg...);
            if (isConnected(std::type_index(typeid(Response)))) {
                async.setState(Async<Request, Response>::State::Error);
                throw async_fail();
                throw async_fail("connection failure");
            }
            auto meta                                    = async.metadata;
            meta->request                                = request;


@@ 174,10 174,10 @@ namespace sys
            };

            if (!connect(typeid(Response), foo)) {
                throw async_fail();
                throw async_fail("cant connect");
            }
            if (!bus.sendUnicast(request, whom)) {
                throw async_fail();
                throw async_fail("cant send to " + whom);
            }
            return async;
        }


@@ 188,7 188,7 @@ namespace sys
            static_assert(std::is_base_of<sys::ResponseMessage, Response>::value,
                          "Response has to be based on system message");
            if (async.metadata->request == nullptr) {
                throw async_fail();
                throw async_fail("there was no request");
            }
            if (async.getState() != Async<Request, Response>::State::Pending) {
                return;


@@ 209,6 209,10 @@ namespace sys
        bool enableRunLoop;

        void Run() override;
        /// one and only buss processing function to run in the loop
        /// please __always__ call it in Run() method in loop instead
        /// creating different implementations in other services
        virtual void processBus() final;

        std::map<std::type_index, MessageHandler> message_handlers;


M module-sys/SystemManager/CMakeLists.txt => module-sys/SystemManager/CMakeLists.txt +5 -0
@@ 23,6 23,11 @@ target_sources(sys-manager
        graph/TopologicalSort.hpp
        PowerManager.cpp
        SystemManagerCommon.cpp
        cpu/AlgorithmFactory.cpp
        cpu/algorithm/Algorithm.cpp
        cpu/algorithm/FrequencyHold.cpp
        cpu/algorithm/ImmediateUpscale.cpp
        cpu/algorithm/FrequencyStepping.cpp
)

target_include_directories(sys-manager

M module-sys/SystemManager/CpuGovernor.cpp => module-sys/SystemManager/CpuGovernor.cpp +4 -23
@@ 83,15 83,8 @@ namespace sys
        std::for_each(std::begin(sentinels), std::end(sentinels), PrintName);
    }

    void CpuGovernor::SetCpuFrequencyRequest(std::string sentinelName,
                                             bsp::CpuFrequencyMHz request,
                                             bool permanentBlock)
    void CpuGovernor::SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request)
    {
        if (permanentBlock) {
            permanentFrequencyToHold.isActive        = true;
            permanentFrequencyToHold.frequencyToHold = request;
            return;
        }
        for (auto &sentinel : sentinels) {
            auto sentinelWeakPointer = sentinel->GetSentinel();
            if (!sentinelWeakPointer.expired()) {


@@ 103,19 96,14 @@ namespace sys
        }
    }

    void CpuGovernor::ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock)
    void CpuGovernor::ResetCpuFrequencyRequest(const std::string &sentinelName)
    {
        if (permanentBlock) {
            permanentFrequencyToHold.isActive        = false;
            permanentFrequencyToHold.frequencyToHold = bsp::CpuFrequencyMHz::Level_0;
            return;
        }
        SetCpuFrequencyRequest(sentinelName, bsp::CpuFrequencyMHz::Level_0);
    }

    [[nodiscard]] auto CpuGovernor::GetMinimumFrequencyRequested() const noexcept -> sentinel::Data
    [[nodiscard]] auto CpuGovernor::GetMinimumFrequencyRequested() const noexcept -> sentinel::View
    {
        sentinel::Data d;
        sentinel::View d;
        if (sentinels.empty()) {
            d.reason = "empty";
            return d;


@@ 133,7 121,6 @@ namespace sys
        d.frequency = (*minSentinel)->GetRequestedFrequency();
        if (auto p = (*minSentinel)->GetSentinel().lock()) {
            d.name   = p->GetName();
            d.task   = p->getTask();
            d.reason = p->getReason();
        }
        else {


@@ 161,10 148,4 @@ namespace sys
            LOG_INFO("Sentinel %s", sharedResource->GetName().c_str());
        }
    }

    [[nodiscard]] auto CpuGovernor::GetPermanentFrequencyRequested() const noexcept -> PermanentFrequencyToHold
    {
        return permanentFrequencyToHold;
    }

} // namespace sys

M module-sys/SystemManager/CpuLogPrinter.cpp => module-sys/SystemManager/CpuLogPrinter.cpp +3 -0
@@ 44,4 44,7 @@ namespace sys::cpu::stats
                   int(ret.data.frequency),
                   CLOCK_GetFreq(0));
    }

    void LogPrinter::printPowerConsumption()
    {}
} // namespace sys::cpu::stats

M module-sys/SystemManager/CpuPackPrinter.cpp => module-sys/SystemManager/CpuPackPrinter.cpp +29 -10
@@ 5,6 5,8 @@
#include "SystemManager/SysCpuUpdateResult.hpp"
#include <SystemManager/SystemManagerCommon.hpp>
#include "third-party/msgpack11/msgpack11/msgpack11.hpp"
#include "battery_charger/battery_charger.hpp"
#include "time/time_conversion.hpp"

namespace sys::cpu::stats
{


@@ 12,35 14,52 @@ namespace sys::cpu::stats
    using namespace msgpack11;
    enum class PackID
    {
        Proc,
        Usage,
        Usage   = 1,
        ProcEnd = 2,
        Proc    = 3,
        Power   = 4,
    };

    void PackPrinter::printSysUsage(struct task_prof_data *data, size_t size)
    {
        MsgPack procEnd = MsgPack::object({{"id", uint8_t(PackID::ProcEnd)}});
        vTaskSuspendAll();
        {
            for (size_t i = 0; i < size; ++i) {
                if (data[i].exec_time == 0 && data[i].switches == 0) {
                    continue;
                }
                MsgPack obj = MsgPack::object{{"id", uint32_t(PackID::Proc)},
                                              {"name", SystemManagerCommon::ServiceProcessor(i)},
                                              {"tcb", uint32_t(data[i].task_TCB_id)},
                                              {"t", data[i].exec_time}};
                LOG_PRINTF("%c%s\n", 2, obj.dump().c_str());
                MsgPack obj = MsgPack::object{{"name", SystemManagerCommon::ServiceProcessor(i)},
                                              {"tcb", uint16_t(data[i].task_TCB_id)},
                                              {"time", data[i].exec_time},
                                              {"id", uint8_t(PackID::Proc)}};

                LOG_PRINTF("\n%c%s\n", 2, obj.dump().c_str());
            }
            LOG_PRINTF("\n%c%s\n", 2, procEnd.dump().c_str());
        }
        xTaskResumeAll();
    }

    void PackPrinter::printCPUChange(const cpu::UpdateResult &ret)
    {
        MsgPack obj = MsgPack::object{{"id", uint32_t(PackID::Usage)},
        MsgPack obj = MsgPack::object{{"id", uint8_t(PackID::Usage)},
                                      {"freq", uint32_t(ret.frequencySet)},
                                      {"name", ret.data.name},
                                      {"reason", ret.data.reason},
                                      {"requested", uint32_t(ret.data.frequency)}};
        LOG_PRINTF("%c%s\n", 2, obj.dump().c_str());
                                      {"requested", uint32_t(ret.data.frequency)},
                                      {"avgA", int32_t(bsp::battery_charger::getAvgCurrent())},
                                      {"nowA", int32_t(bsp::battery_charger::getCurrentMeasurement())},
                                      {"ts", static_cast<uint64_t>(utils::time::getCurrentTimestamp().getTime())}};
        LOG_PRINTF("\n%c%s\n", 2, obj.dump().c_str());
    }

    void PackPrinter::printPowerConsumption()
    {
        MsgPack obj = MsgPack::object{{"id", uint8_t(PackID::Power)},
                                      {"avgA", int32_t(bsp::battery_charger::getAvgCurrent())},
                                      {"nowA", int32_t(bsp::battery_charger::getCurrentMeasurement())},
                                      {"ts", static_cast<uint64_t>(utils::time::getCurrentTimestamp().getTime())}};
        LOG_PRINTF("\n%c%s\n", 2, obj.dump().c_str());
    }
} // namespace sys::cpu::stats

M module-sys/SystemManager/CpuSentinel.cpp => module-sys/SystemManager/CpuSentinel.cpp +6 -55
@@ 3,6 3,7 @@

#include <SystemManager/CpuSentinel.hpp>
#include "system/messages/RequestCpuFrequencyMessage.hpp"
#include "system/messages/HoldCpuFrequency.hpp"
#include "system/Constants.hpp"
#include <Timers/TimerFactory.hpp>
#include <memory>


@@ 28,11 29,13 @@ namespace sys
    void CpuSentinel::HoldMinimumFrequency(bsp::CpuFrequencyMHz frequencyToHold)
    {
        if (currentFrequencyToHold != frequencyToHold) {
            auto msg = std::make_shared<sys::HoldCpuFrequencyMessage>(GetName(), frequencyToHold);
            auto msg =
                std::make_shared<sys::HoldCpuFrequencyMessage>(GetName(), frequencyToHold, xTaskGetCurrentTaskHandle());
            owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
            currentFrequencyToHold = frequencyToHold;
            currentReason          = std::string("up: ") + owner->getCurrentProcessing() + std::string(" req: ") +
                            std::to_string(int(frequencyToHold));
            ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100));
        }
    }



@@ 46,37 49,9 @@ namespace sys
        }
    }

    void CpuSentinel::HoldFrequencyPermanently(bsp::CpuFrequencyMHz frequencyToHold)
    {
        permanentFrequencyToHold.isActive        = true;
        permanentFrequencyToHold.frequencyToHold = frequencyToHold;
        auto msg = std::make_shared<sys::HoldCpuFrequencyPermanentlyMessage>(GetName(), frequencyToHold);
        owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
    }

    [[nodiscard]] auto CpuSentinel::GetFrequency() const noexcept -> bsp::CpuFrequencyMHz
    {
        if (permanentFrequencyToHold.isActive) {
            return permanentFrequencyToHold.frequencyToHold;
        }
        else {
            return currentFrequency;
        }
    }

    void CpuSentinel::ReleasePermanentFrequency()
    {
        if (permanentFrequencyToHold.isActive) {
            auto msg = std::make_shared<sys::ReleaseCpuPermanentFrequencyMessage>(GetName());
            owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
            permanentFrequencyToHold.isActive        = false;
            permanentFrequencyToHold.frequencyToHold = bsp::CpuFrequencyMHz::Level_0;
        }
    }

    bool CpuSentinel::isPermanentFrequencyActive()
    {
        return permanentFrequencyToHold.isActive;
    }

    void CpuSentinel::CpuFrequencyHasChanged(bsp::CpuFrequencyMHz newFrequency)


@@ 85,35 60,11 @@ namespace sys
        if (callback) {
            callback(newFrequency);
        }
        if (taskWaitingForFrequency != nullptr && newFrequency >= currentFrequencyToHold) {
            xTaskNotifyGive(taskWaitingForFrequency);
            taskWaitingForFrequency = nullptr;
        }
    }

    bool CpuSentinel::HoldMinimumFrequencyAndWait(bsp::CpuFrequencyMHz frequencyToHold,
                                                  TaskHandle_t taskToNotify,
                                                  uint32_t timeout)
    void CpuSentinel::ReadRegistrationData(bsp::CpuFrequencyMHz frequencyHz)
    {
        currentReason = std::string("h+w: ") + owner->getCurrentProcessing();
        HoldMinimumFrequency(frequencyToHold);

        if (currentFrequencyToHold < frequencyToHold) {
            taskWaitingForFrequency = taskToNotify;
            return ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(timeout)) == 0;
        }

        return true;
    }

    void CpuSentinel::ReadRegistrationData(bsp::CpuFrequencyMHz frequencyHz, bool permanentFrequency)
    {
        currentFrequency                  = frequencyHz;
        permanentFrequencyToHold.isActive = permanentFrequency;

        if (permanentFrequencyToHold.isActive) {
            permanentFrequencyToHold.frequencyToHold = currentFrequency;
        }
        currentFrequency = frequencyHz;
    }

    TimedCpuSentinel::TimedCpuSentinel(std::string name, sys::Service *service)

M module-sys/SystemManager/CpuStatistics.cpp => module-sys/SystemManager/CpuStatistics.cpp +9 -3
@@ 21,8 21,12 @@ namespace sys
#if PROF_ON
        data_size = prof_pool_get_data().size;
        data      = new task_prof_data[data_size];
        printer   = std::make_unique<cpu::stats::PackPrinter>();
#else
        // to change printer change assignment
        // printer = std::make_unique<cpu::stats::LogPrinter>();
        printer = std::make_unique<cpu::stats::NullPrinter>();
#endif
        printer = std::make_unique<cpu::stats::LogPrinter>();
    }

    CpuStatistics::~CpuStatistics()


@@ 47,12 51,13 @@ namespace sys

    void CpuStatistics::TrackChange(const cpu::UpdateResult &ret)
    {
        if (ret.changed) {
        if (ret.changed != sys::cpu::UpdateResult::Result::NoChange) {
            printer->printCPUChange(ret);
#if PROF_ON
            printer->printSysUsage(data, data_size);
#endif
        }
        printer->printPowerConsumption();
        StoreSysUsage();
    }



@@ 72,8 77,9 @@ namespace sys
        }
    }

    uint32_t CpuStatistics::GetPercentageCpuLoad() const noexcept
    uint32_t CpuStatistics::GetPercentageCpuLoad()
    {
        UpdatePercentageCpuLoad();
        return cpuLoad;
    }


M module-sys/SystemManager/PowerManager.cpp => module-sys/SystemManager/PowerManager.cpp +65 -165
@@ 1,11 1,16 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SystemManager/cpu/algorithm/FrequencyHold.hpp"
#include "SystemManager/cpu/algorithm/ImmediateUpscale.hpp"
#include "SystemManager/cpu/algorithm/FrequencyStepping.hpp"
#include "cpu/AlgorithmFactory.hpp"
#include "magic_enum.hpp"
#include <SystemManager/CpuStatistics.hpp>
#include <SystemManager/PowerManager.hpp>
#include <gsl/util>
#include <log/log.hpp>

#include <SystemManager/PowerManager.hpp>

namespace sys
{
    namespace


@@ 34,12 39,17 @@ namespace sys
        totalTicksCount += ticks;
    }

    PowerManager::PowerManager() : powerProfile{bsp::getPowerProfile()}
    PowerManager::PowerManager(CpuStatistics &stats) : powerProfile{bsp::getPowerProfile()}, cpuStatistics(stats)
    {
        driverSEMC      = drivers::DriverSEMC::Create(drivers::name::ExternalRAM);
        lowPowerControl = bsp::LowPowerMode::Create().value_or(nullptr);
        driverSEMC      = drivers::DriverSEMC::Create("ExternalRAM");
        cpuGovernor     = std::make_unique<CpuGovernor>();

        cpuAlgorithms = std::make_unique<cpu::AlgorithmFactory>();
        cpuAlgorithms->emplace(sys::cpu::AlgoID::ImmediateUpscale, std::make_unique<sys::cpu::ImmediateUpscale>());
        cpuAlgorithms->emplace(sys::cpu::AlgoID::FrequencyStepping,
                               std::make_unique<sys::cpu::FrequencyStepping>(powerProfile, *cpuGovernor));

        cpuFrequencyMonitor.push_back(CpuFrequencyMonitor(lowestLevelName));
        cpuFrequencyMonitor.push_back(CpuFrequencyMonitor(middleLevelName));
        cpuFrequencyMonitor.push_back(CpuFrequencyMonitor(highestLevelName));


@@ 77,202 87,92 @@ namespace sys
        }
    }

    [[nodiscard]] cpu::UpdateResult PowerManager::UpdateCpuFrequency(uint32_t cpuLoad)
    [[nodiscard]] cpu::UpdateResult PowerManager::UpdateCpuFrequency()
    {
        uint32_t cpuLoad = cpuStatistics.GetPercentageCpuLoad();
        cpu::UpdateResult result;
        cpu::AlgorithmData data{
            cpuLoad, lowPowerControl->GetCurrentFrequencyLevel(), cpuGovernor->GetMinimumFrequencyRequested()};

        const auto currentCpuFreq           = lowPowerControl->GetCurrentFrequencyLevel();
        const auto min                      = cpuGovernor->GetMinimumFrequencyRequested();
        const auto permanent                = cpuGovernor->GetPermanentFrequencyRequested();

        auto _ = gsl::finally([&result, this, &currentCpuFreq, min, permanent] {
        auto _ = gsl::finally([&result, this, data] {
            result.frequencySet = lowPowerControl->GetCurrentFrequencyLevel();
            result.changed      = result.frequencySet != currentCpuFreq;
            if (not permanent.isActive) {
                result.data = min;
            }
            else {
                result.data.reason = "perm";
            }
            result.changed      = result.frequencySet > data.curentFrequency ? sys::cpu::UpdateResult::Result::UpScaled
                                  : result.frequencySet < data.curentFrequency ? sys::cpu::UpdateResult::Result::Downscaled
                                                                               : sys::cpu::UpdateResult::Result::NoChange;
            result.data         = data.sentinel;
        });

        if (permanent.isActive) {
            auto frequencyToHold = std::max(permanent.frequencyToHold, powerProfile.minimalFrequency);

            if (currentCpuFreq < frequencyToHold) {
                IncreaseCpuFrequency(frequencyToHold);
            }
            else if (currentCpuFreq > frequencyToHold) {
                do {
                    DecreaseCpuFrequency();
                } while (lowPowerControl->GetCurrentFrequencyLevel() > frequencyToHold);
        auto algorithms = {
            sys::cpu::AlgoID::FrequencyHold, sys::cpu::AlgoID::ImmediateUpscale, sys::cpu::AlgoID::FrequencyStepping};

        for (auto id : algorithms) {
            auto algo = cpuAlgorithms->get(id);
            if (algo != nullptr) {
                if (auto frequencyToSet = algo->calculate(data); frequencyToSet != data.curentFrequency) {
                    result.id = id;
                    SetCpuFrequency(frequencyToSet);
                    for (auto again : algorithms) {
                        if (auto al = cpuAlgorithms->get(again); al != nullptr) {
                            al->reset();
                        }
                    }
                    return result;
                }
            }
            ResetFrequencyShiftCounter();
            return result;
        }

        if (cpuLoad > powerProfile.frequencyShiftUpperThreshold && currentCpuFreq < bsp::CpuFrequencyMHz::Level_6) {
            aboveThresholdCounter++;
            belowThresholdCounter = 0;
        }
        else if (cpuLoad < powerProfile.frequencyShiftLowerThreshold &&
                 currentCpuFreq > powerProfile.minimalFrequency) {
            belowThresholdCounter++;
            aboveThresholdCounter = 0;
        }
        else {
            ResetFrequencyShiftCounter();
        }

        if (!belowThresholdCounter) {
            isFrequencyLoweringInProgress = false;
        }

        if (min.frequency > currentCpuFreq) {
            ResetFrequencyShiftCounter();
            IncreaseCpuFrequency(min.frequency);
        }
        else if (aboveThresholdCounter >= powerProfile.maxAboveThresholdCount) {
            if (powerProfile.frequencyIncreaseIntermediateStep && currentCpuFreq < bsp::CpuFrequencyMHz::Level_4) {
                ResetFrequencyShiftCounter();
                IncreaseCpuFrequency(bsp::CpuFrequencyMHz::Level_4);
            }
            else {
                ResetFrequencyShiftCounter();
                IncreaseCpuFrequency(bsp::CpuFrequencyMHz::Level_6);
            }
        }
        else {
            if (belowThresholdCounter >= (isFrequencyLoweringInProgress ? powerProfile.maxBelowThresholdInRowCount
                                                                        : powerProfile.maxBelowThresholdCount) &&
                currentCpuFreq > min.frequency) {
                ResetFrequencyShiftCounter();
                DecreaseCpuFrequency();
            }
        }
        return result;
    }

    void PowerManager::IncreaseCpuFrequency(bsp::CpuFrequencyMHz newFrequency)
    void PowerManager::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) const
    {
        const auto freq = lowPowerControl->GetCurrentFrequencyLevel();

        if ((freq <= bsp::CpuFrequencyMHz::Level_1) && (newFrequency > bsp::CpuFrequencyMHz::Level_1)) {
            // connect internal the load resistor
            lowPowerControl->ConnectInternalLoadResistor();
            // turn off power save mode for DCDC inverter
            lowPowerControl->DisableDcdcPowerSaveMode();
            // Switch DCDC to full throttle during oscillator switch
            lowPowerControl->SetHighestCoreVoltage();
            // Enable regular 2P5 and 1P1 LDO and Turn off weak 2P5 and 1P1 LDO
            lowPowerControl->SwitchToRegularModeLDO();
            // switch oscillator source
            lowPowerControl->SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::External);
            // then switch external RAM clock source
            if (driverSEMC) {
                driverSEMC->SwitchToPLL2ClockSource();
            }
            // Add intermediate step in frequency
            if (newFrequency > bsp::CpuFrequencyMHz::Level_4)
                SetCpuFrequency(bsp::CpuFrequencyMHz::Level_4);
        }

        // and increase frequency
        if (freq < newFrequency) {
            SetCpuFrequency(newFrequency);
        if (cpuGovernor->RegisterNewSentinel(newSentinel)) {
            newSentinel->ReadRegistrationData(lowPowerControl->GetCurrentFrequencyLevel());
        }
    }

    void PowerManager::DecreaseCpuFrequency()
    void PowerManager::RemoveSentinel(std::string sentinelName) const
    {
        const auto freq = lowPowerControl->GetCurrentFrequencyLevel();
        auto level      = powerProfile.minimalFrequency;

        switch (freq) {
        case bsp::CpuFrequencyMHz::Level_6:
            level = bsp::CpuFrequencyMHz::Level_5;
            break;
        case bsp::CpuFrequencyMHz::Level_5:
            level = bsp::CpuFrequencyMHz::Level_4;
            break;
        case bsp::CpuFrequencyMHz::Level_4:
            level = bsp::CpuFrequencyMHz::Level_3;
            break;
        case bsp::CpuFrequencyMHz::Level_3:
            level = bsp::CpuFrequencyMHz::Level_2;
            break;
        case bsp::CpuFrequencyMHz::Level_2:
            level = powerProfile.minimalFrequency;
            break;
        case bsp::CpuFrequencyMHz::Level_1:
            [[fallthrough]];
        case bsp::CpuFrequencyMHz::Level_0:
            break;
        }

        // decrease frequency first
        if (level != freq) {
            SetCpuFrequency(level);
        }

        if (level <= bsp::CpuFrequencyMHz::Level_1) {
            // Enable weak 2P5 and 1P1 LDO and Turn off regular 2P5 and 1P1 LDO
            lowPowerControl->SwitchToLowPowerModeLDO();

            // then switch osc source
            lowPowerControl->SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::Internal);

            // and switch external RAM clock source
            if (driverSEMC) {
                driverSEMC->SwitchToPeripheralClockSource();
            }

            // turn on power save mode for DCDC inverter
            lowPowerControl->EnableDcdcPowerSaveMode();

            // disconnect internal the load resistor
            lowPowerControl->DisconnectInternalLoadResistor();
        }

        isFrequencyLoweringInProgress = true;
        cpuGovernor->RemoveSentinel(sentinelName);
    }

    void PowerManager::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) const
    void PowerManager::SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request)
    {
        if (cpuGovernor->RegisterNewSentinel(newSentinel)) {
            newSentinel->ReadRegistrationData(lowPowerControl->GetCurrentFrequencyLevel(),
                                              cpuGovernor->GetPermanentFrequencyRequested().isActive);
        }
        cpuGovernor->SetCpuFrequencyRequest(sentinelName, request);
        auto ret = UpdateCpuFrequency();
        cpuStatistics.TrackChange(ret);
    }

    void PowerManager::RemoveSentinel(std::string sentinelName) const
    void PowerManager::ResetCpuFrequencyRequest(const std::string &sentinelName)
    {
        cpuGovernor->RemoveSentinel(sentinelName);
        cpuGovernor->ResetCpuFrequencyRequest(sentinelName);
        auto ret = UpdateCpuFrequency();
        cpuStatistics.TrackChange(ret);
    }

    void PowerManager::SetCpuFrequencyRequest(std::string sentinelName,
                                              bsp::CpuFrequencyMHz request,
                                              bool permanentBlock)
    bool PowerManager::IsCpuPernamentFrequency()
    {
        cpuGovernor->SetCpuFrequencyRequest(std::move(sentinelName), request, permanentBlock);
        return cpuAlgorithms->get(sys::cpu::AlgoID::FrequencyHold) != nullptr;
    }

    void PowerManager::ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock)
    void PowerManager::SetPernamentFrequency(bsp::CpuFrequencyMHz freq)
    {
        cpuGovernor->ResetCpuFrequencyRequest(std::move(sentinelName), permanentBlock);
        cpuAlgorithms->emplace(sys::cpu::AlgoID::FrequencyHold,
                               std::make_unique<sys::cpu::FrequencyHold>(freq, powerProfile));
    }

    void PowerManager::SetCpuFrequency(bsp::CpuFrequencyMHz freq)
    void PowerManager::ResetPernamentFrequency()
    {
        UpdateCpuFrequencyMonitor(lowPowerControl->GetCurrentFrequencyLevel());
        lowPowerControl->SetCpuFrequency(freq);
        cpuGovernor->InformSentinelsAboutCpuFrequencyChange(freq);
        cpuAlgorithms->remove(sys::cpu::AlgoID::FrequencyHold);
    }

    void PowerManager::ResetFrequencyShiftCounter()
    void PowerManager::SetCpuFrequency(bsp::CpuFrequencyMHz freq)
    {
        aboveThresholdCounter = 0;
        belowThresholdCounter = 0;
        UpdateCpuFrequencyMonitor(lowPowerControl->GetCurrentFrequencyLevel());
        while (lowPowerControl->GetCurrentFrequencyLevel() != freq) {
            lowPowerControl->SetCpuFrequency(freq);
            cpuGovernor->InformSentinelsAboutCpuFrequencyChange(freq);
        }
    }

    [[nodiscard]] auto PowerManager::getExternalRamDevice() const noexcept -> std::shared_ptr<devices::Device>

M module-sys/SystemManager/SystemManagerCommon.cpp => module-sys/SystemManager/SystemManagerCommon.cpp +16 -18
@@ 24,6 24,7 @@
#include <system/messages/DeviceRegistrationMessage.hpp>
#include <system/messages/SentinelRegistrationMessage.hpp>
#include <system/messages/RequestCpuFrequencyMessage.hpp>
#include <system/messages/HoldCpuFrequency.hpp>
#include <time/ScopedTime.hpp>
#include "Timers/TimerFactory.hpp"
#include <service-appmgr/StartupType.hpp>


@@ 152,9 153,7 @@ namespace sys

        // in shutdown we need to wait till event manager tells us that it's ok to stfu
        while (state == State::Running) {
            if (auto msg = mailbox.pop(); msg) {
                msg->Execute(this);
            }
            processBus();
        }

        while (state == State::Shutdown) {


@@ 226,8 225,8 @@ namespace sys

    void SystemManagerCommon::StartSystem(InitFunction sysInit, InitFunction appSpaceInit, DeinitFunction sysDeinit)
    {
        powerManager  = std::make_unique<PowerManager>();
        cpuStatistics = std::make_unique<CpuStatistics>();
        powerManager  = std::make_unique<PowerManager>(*cpuStatistics);
        deviceManager = std::make_unique<DeviceManager>();

        systemInit   = std::move(sysInit);


@@ 241,7 240,7 @@ namespace sys
        freqTimer.start();

        powerManagerEfficiencyTimer = sys::TimerFactory::createPeriodicTimer(
            this, "logPowerManagerEfficiency", constants::powerManagerLogsTimerInterval, [](sys::Timer &) {
            this, "logPowerManagerEfficiency", constants::powerManagerLogsTimerInterval, [this](sys::Timer &) {
                powerManager->LogPowerManagerEfficiency();
            });
        powerManagerEfficiencyTimer.start();


@@ 618,7 617,9 @@ namespace sys
        connect(typeid(sys::HoldCpuFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::HoldCpuFrequencyMessage *>(message);
            powerManager->SetCpuFrequencyRequest(msg->getName(), msg->getRequest());

            if (msg->getHandle() != nullptr) {
                xTaskNotifyGive(msg->getHandle());
            }
            return sys::MessageNone{};
        });



@@ 629,17 630,19 @@ namespace sys
            return sys::MessageNone{};
        });

        connect(typeid(sys::IsCpuPernament), [this](sys::Message *message) -> sys::MessagePointer {
            return std::make_shared<sys::IsCpuPernamentResponse>(powerManager->IsCpuPernamentFrequency());
        });

        connect(typeid(sys::HoldCpuFrequencyPermanentlyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::HoldCpuFrequencyPermanentlyMessage *>(message);
            powerManager->SetCpuFrequencyRequest(msg->getName(), msg->getRequest(), true);

            return sys::MessageNone{};
            powerManager->SetPernamentFrequency(msg->request);
            return std::make_shared<sys::HoldCpuFrequencyPermanentlyResponse>();
        });

        connect(typeid(sys::ReleaseCpuPermanentFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::ReleaseCpuPermanentFrequencyMessage *>(message);
            powerManager->ResetCpuFrequencyRequest(msg->getName(), true);
            return sys::MessageNone{};
            powerManager->ResetPernamentFrequency();
            return std::make_shared<sys::HoldCpuFrequencyPermanentlyResponse>();
        });

        connect(typeid(app::manager::CheckIfStartAllowedMessage), [this](sys::Message *) -> sys::MessagePointer {


@@ 766,8 769,7 @@ namespace sys
            freqTimer.restart(constants::timerPeriodInterval);
        }

        cpuStatistics->UpdatePercentageCpuLoad();
        auto ret = powerManager->UpdateCpuFrequency(cpuStatistics->GetPercentageCpuLoad());
        auto ret = powerManager->UpdateCpuFrequency();
        cpuStatistics->TrackChange(ret);
    }



@@ 785,8 787,4 @@ namespace sys
    std::vector<std::shared_ptr<app::ApplicationCommon>> SystemManagerCommon::applicationsList;
    cpp_freertos::MutexStandard SystemManagerCommon::serviceDestroyMutex;
    cpp_freertos::MutexStandard SystemManagerCommon::appDestroyMutex;
    std::unique_ptr<PowerManager> SystemManagerCommon::powerManager;
    std::unique_ptr<CpuStatistics> SystemManagerCommon::cpuStatistics;
    std::unique_ptr<DeviceManager> SystemManagerCommon::deviceManager;

} // namespace sys

A module-sys/SystemManager/cpu/AlgorithmFactory.cpp => module-sys/SystemManager/cpu/AlgorithmFactory.cpp +33 -0
@@ 0,0 1,33 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AlgorithmFactory.hpp"
#include "SystemManager/cpu/algorithm/FrequencyHold.hpp"
#include <memory>

namespace sys::cpu
{

    AlgorithmFactory::PutResult AlgorithmFactory::emplace(sys::cpu::AlgoID id, std::unique_ptr<Algorithm> &&algorithm)
    {
        if (algorithms.find(id) != std::end(algorithms)) {
            algorithms[id] = std::move(algorithm);
            return PutResult::Replaced;
        }
        algorithms.emplace(id, std::move(algorithm));
        return PutResult::Added;
    }

    Algorithm *AlgorithmFactory::get(sys::cpu::AlgoID id)
    {
        if (auto el = algorithms.find(id); el != std::end(algorithms)) {
            return el->second.get();
        }
        return nullptr;
    }

    void AlgorithmFactory::remove(sys::cpu::AlgoID id)
    {
        algorithms.erase(id);
    }
} // namespace sys::cpu

A module-sys/SystemManager/cpu/AlgorithmFactory.hpp => module-sys/SystemManager/cpu/AlgorithmFactory.hpp +27 -0
@@ 0,0 1,27 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "algorithm/Algorithm.hpp"
#include <map>
#include <memory>

namespace sys::cpu
{

    class AlgorithmFactory
    {
        std::map<sys::cpu::AlgoID, std::unique_ptr<Algorithm>> algorithms;

      public:
        Algorithm *get(sys::cpu::AlgoID);
        enum class PutResult
        {
            Added,
            Replaced,
        };
        PutResult emplace(sys::cpu::AlgoID id, std::unique_ptr<Algorithm> &&algorithm);
        void remove(sys::cpu::AlgoID id);
    };
}; // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/Algorithm.cpp => module-sys/SystemManager/cpu/algorithm/Algorithm.cpp +17 -0
@@ 0,0 1,17 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Algorithm.hpp"

namespace sys::cpu
{
    bsp::CpuFrequencyMHz Algorithm::calculate(const AlgorithmData &data)
    {
        return calculateImplementation(data);
    }

    void Algorithm::reset()
    {
        resetImplementation();
    }
} // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/Algorithm.hpp => module-sys/SystemManager/cpu/algorithm/Algorithm.hpp +32 -0
@@ 0,0 1,32 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "AlgorithmID.hpp"
#include "SystemManager/SentinelView.hpp"
#include "common.hpp"

namespace sys::cpu
{
    struct AlgorithmData
    {
        unsigned int CPUload                 = 0;
        bsp::CpuFrequencyMHz curentFrequency = bsp::CpuFrequencyMHz::Level_6;
        sentinel::View sentinel;
    };

    class Algorithm
    {
      private:
        [[nodiscard]] virtual bsp::CpuFrequencyMHz calculateImplementation(const AlgorithmData &) = 0;
        virtual void resetImplementation()
        {}

      public:
        [[nodiscard]] virtual bsp::CpuFrequencyMHz calculate(const AlgorithmData &) final;
        virtual void reset() final;

        virtual ~Algorithm() = default;
    };
} // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/AlgorithmID.hpp => module-sys/SystemManager/cpu/algorithm/AlgorithmID.hpp +15 -0
@@ 0,0 1,15 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace sys::cpu
{
    enum class AlgoID
    {
        None,
        FrequencyHold,
        ImmediateUpscale,
        FrequencyStepping,
    };
}

A module-sys/SystemManager/cpu/algorithm/FrequencyHold.cpp => module-sys/SystemManager/cpu/algorithm/FrequencyHold.cpp +17 -0
@@ 0,0 1,17 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "FrequencyHold.hpp"
#include <algorithm>

namespace sys::cpu
{
    FrequencyHold::FrequencyHold(bsp::CpuFrequencyMHz toHold, const bsp::PowerProfile &profile)
        : toHold(toHold), profile(profile)
    {}

    bsp::CpuFrequencyMHz FrequencyHold::calculateImplementation(const AlgorithmData &data)
    {
        return std::max(toHold, profile.minimalFrequency);
    }
}; // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/FrequencyHold.hpp => module-sys/SystemManager/cpu/algorithm/FrequencyHold.hpp +20 -0
@@ 0,0 1,20 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Algorithm.hpp"
#include "lpm/PowerProfile.hpp"

namespace sys::cpu
{
    class FrequencyHold : public Algorithm
    {
        bsp::CpuFrequencyMHz toHold;
        const bsp::PowerProfile &profile;
        [[nodiscard]] bsp::CpuFrequencyMHz calculateImplementation(const AlgorithmData &data) override;

      public:
        explicit FrequencyHold(bsp::CpuFrequencyMHz toHold, const bsp::PowerProfile &profile);
    };
} // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp => module-sys/SystemManager/cpu/algorithm/FrequencyStepping.cpp +85 -0
@@ 0,0 1,85 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "FrequencyStepping.hpp"
#include "SystemManager/CpuGovernor.hpp"

namespace sys::cpu
{

    FrequencyStepping::FrequencyStepping(const bsp::PowerProfile &powerProfile, CpuGovernor &cpuGovernor)
        : powerProfile(powerProfile), cpuGovernor(cpuGovernor)
    {}

    bsp::CpuFrequencyMHz stepDown(bsp::CpuFrequencyMHz freq, const bsp::PowerProfile &profile)
    {
        switch (freq) {
        case bsp::CpuFrequencyMHz::Level_6:
            return bsp::CpuFrequencyMHz::Level_5;
        case bsp::CpuFrequencyMHz::Level_5:
            return bsp::CpuFrequencyMHz::Level_4;
        case bsp::CpuFrequencyMHz::Level_4:
            return bsp::CpuFrequencyMHz::Level_3;
        case bsp::CpuFrequencyMHz::Level_3:
            return bsp::CpuFrequencyMHz::Level_2;
        case bsp::CpuFrequencyMHz::Level_2:
            [[fallthrough]];
        case bsp::CpuFrequencyMHz::Level_1:
            [[fallthrough]];
        case bsp::CpuFrequencyMHz::Level_0:
            return profile.minimalFrequency;
        }
        return freq;
    }

    bsp::CpuFrequencyMHz FrequencyStepping::calculateImplementation(const AlgorithmData &data)
    {
        const auto load           = data.CPUload;
        const auto startFrequency = data.curentFrequency;
        const auto min            = cpuGovernor.GetMinimumFrequencyRequested();

        if (load > powerProfile.frequencyShiftUpperThreshold && startFrequency < bsp::CpuFrequencyMHz::Level_6) {
            aboveThresholdCounter++;
            belowThresholdCounter = 0;
        }
        else if (load < powerProfile.frequencyShiftLowerThreshold && startFrequency > powerProfile.minimalFrequency) {
            belowThresholdCounter++;
            aboveThresholdCounter = 0;
        }
        else {
            reset();
        }

        if (belowThresholdCounter == 0u) {
            isFrequencyLoweringInProgress = false;
        }

        if (min.frequency > startFrequency) {}
        else if (aboveThresholdCounter >= powerProfile.maxAboveThresholdCount) {
            if (startFrequency < bsp::CpuFrequencyMHz::Level_4) {
                reset();
                return bsp::CpuFrequencyMHz::Level_4;
            }
            else {
                reset();
                return bsp::CpuFrequencyMHz::Level_6;
            }
        }
        else {
            if (belowThresholdCounter >= (isFrequencyLoweringInProgress ? powerProfile.maxBelowThresholdInRowCount
                                                                        : powerProfile.maxBelowThresholdCount) &&
                startFrequency > min.frequency) {
                reset();
                return stepDown(startFrequency, powerProfile);
            }
        }

        return startFrequency;
    }

    void FrequencyStepping::resetImplementation()
    {
        aboveThresholdCounter = 0;
        belowThresholdCounter = 0;
    }
} // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/FrequencyStepping.hpp => module-sys/SystemManager/cpu/algorithm/FrequencyStepping.hpp +29 -0
@@ 0,0 1,29 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Algorithm.hpp"
#include "lpm/PowerProfile.hpp"

namespace sys
{
    class CpuGovernor;
}

namespace sys::cpu
{
    class FrequencyStepping : public Algorithm
    {
        const bsp::PowerProfile &powerProfile;
        CpuGovernor &cpuGovernor;
        unsigned int aboveThresholdCounter = 0;
        unsigned int belowThresholdCounter = 0;
        bool isFrequencyLoweringInProgress = true;

      public:
        FrequencyStepping(const bsp::PowerProfile &powerProfile, CpuGovernor &cpuGovernor);
        [[nodiscard]] bsp::CpuFrequencyMHz calculateImplementation(const AlgorithmData &data) override;
        void resetImplementation() override;
    };
} // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/ImmediateUpscale.cpp => module-sys/SystemManager/cpu/algorithm/ImmediateUpscale.cpp +14 -0
@@ 0,0 1,14 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ImmediateUpscale.hpp"

namespace sys::cpu
{
    bsp::CpuFrequencyMHz ImmediateUpscale::calculateImplementation(const AlgorithmData &data)
    {
        const auto now = data.sentinel.frequency;
        const auto was = data.curentFrequency;
        return std::max(now, was);
    }
} // namespace sys::cpu

A module-sys/SystemManager/cpu/algorithm/ImmediateUpscale.hpp => module-sys/SystemManager/cpu/algorithm/ImmediateUpscale.hpp +18 -0
@@ 0,0 1,18 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Algorithm.hpp"
#include "lpm/PowerProfile.hpp"
#include <functional>
#include <utility>

namespace sys::cpu
{
    class ImmediateUpscale : public Algorithm
    {
      public:
        bsp::CpuFrequencyMHz calculateImplementation(const AlgorithmData &data) override;
    };
} // namespace sys::cpu

M module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp => module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp +4 -24
@@ 6,26 6,11 @@
#include <memory>
#include <vector>
#include "SystemManager/CpuSentinel.hpp"
#include "SentinelView.hpp"

namespace sys
{

    namespace sentinel
    {
        struct Data
        {
            UBaseType_t ownerTCBNumber = 0;
            /// name of sentinel thread responsible for curent minimum load
            std::string name;
            /// curent minimum frequency set in sentinel
            bsp::CpuFrequencyMHz frequency = bsp::CpuFrequencyMHz::Level_0;
            /// please do not use this task handle to perform actions, it's just for reference sake
            TaskHandle_t task;
            /// textual information on what actually happens
            std::string reason;
        };
    }; // namespace sentinel

    using SentinelPointer = std::weak_ptr<CpuSentinel>;

    class GovernorSentinel


@@ 55,22 40,17 @@ namespace sys
        [[nodiscard]] auto GetNumberOfRegisteredSentinels() const noexcept -> uint32_t;
        void PrintAllSentinels() const noexcept;

        void SetCpuFrequencyRequest(std::string sentinelName,
                                    bsp::CpuFrequencyMHz request,
                                    bool permanentBlock = false);
        void ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock = false);
        void SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request);
        void ResetCpuFrequencyRequest(const std::string &sentinelName);

        [[nodiscard]] auto GetMinimumFrequencyRequested() const noexcept -> sentinel::Data;
        [[nodiscard]] auto GetMinimumFrequencyRequested() const noexcept -> sentinel::View;
        void InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) const noexcept;

        [[nodiscard]] auto GetPermanentFrequencyRequested() const noexcept -> PermanentFrequencyToHold;

      private:
        static void PrintName(const GovernorSentinelPointer &element);

        /// this could be set - set is sorted :)
        GovernorSentinelsVector sentinels;
        PermanentFrequencyToHold permanentFrequencyToHold{false, bsp::CpuFrequencyMHz::Level_0};
    };

} // namespace sys

M module-sys/SystemManager/include/SystemManager/CpuPrinter.hpp => module-sys/SystemManager/include/SystemManager/CpuPrinter.hpp +5 -0
@@ 17,6 17,7 @@ namespace sys::cpu
          public:
            virtual void printSysUsage(struct task_prof_data *data, size_t size) = 0;
            virtual void printCPUChange(const cpu::UpdateResult &ret)            = 0;
            virtual void printPowerConsumption()                                 = 0;
        };

        class NullPrinter : public Printer


@@ 25,6 26,8 @@ namespace sys::cpu
            {}
            void printCPUChange(const cpu::UpdateResult &ret)
            {}
            void printPowerConsumption()
            {}
        };

        class LogPrinter : public Printer


@@ 32,6 35,7 @@ namespace sys::cpu
          public:
            void printSysUsage(struct task_prof_data *data, size_t size) override;
            void printCPUChange(const cpu::UpdateResult &ret) override;
            void printPowerConsumption() override;
        };

        class PackPrinter : public Printer


@@ 39,6 43,7 @@ namespace sys::cpu
          public:
            void printSysUsage(struct task_prof_data *data, size_t size) override;
            void printCPUChange(const cpu::UpdateResult &ret) override;
            void printPowerConsumption() override;
        };
    }; // namespace stats
};     // namespace sys::cpu

M module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp => module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp +2 -16
@@ 13,12 13,6 @@

namespace sys
{
    struct PermanentFrequencyToHold
    {
        bool isActive;
        bsp::CpuFrequencyMHz frequencyToHold;
    };

    /// Each sentinel manages the requests, i.e. when it is needed it sends messages to CpuGovernor with the required
    /// minimum CPU frequency to perform the task (e.g. screen redraw). Furthermore, every sentinel is informed
    /// immediately after changing the frequency. This allows it to invoke a callback to the service to update their


@@ 30,29 24,22 @@ namespace sys
        explicit CpuSentinel(std::string name,
                             sys::Service *service,
                             std::function<void(bsp::CpuFrequencyMHz)> callback = nullptr);
        ~CpuSentinel() = default;

        [[nodiscard]] auto GetName() const noexcept -> std::string;
        void HoldMinimumFrequency(bsp::CpuFrequencyMHz frequencyToHold);
        bool HoldMinimumFrequencyAndWait(bsp::CpuFrequencyMHz frequencyToHold,
                                         TaskHandle_t taskToNotify,
                                         uint32_t timeout);
        void ReleaseMinimumFrequency();

        void HoldFrequencyPermanently(bsp::CpuFrequencyMHz frequencyToHold);
        [[nodiscard]] auto GetFrequency() const noexcept -> bsp::CpuFrequencyMHz;
        void ReleasePermanentFrequency();
        [[nodiscard]] bool isPermanentFrequencyActive();

        void CpuFrequencyHasChanged(bsp::CpuFrequencyMHz newFrequency);
        void ReadRegistrationData(bsp::CpuFrequencyMHz frequencyHz, bool permanentFrequency);

        void ReadRegistrationData(bsp::CpuFrequencyMHz frequencyHz);
        TaskHandle_t getTask();
        std::string getReason();

      protected:
        const std::string name;
        bsp::CpuFrequencyMHz currentFrequencyToHold{bsp::CpuFrequencyMHz::Level_0};
        PermanentFrequencyToHold permanentFrequencyToHold{false, bsp::CpuFrequencyMHz::Level_0};
        std::atomic<bsp::CpuFrequencyMHz> currentFrequency{bsp::CpuFrequencyMHz::Level_0};
        sys::Service *owner{nullptr};



@@ 61,7 48,6 @@ namespace sys
        /// critical section or mutex support necessary
        std::function<void(bsp::CpuFrequencyMHz)> callback;

        TaskHandle_t taskWaitingForFrequency = nullptr;
        std::string currentReason;
    };


M module-sys/SystemManager/include/SystemManager/CpuStatistics.hpp => module-sys/SystemManager/include/SystemManager/CpuStatistics.hpp +2 -2
@@ 24,11 24,11 @@ namespace sys
        /// stores system usage, should be called before any CPU frequency change
        /// this way we know what services were in use and for how long before it happened
        void StoreSysUsage();
        [[nodiscard]] uint32_t GetPercentageCpuLoad() const noexcept;
        void UpdatePercentageCpuLoad();
        [[nodiscard]] uint32_t GetPercentageCpuLoad();
        void TrackChange(const cpu::UpdateResult &ret);

      private:
        void UpdatePercentageCpuLoad();
        /// used to print stored data in CpuStatistics on change
        std::unique_ptr<cpu::stats::Printer> printer;
        uint32_t ComputeIncrease(uint32_t currentCount, uint32_t lastCount) const;

M module-sys/SystemManager/include/SystemManager/PowerManager.hpp => module-sys/SystemManager/include/SystemManager/PowerManager.hpp +19 -19
@@ 13,8 13,15 @@
#include <bsp/lpm/PowerProfile.hpp>
#include <vector>

namespace sys::cpu
{
    class AlgorithmFactory;
}

namespace sys
{
    class CpuStatistics;

    class CpuFrequencyMonitor
    {
      public:


@@ 31,9 38,8 @@ namespace sys

    class PowerManager
    {

      public:
        PowerManager();
        explicit PowerManager(CpuStatistics &stats);
        ~PowerManager();

        int32_t PowerOff();


@@ 47,44 53,38 @@ namespace sys
        /// limit (frequencyShiftUpperThreshold), CPU frequency is increased; if for the last 'maxBelowThresholdCount'
        /// periods the current CPU usage was below the lower limit (frequencyShiftLowerThreshold), CPU frequency is
        /// reduced frequency
        /// @param current cpu load
        [[nodiscard]] cpu::UpdateResult UpdateCpuFrequency(uint32_t cpuLoad);
        [[nodiscard]] cpu::UpdateResult UpdateCpuFrequency();

        [[nodiscard]] auto getExternalRamDevice() const noexcept -> std::shared_ptr<devices::Device>;

        void RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) const;
        void RemoveSentinel(std::string sentinelName) const;
        void SetCpuFrequencyRequest(std::string sentinelName,
                                    bsp::CpuFrequencyMHz request,
                                    bool permanentBlock = false);
        void ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock = false);
        void SetCpuFrequencyRequest(const std::string &sentinelName, bsp::CpuFrequencyMHz request);
        void ResetCpuFrequencyRequest(const std::string &sentinelName);
        bool IsCpuPernamentFrequency();
        void SetPernamentFrequency(bsp::CpuFrequencyMHz freq);
        void ResetPernamentFrequency();

        void LogPowerManagerEfficiency();
        void SetBootSuccess();

      private:
        /// called when the CPU frequency needs to be increased
        void IncreaseCpuFrequency(bsp::CpuFrequencyMHz newFrequency);

        /// called when the CPU frequency needs to be reduced
        /// @note the frequency is always reduced by one step
        void DecreaseCpuFrequency();

        void ResetFrequencyShiftCounter();
        void SetCpuFrequency(bsp::CpuFrequencyMHz freq);

        void UpdateCpuFrequencyMonitor(bsp::CpuFrequencyMHz currentFreq);

        uint32_t belowThresholdCounter{0};
        uint32_t aboveThresholdCounter{0};
        TickType_t lastCpuFrequencyChangeTimestamp{0};
        bool isFrequencyLoweringInProgress{false};

        std::vector<CpuFrequencyMonitor> cpuFrequencyMonitor;

        std::unique_ptr<bsp::LowPowerMode> lowPowerControl;
        std::shared_ptr<drivers::DriverSEMC> driverSEMC;
        std::unique_ptr<bsp::LowPowerMode> lowPowerControl;
        std::unique_ptr<CpuGovernor> cpuGovernor;
        const bsp::PowerProfile powerProfile;

        std::unique_ptr<sys::cpu::AlgorithmFactory> cpuAlgorithms;
        CpuStatistics &cpuStatistics;
    };

} // namespace sys

A module-sys/SystemManager/include/SystemManager/SentinelView.hpp => module-sys/SystemManager/include/SystemManager/SentinelView.hpp +27 -0
@@ 0,0 1,27 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "common.hpp"
#include "FreeRTOS.h"
#include "portmacro.h"
#include <string>

namespace sys
{

    namespace sentinel
    {
        struct View
        {
            UBaseType_t ownerTCBNumber = 0;
            /// name of sentinel thread responsible for curent minimum load
            std::string name;
            /// curent minimum frequency set in sentinel
            bsp::CpuFrequencyMHz frequency = bsp::CpuFrequencyMHz::Level_0;
            /// textual information on what actually happens
            std::string reason;
        };
    }; // namespace sentinel
} // namespace sys

M module-sys/SystemManager/include/SystemManager/SysCpuUpdateResult.hpp => module-sys/SystemManager/include/SystemManager/SysCpuUpdateResult.hpp +12 -3
@@ 3,13 3,22 @@

#pragma once

#include "SystemManager/CpuGovernor.hpp"
#include "SystemManager/cpu/algorithm/AlgorithmID.hpp"
#include "SystemManager/SentinelView.hpp"

namespace sys::cpu
{
    struct UpdateResult
    {
        bool changed                      = false;
        enum class Result
        {
            UpScaled,   /// frequency risen
            Downscaled, /// frequency downscaled
            NoChange    /// nothing to do
        };
        Result changed                    = Result::NoChange;
        bsp::CpuFrequencyMHz frequencySet = bsp::CpuFrequencyMHz::Level_0;
        sentinel::Data data{};
        sentinel::View data{};
        AlgoID id = AlgoID::None;
    };
}; // namespace sys::cpu

M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp => module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp +3 -3
@@ 212,9 212,9 @@ namespace sys
        static std::vector<std::shared_ptr<app::ApplicationCommon>> applicationsList;
        static cpp_freertos::MutexStandard serviceDestroyMutex;
        static cpp_freertos::MutexStandard appDestroyMutex;
        static std::unique_ptr<PowerManager> powerManager;
        static std::unique_ptr<CpuStatistics> cpuStatistics;
        static std::unique_ptr<DeviceManager> deviceManager;
        std::unique_ptr<CpuStatistics> cpuStatistics;
        std::unique_ptr<PowerManager> powerManager;
        std::unique_ptr<DeviceManager> deviceManager;
    };
} // namespace sys


M module-sys/common/include/system/SystemReturnCodes.hpp => module-sys/common/include/system/SystemReturnCodes.hpp +4 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 11,9 11,9 @@ namespace sys
        Failure,
        Timeout,
        ServiceDoesntExist,
        // This is used in application's template in base class messages handler. The meaning is that
        // message that was processed by base class implementation of the DataReceivedHandler was not processed
        // and it should be handled by the class next in hierarchy.
        /// This is used in application's template in base class messages handler. The meaning is that
        /// message that was processed by base class implementation of the DataReceivedHandler was not processed
        /// and it should be handled by the class next in hierarchy.
        Unresolved
    };
}

A module-sys/common/include/system/messages/HoldCpuFrequency.hpp => module-sys/common/include/system/messages/HoldCpuFrequency.hpp +55 -0
@@ 0,0 1,55 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "FreeRTOS.h"
#include "task.h"
#include <Service/Message.hpp>
#include <bsp/common.hpp>

namespace sys
{
    class HoldCpuFrequencyMessage : public sys::DataMessage
    {
      public:
        HoldCpuFrequencyMessage(std::string sentinelName, bsp::CpuFrequencyMHz request, TaskHandle_t handle)
            : sys::DataMessage(MessageType::SystemManagerCpuFrequency), sentinelName(std::move(sentinelName)),
              frequencyRequested(request), handle(handle)
        {}

        [[nodiscard]] auto getRequest() const noexcept
        {
            return frequencyRequested;
        };

        [[nodiscard]] auto getName() const
        {
            return sentinelName;
        };

        [[nodiscard]] TaskHandle_t getHandle() const
        {
            return handle;
        }

      private:
        std::string sentinelName;
        bsp::CpuFrequencyMHz frequencyRequested = bsp::CpuFrequencyMHz::Level_0;
        TaskHandle_t handle;
    };

    class ReleaseCpuFrequencyMessage : public sys::DataMessage
    {
      public:
        explicit ReleaseCpuFrequencyMessage(std::string sentinelName)
            : sys::DataMessage(MessageType::SystemManagerCpuFrequency), sentinelName(std::move(sentinelName))
        {}

        [[nodiscard]] auto getName() const
        {
            return sentinelName;
        };

      private:
        std::string sentinelName;
    };
} // namespace sys

M module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp => module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp +13 -37
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 9,58 9,34 @@
namespace sys
{

    class HoldCpuFrequencyMessage : public sys::DataMessage
    struct IsCpuPernament : public sys::DataMessage
    {
      public:
        HoldCpuFrequencyMessage(std::string sentinelName, bsp::CpuFrequencyMHz request)
            : sys::DataMessage(MessageType::SystemManagerCpuFrequency), sentinelName(std::move(sentinelName)),
              frequencyRequested(request)
        explicit IsCpuPernament()
        {}

        [[nodiscard]] auto getRequest() const noexcept
        {
            return frequencyRequested;
        };

        [[nodiscard]] auto getName() const
        {
            return sentinelName;
        };

      private:
        std::string sentinelName;
        bsp::CpuFrequencyMHz frequencyRequested = bsp::CpuFrequencyMHz::Level_0;
    };

    class ReleaseCpuFrequencyMessage : public sys::DataMessage
    struct IsCpuPernamentResponse : public sys::ResponseMessage
    {
      public:
        explicit ReleaseCpuFrequencyMessage(std::string sentinelName)
            : sys::DataMessage(MessageType::SystemManagerCpuFrequency), sentinelName(std::move(sentinelName))
        explicit IsCpuPernamentResponse(bool pernament) : pernament(pernament)
        {}

        [[nodiscard]] auto getName() const
        {
            return sentinelName;
        };

      private:
        std::string sentinelName;
        const bool pernament = false;
    };

    class HoldCpuFrequencyPermanentlyMessage : public HoldCpuFrequencyMessage
    struct HoldCpuFrequencyPermanentlyMessage : public sys::DataMessage
    {
      public:
        HoldCpuFrequencyPermanentlyMessage(std::string sentinelName, bsp::CpuFrequencyMHz request)
            : HoldCpuFrequencyMessage(sentinelName, request)
        explicit HoldCpuFrequencyPermanentlyMessage(bsp::CpuFrequencyMHz request) : request(request)
        {}
        const bsp::CpuFrequencyMHz request;
    };

    class ReleaseCpuPermanentFrequencyMessage : public ReleaseCpuFrequencyMessage
    class HoldCpuFrequencyPermanentlyResponse : public sys::ResponseMessage
    {
      public:
        ReleaseCpuPermanentFrequencyMessage(std::string sentinelName) : ReleaseCpuFrequencyMessage(sentinelName)
        {}
    };

    class ReleaseCpuPermanentFrequencyMessage : public sys::DataMessage
    {};

} // namespace sys

M products/PurePhone/BinaryAssetsVersions.cmake => products/PurePhone/BinaryAssetsVersions.cmake +2 -2
@@ 1,9 1,9 @@
# This file sets versions of downloaded binaries for release packaging purposes

if( NOT DEFINED ECOBOOT_BIN_VERSION)
    set(ECOBOOT_BIN_VERSION 1.1.0 CACHE STRING "bootloader binary version to download from bootloader release page")
    set(ECOBOOT_BIN_VERSION 1.1.2 CACHE STRING "bootloader binary version to download from bootloader release page")
endif()

if (NOT DEFINED UPDATER_BIN_VERSION)
    set(UPDATER_BIN_VERSION 1.3.0 CACHE STRING "updater binary version to download from updater release page")
    set(UPDATER_BIN_VERSION 1.4.0 CACHE STRING "updater binary version to download from updater release page")
endif()

M products/PurePhone/apps/Application.cpp => products/PurePhone/apps/Application.cpp +12 -0
@@ 7,6 7,8 @@
#include <popups/HomeModesWindow.hpp>
#include <popups/TetheringPhoneModePopup.hpp>
#include <popups/TetheringConfirmationPopup.hpp>
#include <popups/BluetoothAuthenticatePopup.hpp>
#include <popups/BluetoothInfoPopup.hpp>
#include <popups/PowerOffWindow.hpp>
#include <popups/presenter/PowerOffPresenter.hpp>
#include <popups/presenter/WallpaperPresenter.hpp>


@@ 60,6 62,16 @@ namespace app
                    return std::make_unique<gui::HomeModesWindow>(app, window::phone_modes_window);
                });
                break;
            case ID::BluetoothAuthenticate:
            case ID::BluetoothInfo:
                windowsFactory.attach(
                    window::bluetooth_authenticate, [](ApplicationCommon *app, const std::string &name) {
                        return std::make_unique<gui::BluetoothAuthenticatePopup>(app, window::bluetooth_authenticate);
                    });
                windowsFactory.attach(window::bluetooth_info, [](ApplicationCommon *app, const std::string &name) {
                    return std::make_unique<gui::BluetoothInfoPopup>(app, window::bluetooth_info);
                });
                break;
            case ID::Brightness:
                break;
            case ID::PhoneLock:

M products/PurePhone/services/appmgr/ApplicationManager.cpp => products/PurePhone/services/appmgr/ApplicationManager.cpp +24 -0
@@ 18,6 18,7 @@
#include <service-appmgr/messages/GetAllNotificationsRequest.hpp>
#include <service-appmgr/messages/GetWallpaperOptionRequest.hpp>
#include <service-bluetooth/messages/BluetoothModeChanged.hpp>
#include <service-bluetooth/messages/Authenticate.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>


@@ 352,6 353,29 @@ namespace app::manager
            handleBluetoothModeChanged(data->getBluetoothMode());
            return sys::msgHandled();
        });
        connect(typeid(message::bluetooth::RequestAuthenticate), [&](sys::Message *msg) {
            auto m = dynamic_cast<::message::bluetooth::RequestAuthenticate *>(msg);

            auto data =
                std::make_unique<gui::BluetoothAuthenticateRequestParams>(m->getDevice(), m->getAuthenticateType());
            data->setDisposition(gui::popup::Disposition{gui::popup::Disposition::Priority::High,
                                                         gui::popup::Disposition::WindowType::Popup,
                                                         gui::popup::ID::BluetoothAuthenticate});
            actionsRegistry.enqueue(ActionEntry{actions::ShowPopup, std::move(data)});

            return sys::MessageNone{};
        });
        connect(typeid(BluetoothPairResultMessage), [&](sys::Message *msg) {
            auto m = dynamic_cast<BluetoothPairResultMessage *>(msg);

            auto data = std::make_unique<gui::BluetoothInfoParams>(m->getDevice(), m->isSucceed(), m->getErrorCode());
            data->setDisposition(gui::popup::Disposition{gui::popup::Disposition::Priority::High,
                                                         gui::popup::Disposition::WindowType::Popup,
                                                         gui::popup::ID::BluetoothInfo});
            actionsRegistry.enqueue(ActionEntry{actions::ShowPopup, std::move(data)});

            return sys::MessageNone{};
        });

        alarms::AlarmServiceAPI::requestRegisterSnoozedAlarmsCountChangeCallback(this);
        connect(typeid(alarms::SnoozedAlarmsCountChangeMessage), [&](sys::Message *request) -> sys::MessagePointer {

M products/PurePhone/services/evtmgr/EventManager.cpp => products/PurePhone/services/evtmgr/EventManager.cpp +2 -2
@@ 107,14 107,14 @@ void EventManager::initProductEvents()
void EventManager::toggleTorchOnOff()
{
    auto state    = bsp::torch::getState();
    auto newState = (state.second == bsp::torch::State::off) ? bsp::torch::State::on : bsp::torch::State::off;
    auto newState = (state == bsp::torch::State::off) ? bsp::torch::State::on : bsp::torch::State::off;
    bsp::torch::turn(newState, bsp::torch::ColourTemperature::coldest);
}

void EventManager::toggleTorchColor()
{
    auto state = bsp::torch::getState();
    if (state.second == bsp::torch::State::on) {
    if (state == bsp::torch::State::on) {
        auto color    = bsp::torch::getColorTemp();
        auto newColor = (color == bsp::torch::ColourTemperature::coldest) ? bsp::torch::ColourTemperature::warmest
                                                                          : bsp::torch::ColourTemperature::coldest;

M test/get_os_log.py => test/get_os_log.py +1 -1
@@ 1,5 1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

import sys

M test/harness => test/harness +1 -1
@@ 1,1 1,1 @@
Subproject commit fcb4287c5061b612d4ff68b0f86c49db5ded2998
Subproject commit 549ac3a09dab95223baa32084ff20afb340be9d5

M test/pytest/conftest.py => test/pytest/conftest.py +3 -3
@@ 1,4 1,4 @@
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

import time


@@ 121,8 121,8 @@ def harnesses():
    '''
    Automatically init at least two Pure phones
    '''
    found_pures = serial.find_Pures()
    harnesses = [Harness(pure) for pure in found_pures]
    connected_devices = serial.find_Devices()
    harnesses = [Harness(device) for device in connected_devices]
    if not len(harnesses) >= 2:
        pytest.skip("At least two phones are needed for this test")
    assert len(harnesses) >= 2