~aleteoryx/muditaos

d8fc8f9f90a46ff1f0ec9ff0ca278db6dab8987a — Kuba 4 years ago 7769558
[EGD-7909] Fix Retry mode change on fail

Service cellular will retry phone mode change on
failed attempt.
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +10 -2
@@ 290,8 290,11 @@ sys::ReturnCodes ServiceCellular::SwitchPowerModeHandler(const sys::ServicePower
void ServiceCellular::registerMessageHandlers()
{
    phoneModeObserver->connect(this);
    phoneModeObserver->subscribe(
        [this](sys::phone_modes::PhoneMode mode) { connectionManager->onPhoneModeChange(mode); });
    phoneModeObserver->subscribe([this](sys::phone_modes::PhoneMode mode) {
        if (priv->simCard->isSimCardSelected()) {
            connectionManager->onPhoneModeChange(mode);
        }
    });
    phoneModeObserver->subscribe([&](sys::phone_modes::Tethering tethering) {
        if (tethering == sys::phone_modes::Tethering::On) {
            priv->tetheringHandler->enable();


@@ 574,6 577,11 @@ void ServiceCellular::registerMessageHandlers()
        return handleCellularSetConnectionFrequencyMessage(request);
    });

    connect(typeid(RetryPhoneModeChangeRequest), [&](sys::Message *request) -> sys::MessagePointer {
        connectionManager->onPhoneModeChange(phoneModeObserver->getCurrentPhoneMode());
        return sys::MessageNone{};
    });

    handle_CellularGetChannelMessage();
}


M module-services/service-cellular/connection-manager/ConnectionManager.cpp => module-services/service-cellular/connection-manager/ConnectionManager.cpp +36 -4
@@ 61,12 61,23 @@ auto ConnectionManager::isMessagesOnlyMode() -> bool

auto ConnectionManager::handleModeChangeToCommonOffline() -> bool
{
    if (cellular->isConnectedToNetwork()) {
    auto isConnected = cellular->isConnectedToNetwork();

    if (not isConnected.has_value()) {
        retryOnFail();
        return false;
    }

    if (isConnected.value()) {
        cellular->hangUpOngoingCall();
        cellular->disconnectFromNetwork();
        if (!cellular->disconnectFromNetwork()) {
            retryOnFail();
            return false;
        }
        cellular->clearNetworkIndicator();
    }

    failRetries           = 0;
    minutesOfflineElapsed = static_cast<std::chrono::minutes>(0);
    minutesOnlineElapsed = static_cast<std::chrono::minutes>(0);



@@ 101,9 112,20 @@ auto ConnectionManager::handleModeChangeToConnected() -> bool
        cellular->stopConnectionTimer();
        onlinePeriod = false;
    }
    if (!cellular->isConnectedToNetwork()) {
        cellular->connectToNetwork();

    auto isConnected = cellular->isConnectedToNetwork();
    if (not isConnected.has_value()) {
        retryOnFail();
        return false;
    }

    if (not isConnected.value()) {
        if (!cellular->connectToNetwork()) {
            retryOnFail();
            return false;
        }
    }
    failRetries = 0;
    return true;
}



@@ 111,3 133,13 @@ auto ConnectionManager::forceDismissCalls() -> bool
{
    return forceDismissCallsFlag;
}
void ConnectionManager::retryOnFail()
{
    if (failRetries < maxFailRetries) {
        cellular->retryPhoneModeChange();
        failRetries++;
        return;
    }
    LOG_FATAL("Not able to handle phone mode change!!");
    failRetries = 0;
}

M module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp => module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp +6 -2
@@ 33,7 33,7 @@ auto ConnectionManagerCellularCommands::connectToNetwork() -> bool
    return false;
}

auto ConnectionManagerCellularCommands::isConnectedToNetwork() -> bool
auto ConnectionManagerCellularCommands::isConnectedToNetwork() -> std::optional<bool>
{

    using at::cfun::Functionality;


@@ 48,7 48,7 @@ auto ConnectionManagerCellularCommands::isConnectedToNetwork() -> bool
            }
        }
    }
    return false;
    return std::nullopt;
}

auto ConnectionManagerCellularCommands::clearNetworkIndicator() -> bool


@@ 106,3 106,7 @@ void ConnectionManagerCellularCommands::holdMinimumCpuFrequency()
    }
    return;
}
void ConnectionManagerCellularCommands::retryPhoneModeChange()
{
    cellular.bus.sendUnicast(std::make_shared<cellular::RetryPhoneModeChangeRequest>(), cellular.serviceName);
}

M module-services/service-cellular/service-cellular/CellularMessage.hpp => module-services/service-cellular/service-cellular/CellularMessage.hpp +5 -0
@@ 976,4 976,9 @@ namespace cellular
        at::SimInsertedStatus insertedStatus;
    };

    class RetryPhoneModeChangeRequest : public sys::DataMessage
    {
      public:
        RetryPhoneModeChangeRequest() : sys::DataMessage(MessageType::MessageTypeUninitialized){};
    };
} // namespace cellular

M module-services/service-cellular/service-cellular/connection-manager/ConnectionManager.hpp => module-services/service-cellular/service-cellular/connection-manager/ConnectionManager.hpp +6 -1
@@ 10,7 10,7 @@

// connection timer period is 1 minute, connect to network for 5 minutes
constexpr std::chrono::minutes connectedPeriod{5};

constexpr auto maxFailRetries = 5;
/**
 * @brief Intended for GSM network connection management depending on the selected phone mode.
 * Switching modes takes place at Phone Modes Observer event.


@@ 63,6 63,7 @@ class ConnectionManager
    std::chrono::minutes minutesOnlineElapsed{0};
    std::shared_ptr<ConnectionManagerCellularCommandsInterface> cellular;
    bool onlinePeriod = false;
    int failRetries   = 0;

    /// Flag determining if we should always dismiss incoming calls - even when
    /// we are in offline mode (messages only) and we connect to network to poll


@@ 94,4 95,8 @@ class ConnectionManager
     * @return true on success, false on fail
     */
    auto handleModeChangeToConnected() -> bool;
    /**
     * Request retry if phone mode changing fails
     */
    void retryOnFail();
};

M module-services/service-cellular/service-cellular/connection-manager/ConnectionManagerCellularCommands.hpp => module-services/service-cellular/service-cellular/connection-manager/ConnectionManagerCellularCommands.hpp +2 -1
@@ 14,13 14,14 @@ class ConnectionManagerCellularCommands : public ConnectionManagerCellularComman
    {}
    auto disconnectFromNetwork() -> bool final;
    auto connectToNetwork() -> bool final;
    auto isConnectedToNetwork() -> bool final;
    auto isConnectedToNetwork() -> std::optional<bool> final;
    auto clearNetworkIndicator() -> bool final;
    auto hangUpOngoingCall() -> bool final;
    auto isConnectionTimerActive() -> bool final;
    void startConnectionTimer() final;
    void stopConnectionTimer() final;
    void holdMinimumCpuFrequency() final;
    void retryPhoneModeChange() final;

  private:
    ServiceCellular &cellular;

M module-services/service-cellular/service-cellular/connection-manager/ConnectionManagerCellularCommandsInterface.hpp => module-services/service-cellular/service-cellular/connection-manager/ConnectionManagerCellularCommandsInterface.hpp +6 -1
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <optional>

class ConnectionManagerCellularCommandsInterface
{


@@ 25,7 26,7 @@ class ConnectionManagerCellularCommandsInterface
     * * Checks current state of modem radio module
     * @return true when modem radio module is enabled, false when modem radio module is disabled
     */
    virtual auto isConnectedToNetwork() -> bool = 0;
    virtual auto isConnectedToNetwork() -> std::optional<bool> = 0;
    /**
     * * It's disabling modem radio module, so it can't connect to the GSM network
     * @return true on success, false on fail


@@ 53,4 54,8 @@ class ConnectionManagerCellularCommandsInterface
     * @brief Holds minimum cpu frequency
     */
    virtual void holdMinimumCpuFrequency() = 0;
    /**
     * Request retry if phone mode changing fails
     */
    virtual void retryPhoneModeChange() = 0;
};

M module-services/service-cellular/src/SimCard.hpp => module-services/service-cellular/src/SimCard.hpp +8 -0
@@ 166,6 166,14 @@ namespace cellular::service
         */
        void handleSimCardSelected();
        /**
         * Get Sim selected state
         * @return true when Sim is selected, fail when not
         */
        bool isSimCardSelected()
        {
            return isSimSelected;
        }
        /**
         * Notification events
         */
        std::function<void()> onSimReady;

M module-services/service-cellular/tests/unittest_connection-manager.cpp => module-services/service-cellular/tests/unittest_connection-manager.cpp +4 -1
@@ 7,6 7,8 @@
#include <service-cellular/connection-manager/ConnectionManager.hpp>
#include <service-cellular/connection-manager/ConnectionManagerCellularCommandsInterface.hpp>

#include <optional>

using namespace testing;

class MockCellular : public ConnectionManagerCellularCommandsInterface


@@ 14,13 16,14 @@ class MockCellular : public ConnectionManagerCellularCommandsInterface
  public:
    MOCK_METHOD(bool, disconnectFromNetwork, (), (override));
    MOCK_METHOD(bool, connectToNetwork, (), (override));
    MOCK_METHOD(bool, isConnectedToNetwork, (), (override));
    MOCK_METHOD(std::optional<bool>, isConnectedToNetwork, (), (override));
    MOCK_METHOD(bool, clearNetworkIndicator, (), (override));
    MOCK_METHOD(bool, hangUpOngoingCall, (), (override));
    MOCK_METHOD(bool, isConnectionTimerActive, (), (override));
    MOCK_METHOD(void, startConnectionTimer, (), (override));
    MOCK_METHOD(void, stopConnectionTimer, (), (override));
    MOCK_METHOD(void, holdMinimumCpuFrequency, (), (override));
    MOCK_METHOD(void, retryPhoneModeChange, (), (override));
};

TEST(ConnectionManager, onPhoneModeChange)