~aleteoryx/muditaos

4490d0da7fc455fce1dca85be645c1bd7bedf617 — Hubert Chrzaniuk 5 years ago e9fae2e
[EGD-5714] Add phone mode handling for Audio Service

Added separate set of settings for all phone modes along
with basic support for phone mode change.
M module-audio/Audio/AudioCommon.cpp => module-audio/Audio/AudioCommon.cpp +14 -5
@@ 2,10 2,12 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AudioCommon.hpp"
#include <sstream>
#include <Utils.hpp>
#include "Profiles/Profile.hpp"

#include <Utils.hpp>

#include <sstream>

namespace audio
{
    audio::RetCode GetDeviceError(AudioDevice::RetCode retCode)


@@ 35,18 37,25 @@ namespace audio
        return utils::enumToString(setting);
    }

    const std::string dbPath(const Setting &setting, const PlaybackType &playbackType, const Profile::Type &profileType)
    const std::string dbPath(const sys::phone_modes::PhoneMode &phoneMode,
                             const Setting &setting,
                             const PlaybackType &playbackType,
                             const Profile::Type &profileType)
    {
        if (profileType == Profile::Type::Idle && playbackType == PlaybackType::None) {
            return std::string();
        }

        constexpr auto separator = '/';
        std::string path(audioDbPrefix);

        path.append(utils::enumToString(phoneMode));
        path.append(1, separator);
        if (auto s = str(profileType); !s.empty()) {
            path.append(s + "/");
            path.append(s.append(1, separator));
        }
        if (auto s = str(playbackType); !s.empty()) {
            path.append(s + "/");
            path.append(s.append(1, separator));
        }
        if (auto s = str(setting); !s.empty()) {
            path.append(s);

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +10 -8
@@ 7,6 7,7 @@
#include "Profiles/Profile.hpp"

#include <Service/Message.hpp>
#include <PhoneModes/Common.hpp>
#include <Utils.hpp>

#include <map>


@@ 60,7 61,8 @@ namespace audio

    [[nodiscard]] const std::string str(const Setting &setting) noexcept;

    [[nodiscard]] const std::string dbPath(const Setting &setting,
    [[nodiscard]] const std::string dbPath(const sys::phone_modes::PhoneMode &phoneMode,
                                           const Setting &setting,
                                           const PlaybackType &playbackType,
                                           const Profile::Type &profileType);



@@ 285,15 287,15 @@ namespace AudioServiceMessage
    class DbRequest : public sys::Message
    {
      public:
        explicit DbRequest(std::string path) : path(std::move(path))
        explicit DbRequest(const audio::Setting &setting,
                           const audio::PlaybackType &playback,
                           const audio::Profile::Type &profile)
            : setting(setting), profile(profile), playback(playback)
        {}
        const std::string &GetPath() const
        {
            return path;
        }

      private:
        const std::string path;
        const audio::Setting setting;
        const audio::Profile::Type profile;
        const audio::PlaybackType playback;
    };

    using Callback = std::function<std::optional<std::string>(const sys::Message *msg)>;

M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +2 -2
@@ 77,8 77,8 @@ namespace audio
    }
    void Operation::AddProfile(const Profile::Type &profile, const PlaybackType &playback, bool isAvailable)
    {
        const auto reqVol  = AudioServiceMessage::DbRequest(audio::dbPath(Setting::Volume, playback, profile));
        const auto reqGain = AudioServiceMessage::DbRequest(audio::dbPath(Setting::Gain, playback, profile));
        const auto reqVol  = AudioServiceMessage::DbRequest(Setting::Volume, playback, profile);
        const auto reqGain = AudioServiceMessage::DbRequest(Setting::Gain, playback, profile);

        std::optional<audio::Volume> volume;
        std::optional<audio::Gain> gain;

M module-audio/Audio/test/unittest_audio.cpp => module-audio/Audio/test/unittest_audio.cpp +19 -10
@@ 40,31 40,40 @@ TEST_CASE("Audio settings string creation")
{
    SECTION("Create volume string for playback loudspeaker, multimedia")
    {
        const auto str = audio::dbPath(
            audio::Setting::Volume, audio::PlaybackType::Multimedia, audio::Profile::Type::PlaybackLoudspeaker);
        const auto str = audio::dbPath(sys::phone_modes::PhoneMode::Connected,
                                       audio::Setting::Volume,
                                       audio::PlaybackType::Multimedia,
                                       audio::Profile::Type::PlaybackLoudspeaker);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/PlaybackLoudspeaker/Multimedia/Volume");
        REQUIRE(str == "audio/Connected/PlaybackLoudspeaker/Multimedia/Volume");
    }

    SECTION("Create volume string for routing speakerphone")
    {
        const auto str =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingLoudspeaker);
        const auto str = audio::dbPath(sys::phone_modes::PhoneMode::Offline,
                                       audio::Setting::Volume,
                                       audio::PlaybackType::None,
                                       audio::Profile::Type::RoutingLoudspeaker);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/RoutingLoudspeaker/Volume");
        REQUIRE(str == "audio/Offline/RoutingLoudspeaker/Volume");
    }

    SECTION("Create gain string for recording built-in microphone")
    {
        const auto str =
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingBuiltInMic);
        const auto str = audio::dbPath(sys::phone_modes::PhoneMode::DoNotDisturb,
                                       audio::Setting::Gain,
                                       audio::PlaybackType::None,
                                       audio::Profile::Type::RecordingBuiltInMic);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/RecordingBuiltInMic/Gain");
        REQUIRE(str == "audio/DoNotDisturb/RecordingBuiltInMic/Gain");
    }

    SECTION("Create empty volume string when Idle")
    {
        const auto str = audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::Idle);
        const auto str = audio::dbPath(sys::phone_modes::PhoneMode::Offline,
                                       audio::Setting::Volume,
                                       audio::PlaybackType::None,
                                       audio::Profile::Type::Idle);
        REQUIRE(str.empty());
    }
}

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +361 -59
@@ 16,13 16,22 @@

using namespace audio;

inline constexpr auto audioServiceStackSize = 1024 * 13;

ServiceAudio::ServiceAudio()
    : sys::Service(service::name::audio, "", 4096 * 2, sys::ServicePriority::Idle),
    : sys::Service(service::name::audio, "", audioServiceStackSize, sys::ServicePriority::Idle),
      audioMux([this](auto... params) { return this->AudioServicesCallback(params...); }),
      settingsProvider(std::make_unique<settings::Settings>(this))
      settingsProvider(std::make_unique<settings::Settings>(this)),
      phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
{
    LOG_INFO("[ServiceAudio] Initializing");
    bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
    bus.channels.push_back(sys::BusChannel::PhoneModeChanges);

    phoneModeObserver->connect(this);
    phoneModeObserver->subscribe([&](sys::phone_modes::PhoneMode phoneMode, sys::phone_modes::Tethering tetheringMode) {
        HandlePhoneModeChange(phoneMode, tetheringMode);
    });
}

ServiceAudio::~ServiceAudio()


@@ 32,77 41,346 @@ ServiceAudio::~ServiceAudio()

sys::ReturnCodes ServiceAudio::InitHandler()
{
    static const std::string defaultVolumeHigh = "10";
    static const std::string defaultVolumeLow  = "2";
    static const std::string defaultTrue       = "1";
    static const std::string defaultFalse      = "0";
    static const std::string defaultVolumeHigh  = "10";
    static const std::string defaultVolumeLow   = "2";
    static const std::string defaultVolumeMuted = "0";
    static const std::string defaultTrue        = "1";
    static const std::string defaultFalse       = "0";

    using namespace sys::phone_modes;

    settingsCache = {

        // PLAYBACK
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(
             PhoneMode::Connected, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::DoNotDisturb,
                Setting::Volume,
                PlaybackType::Notifications,
                Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackHeadphones),
         defaultVolumeMuted},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeMuted},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeMuted},

        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackHeadphones),
         defaultVolumeMuted},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeMuted},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeMuted},

        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(
             PhoneMode::Connected, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackHeadphones),
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackHeadphones),
         defaultVolumeMuted},
        {dbPath(PhoneMode::DoNotDisturb,
                Setting::Volume,
                PlaybackType::CallRingtone,
                Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeMuted},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeMuted},

        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackHeadphones),
         defaultVolumeMuted},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeMuted},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeMuted},

        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackBluetoothA2DP),
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackLoudspeaker),
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::Connected,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(PhoneMode::Connected,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::DoNotDisturb,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackHeadphones),
         defaultVolumeMuted},
        {dbPath(PhoneMode::DoNotDisturb,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeMuted},
        {dbPath(PhoneMode::DoNotDisturb,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackLoudspeaker),
         defaultVolumeMuted},

        {dbPath(
             PhoneMode::Offline, Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackHeadphones),
         defaultVolumeMuted},
        {dbPath(PhoneMode::Offline,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeMuted},
        {dbPath(PhoneMode::Offline,
                Setting::Volume,
                PlaybackType::TextMessageRingtone,
                Profile::Type::PlaybackLoudspeaker),
         defaultVolumeMuted},

        // ROUTING
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "3"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker), "10"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "0"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), "20"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "3"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker), "10"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "0"},

        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), "20"},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "3"},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker), "10"},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "0"},

        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), "20"},
        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "3"},
        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker), "10"},
        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "0"},

        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP),
         defaultVolumeHigh},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker),
         defaultVolumeHigh},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones),
         defaultVolumeHigh},
        {dbPath(PhoneMode::Connected, Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker),
         defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker), defaultVolumeHigh},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP),
         defaultVolumeHigh},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker),
         defaultVolumeHigh},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones),
         defaultVolumeHigh},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker),
         defaultVolumeHigh},

        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP),
         defaultVolumeHigh},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker),
         defaultVolumeHigh},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones),
         defaultVolumeHigh},
        {dbPath(PhoneMode::Offline, Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker),
         defaultVolumeHigh},

        // RECORDING
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RecordingBuiltInMic), "200"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RecordingHeadphones), "100"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP), "100"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RecordingBuiltInMic), "200"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RecordingHeadphones), "100"},
        {dbPath(PhoneMode::Connected, Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP), "100"},

        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RecordingBuiltInMic), "200"},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RecordingHeadphones), "100"},
        {dbPath(PhoneMode::DoNotDisturb, Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP),
         "100"},

        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RecordingBuiltInMic), "200"},
        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RecordingHeadphones), "100"},
        {dbPath(PhoneMode::Offline, Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP), "100"},

        // MISC
        {dbPath(Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle), defaultFalse},
        {dbPath(Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle), defaultFalse},
        {dbPath(Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle), defaultFalse},
        {dbPath(Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},

        {dbPath(Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Connected, Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},

        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(
             PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle),
         defaultTrue},

        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},

        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::Connected, Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},

        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle),
         defaultTrue},
        {dbPath(PhoneMode::DoNotDisturb, Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},

        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle), defaultTrue},
        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle),
         defaultFalse},
        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle), defaultTrue},
        {dbPath(PhoneMode::Offline, Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle), defaultTrue},
    };

    for (const auto &setting : settingsCache) {


@@ 126,10 404,12 @@ std::optional<std::string> ServiceAudio::AudioServicesCallback(const sys::Messag
        bus.sendMulticast(std::move(newMsg), sys::BusChannel::ServiceAudioNotifications);
    }
    else if (const auto *dbReq = dynamic_cast<const AudioServiceMessage::DbRequest *>(msg); dbReq) {
        LOG_DEBUG("ServiceAudio::DBbCallback(%s)", dbReq->GetPath().c_str());
        auto settings_it = settingsCache.find(dbReq->GetPath());
        std::string path =
            dbPath(phoneModeObserver->getCurrentPhoneMode(), dbReq->setting, dbReq->playback, dbReq->profile);
        LOG_DEBUG("ServiceAudio::DBbCallback(%s)", path.c_str());
        auto settings_it = settingsCache.find(path);
        if (settingsCache.end() == settings_it) {
            LOG_DEBUG("%s does not exist in cache", dbReq->GetPath().c_str());
            LOG_DEBUG("%s does not exist in cache", path.c_str());
            return std::nullopt;
        }
        return settings_it->second;


@@ 429,6 709,26 @@ auto ServiceAudio::HandleKeyPressed(const int step) -> std::unique_ptr<AudioKeyP
    return std::make_unique<AudioKeyPressedResponse>(audio::RetCode::Success, newVolume, muted, context);
}

void ServiceAudio::HandlePhoneModeChange(sys::phone_modes::PhoneMode phoneMode,
                                         sys::phone_modes::Tethering tetheringMode)
{
    LOG_INFO("Phone mode changed to %s", utils::enumToString(phoneMode).c_str());
    for (auto &input : audioMux.GetAllInputs()) {
        if (input.audio->GetCurrentState() != Audio::State::Idle) {
            std::string path = dbPath(phoneMode,
                                      Setting::Volume,
                                      input.audio->GetCurrentOperationPlaybackType(),
                                      input.audio->GetPriorityPlaybackProfile());
            if (const auto it = settingsCache.find(path); settingsCache.end() != it) {
                input.audio->SetOutputVolume(utils::getNumericValue<audio::Volume>(it->second));
            }
            else {
                LOG_ERROR("Requested uninitialized DB value %s", path.c_str());
            }
        }
    }
}

bool ServiceAudio::IsBusy()
{
    for (auto &input : audioMux.GetAllInputs()) {


@@ 543,7 843,7 @@ std::string ServiceAudio::getSetting(const Setting &setting,
        targetProfile = Profile::Type::Idle;
    }

    std::string path = dbPath(setting, targetPlayback, targetProfile);
    std::string path = dbPath(phoneModeObserver->getCurrentPhoneMode(), setting, targetPlayback, targetProfile);
    if (const auto set_it = settingsCache.find(path); settingsCache.end() != set_it) {
        return set_it->second;
    }


@@ 603,8 903,10 @@ void ServiceAudio::setSetting(const Setting &setting,
    }

    if (retCode == RetCode::Success) {
        settingsProvider->setValue(dbPath(setting, updatedPlayback, updatedProfile), valueToSet);
        settingsCache[dbPath(setting, updatedPlayback, updatedProfile)] = valueToSet;
        settingsProvider->setValue(
            dbPath(phoneModeObserver->getCurrentPhoneMode(), setting, updatedPlayback, updatedProfile), valueToSet);
        settingsCache[dbPath(phoneModeObserver->getCurrentPhoneMode(), setting, updatedPlayback, updatedProfile)] =
            valueToSet;
    }
}


M module-services/service-audio/service-audio/ServiceAudio.hpp => module-services/service-audio/service-audio/ServiceAudio.hpp +5 -0
@@ 7,8 7,10 @@

#include <Audio/Audio.hpp>
#include <Audio/AudioMux.hpp>

#include <MessageType.hpp>
#include <Service/Service.hpp>
#include <PhoneModes/Observer.hpp>
#include <Utils.hpp>

#include <service-db/DBServiceAPI.hpp>


@@ 55,6 57,8 @@ class ServiceAudio : public sys::Service
    std::unique_ptr<settings::Settings> settingsProvider;
    std::map<std::string, std::string> settingsCache;

    std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;

    auto IsVibrationMotorOn()
    {
        return vibrationMotorStatus == audio::AudioMux::VibrationStatus::On;


@@ 77,6 81,7 @@ class ServiceAudio : public sys::Service
    auto HandleGetFileTags(const std::string &fileName) -> std::unique_ptr<AudioResponseMessage>;
    void HandleNotification(const AudioNotificationMessage::Type &type, const audio::Token &token);
    auto HandleKeyPressed(const int step) -> std::unique_ptr<AudioKeyPressedResponse>;
    void HandlePhoneModeChange(sys::phone_modes::PhoneMode phoneMode, sys::phone_modes::Tethering tetheringMode);
    void VibrationUpdate(const audio::PlaybackType &type               = audio::PlaybackType::None,
                         std::optional<audio::AudioMux::Input *> input = std::nullopt);
    auto GetVibrationType(const audio::PlaybackType &type) -> VibrationType;

M module-sys/PhoneModes/Observer.cpp => module-sys/PhoneModes/Observer.cpp +5 -0
@@ 28,6 28,11 @@ namespace sys::phone_modes
        return phoneMode == mode;
    }

    PhoneMode Observer::getCurrentPhoneMode() const noexcept
    {
        return phoneMode;
    }

    bool Observer::isTetheringOn() const noexcept
    {
        return tetheringMode == Tethering::On;

M module-sys/PhoneModes/Observer.hpp => module-sys/PhoneModes/Observer.hpp +1 -0
@@ 28,6 28,7 @@ namespace sys::phone_modes
                       OnErrorCallback &&onError       = {}) noexcept;

        bool isInMode(PhoneMode mode) const noexcept;
        PhoneMode getCurrentPhoneMode() const noexcept;
        bool isTetheringOn() const noexcept;

      private: