~aleteoryx/muditaos

f585c33b7afacce8fa10c33c44bab37e935b68d4 — Lefucjusz 1 year, 6 months ago b468e90
[BH-2002] Fix crash when connected with broken USB cable

Fixes of the issues that would cause device
crash when connected with broken USB cable:
* fixed memory leaks in VCOM init and deinit
functions;
* guarded accessing desktopWorker object in
message handlers, as messages are asynchronous
and might arrive after worker has already been
destroyed. Not the cleanest solution, but
does the trick
M harmony_changelog.md => harmony_changelog.md +3 -2
@@ 12,8 12,9 @@

### Changed / Improved
* Changed the refresh rate of the progress bar screen
* Extended range of supported chargers.
* Changed order of options in Settings menu.
* Extended range of supported chargers
* Changed order of options in Settings menu
* Improved device stability with low quality USB cables

## [2.7.0 2024-05-20]


M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +25 -22
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-desktop/ServiceDesktop.hpp>


@@ 27,11 27,9 @@ ServiceDesktop::ServiceDesktop(const std::filesystem::path &mtpRootPath)
    bus.channels.push_back(sys::BusChannel::USBNotifications);
}

ServiceDesktop::~ServiceDesktop()
{
}
ServiceDesktop::~ServiceDesktop() = default;

sys::ReturnCodes ServiceDesktop::InitHandler()
auto ServiceDesktop::InitHandler() -> sys::ReturnCodes
{
    settings = std::make_unique<settings::Settings>();
    settings->init(service::ServiceProxy(shared_from_this()));


@@ 57,18 55,19 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
    return sys::ReturnCodes::Success;
}

sys::ReturnCodes ServiceDesktop::DeinitHandler()
auto ServiceDesktop::DeinitHandler() -> sys::ReturnCodes
{
    LOG_INFO("Deinitialized");
    return usbWorkerDeinit();
}

sys::ReturnCodes ServiceDesktop::SwitchPowerModeHandler(const sys::ServicePowerMode /*mode*/)
auto ServiceDesktop::SwitchPowerModeHandler([[maybe_unused]] const sys::ServicePowerMode mode) -> sys::ReturnCodes
{
    return sys::ReturnCodes::Success;
}

sys::MessagePointer ServiceDesktop::DataReceivedHandler(sys::DataMessage * /*msg*/, sys::ResponseMessage *resp)
auto ServiceDesktop::DataReceivedHandler([[maybe_unused]] sys::DataMessage *msg, sys::ResponseMessage *resp)
    -> sys::MessagePointer
{
    auto response = std::make_shared<sys::ResponseMessage>();
    if (resp == nullptr) {


@@ 92,7 91,7 @@ sys::MessagePointer ServiceDesktop::DataReceivedHandler(sys::DataMessage * /*msg
    return response;
}

void ServiceDesktop::prepareSyncData()
auto ServiceDesktop::prepareSyncData() -> void
{
    syncStatus.state   = Sync::OperationState::Stopped;
    syncStatus.tempDir = purefs::dir::getTemporaryPath() / "sync";


@@ 102,7 101,7 @@ auto ServiceDesktop::requestLogsFlush() -> void
{
    int response = 0;
    auto ret     = bus.sendUnicastSync(
        std::make_shared<sevm::FlushLogsRequest>(), service::name::evt_manager, DefaultLogFlushTimeoutInMs);
        std::make_shared<sevm::FlushLogsRequest>(), service::name::evt_manager, defaultLogFlushTimeoutMs);

    if (ret.first == sys::ReturnCodes::Success) {
        auto responseMsg = std::dynamic_pointer_cast<sevm::FlushLogsResponse>(ret.second);


@@ 145,7 144,7 @@ auto ServiceDesktop::getNotificationEntries() const -> std::vector<Outbox::Notif
    return outboxNotifications.getNotificationEntries();
}

void ServiceDesktop::removeNotificationEntries(const std::vector<std::uint32_t> &uidsOfNotificationsToBeRemoved)
auto ServiceDesktop::removeNotificationEntries(const std::vector<std::uint32_t> &uidsOfNotificationsToBeRemoved) -> void
{
    outboxNotifications.removeNotificationEntries(uidsOfNotificationsToBeRemoved);
}


@@ 217,12 216,12 @@ auto ServiceDesktop::usbWorkerDeinit() -> sys::ReturnCodes
    return sys::ReturnCodes::Success;
}

void ServiceDesktop::restartConnectionActiveTimer()
auto ServiceDesktop::restartConnectionActiveTimer() -> void
{
    connectionActiveTimer.restart(sdesktop::connectionActiveTimerDelayMs);
}

void ServiceDesktop::checkChargingCondition()
auto ServiceDesktop::checkChargingCondition() -> void
{
    if (Store::Battery::get().state == Store::Battery::State::Discharging) {
        usbWorkerDeinit();


@@ 243,7 242,7 @@ auto ServiceDesktop::handle(db::NotificationMessage *msg) -> std::shared_ptr<sys
    return sys::MessageNone{};
}

auto ServiceDesktop::handle(locks::UnlockedPhone * /*msg*/) -> std::shared_ptr<sys::Message>
auto ServiceDesktop::handle([[maybe_unused]] locks::UnlockedPhone *msg) -> std::shared_ptr<sys::Message>
{
    LOG_INFO("Phone unlocked.");
    usbSecurityModel->setPhoneUnlocked();


@@ 252,13 251,15 @@ auto ServiceDesktop::handle(locks::UnlockedPhone * /*msg*/) -> std::shared_ptr<s
        bus.sendUnicast(std::make_shared<sys::TetheringStateRequest>(sys::phone_modes::Tethering::On),
                        service::name::system_manager);
        isPlugEventUnhandled = false;
        desktopWorker->notify(WorkerDesktop::Signal::unlockMTP);
        if (desktopWorker != nullptr) {
            desktopWorker->notify(WorkerDesktop::Signal::unlockMTP);
        }
    }

    return sys::MessageNone{};
}

auto ServiceDesktop::handle(locks::LockedPhone * /*msg*/) -> std::shared_ptr<sys::Message>
auto ServiceDesktop::handle([[maybe_unused]] locks::LockedPhone *msg) -> std::shared_ptr<sys::Message>
{
    LOG_INFO("Phone locked.");
    usbSecurityModel->setPhoneLocked();


@@ 300,7 301,7 @@ auto ServiceDesktop::handle(sdesktop::developerMode::DeveloperModeRequest *msg) 
    return sys::MessageNone{};
}

auto ServiceDesktop::handle(sdesktop::SyncMessage * /*msg*/) -> std::shared_ptr<sys::Message>
auto ServiceDesktop::handle([[maybe_unused]] sdesktop::SyncMessage *msg) -> std::shared_ptr<sys::Message>
{
    syncStatus.state          = Sync::OperationState::Running;
    syncStatus.completionCode = Sync::PrepareSyncPackage(this, syncStatus.tempDir);


@@ 317,7 318,7 @@ auto ServiceDesktop::handle(sdesktop::SyncMessage * /*msg*/) -> std::shared_ptr<
    return sys::MessageNone{};
}

auto ServiceDesktop::handle(sdesktop::FactoryMessage * /*msg*/) -> std::shared_ptr<sys::Message>
auto ServiceDesktop::handle([[maybe_unused]] sdesktop::FactoryMessage *msg) -> std::shared_ptr<sys::Message>
{
    LOG_DEBUG("ServiceDesktop: FactoryMessage received");
    sys::SystemManagerCommon::FactoryReset(this);


@@ 325,7 326,7 @@ auto ServiceDesktop::handle(sdesktop::FactoryMessage * /*msg*/) -> std::shared_p
    return sys::MessageNone{};
}

auto ServiceDesktop::handle(sdesktop::usb::USBConfigured *msg) -> std::shared_ptr<sys::Message>
auto ServiceDesktop::handle([[maybe_unused]] sdesktop::usb::USBConfigured *msg) -> std::shared_ptr<sys::Message>
{
    isUsbConfigured = true;
    if (usbSecurityModel->isSecurityEnabled()) {


@@ 336,13 337,15 @@ auto ServiceDesktop::handle(sdesktop::usb::USBConfigured *msg) -> std::shared_pt
        bus.sendUnicast(std::make_shared<sys::TetheringStateRequest>(sys::phone_modes::Tethering::On),
                        service::name::system_manager);
        isPlugEventUnhandled = false;
        desktopWorker->notify(WorkerDesktop::Signal::unlockMTP);
        if (desktopWorker != nullptr) {
            desktopWorker->notify(WorkerDesktop::Signal::unlockMTP);
        }
    }

    return sys::MessageNone{};
}

auto ServiceDesktop::handle(sdesktop::usb::USBDisconnected * /*msg*/) -> std::shared_ptr<sys::Message>
auto ServiceDesktop::handle([[maybe_unused]] sdesktop::usb::USBDisconnected *msg) -> std::shared_ptr<sys::Message>
{
    LOG_INFO("USB disconnected");
    if (usbSecurityModel->isSecurityEnabled()) {


@@ 378,7 381,7 @@ auto ServiceDesktop::getOnboardingState() const -> sdesktop::endpoints::Onboardi
        settings->getValue(settings::SystemProperties::onboardingDone, settings::SettingsScope::Global)));
}

void ServiceDesktop::cleanFileSystemEndpointUndeliveredTransfers()
auto ServiceDesktop::cleanFileSystemEndpointUndeliveredTransfers() -> void
{
    FileOperations::instance().cleanUpUndeliveredTransfers();
}

M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +3 -3
@@ 41,7 41,7 @@ bool WorkerDesktop::init(std::list<sys::WorkerQueueInfo> queues)
    receiveQueue = Worker::getQueueHandleByName(sdesktop::cdcReceiveQueueName);
    sdesktop::endpoints::sender::setSendQueueHandle(Worker::getQueueHandleByName(sdesktop::cdcSendQueueName));

    cpuSentinel                  = std::make_shared<sys::CpuSentinel>("WorkerDesktop", ownerService);
    cpuSentinel                  = std::make_shared<sys::CpuSentinel>(cpuSentinelName, ownerService);
    auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
    ownerService->bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);



@@ 79,8 79,8 @@ void WorkerDesktop::closeWorker()
    close();

    cpuSentinel->ReleaseMinimumFrequency();
    auto sentinelRemoveMsg = std::make_shared<sys::SentinelRemovalMessage>("WorkerDesktop");
    auto result            = ownerService->bus.sendUnicastSync(sentinelRemoveMsg, service::name::system_manager, 1000);
    auto sentinelRemoveMsg = std::make_shared<sys::SentinelRemovalMessage>(cpuSentinelName);
    auto result = ownerService->bus.sendUnicastSync(std::move(sentinelRemoveMsg), service::name::system_manager, 1000);
    if (result.first != sys::ReturnCodes::Success) {
        LOG_ERROR("Sentinel %s could not be removed!", cpuSentinel->GetName().c_str());
    }

M module-services/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/WorkerDesktop.hpp +2 -0
@@ 62,6 62,8 @@ class WorkerDesktop : public sys::Worker
    sys::Service *ownerService = nullptr;
    sdesktop::endpoints::StateMachine parser;

    static constexpr auto cpuSentinelName = "WorkerDesktop";
    std::shared_ptr<sys::CpuSentinel> cpuSentinel;

    std::function<void()> messageProcessedCallback;
};

M module-services/service-desktop/include/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/include/service-desktop/ServiceDesktop.hpp +15 -15
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 71,17 71,17 @@ class ServiceDesktop : public sys::Service
    std::unique_ptr<WorkerDesktop> desktopWorker;
    Sync::OperationStatus syncStatus;

    sys::ReturnCodes InitHandler() override;
    sys::ReturnCodes DeinitHandler() override;
    sys::ReturnCodes SwitchPowerModeHandler(sys::ServicePowerMode mode) override;
    sys::MessagePointer DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) override;
    auto InitHandler() -> sys::ReturnCodes override;
    auto DeinitHandler() -> sys::ReturnCodes override;
    auto SwitchPowerModeHandler(sys::ServicePowerMode mode) -> sys::ReturnCodes override;
    auto DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) -> sys::MessagePointer override;

    void prepareSyncData();
    const Sync::OperationStatus getSyncStatus()
    auto prepareSyncData() -> void;
    auto getSyncStatus() const -> Sync::OperationStatus
    {
        return syncStatus;
    }
    const sdesktop::USBSecurityModel *getSecurity()
    auto getSecurity() const -> const sdesktop::USBSecurityModel *
    {
        return usbSecurityModel.get();
    }


@@ 93,7 93,7 @@ class ServiceDesktop : public sys::Service
    auto getDeviceToken() -> std::string;

    auto getNotificationEntries() const -> std::vector<Outbox::NotificationEntry>;
    void removeNotificationEntries(const std::vector<std::uint32_t> &);
    auto removeNotificationEntries(const std::vector<std::uint32_t> &uidsOfNotificationsToBeRemoved) -> void;
    auto getMtpPath() const noexcept -> std::filesystem::path;
    auto getOnboardingState() const -> sdesktop::endpoints::OnboardingState;



@@ 103,24 103,24 @@ class ServiceDesktop : public sys::Service
    std::unique_ptr<sdesktop::bluetooth::BluetoothMessagesHandler> btMsgHandler;
    OutboxNotifications outboxNotifications;
    sys::TimerHandle connectionActiveTimer;
    static constexpr unsigned int DefaultLogFlushTimeoutInMs = 1000U;
    static constexpr unsigned int defaultLogFlushTimeoutMs   = 1000U;
    bool initialized                                         = false;
    bool isPlugEventUnhandled                                = false;
    bool isUsbConfigured                                     = false;
    std::filesystem::path mtpRootPath;

    void generateDeviceUniqueId();
    auto generateDeviceUniqueId() -> void;
    auto getDeviceUniqueId() const -> std::string;
    void setDeviceUniqueId(const std::string &token);
    auto setDeviceUniqueId(const std::string &token) -> void;

    auto usbWorkerInit() -> sys::ReturnCodes;
    auto usbWorkerDeinit() -> sys::ReturnCodes;

    void restartConnectionActiveTimer();
    auto restartConnectionActiveTimer() -> void;

    void checkChargingCondition();
    auto checkChargingCondition() -> void;

    void cleanFileSystemEndpointUndeliveredTransfers();
    auto cleanFileSystemEndpointUndeliveredTransfers() -> void;

    template <typename T>
    auto connectHandler() -> bool

M third-party/usb_stack => third-party/usb_stack +1 -1
@@ 1,1 1,1 @@
Subproject commit 02d682190ee2cf1efaf60b9e6ea123960fd83e43
Subproject commit 2818d5b6b8bb6e66d2e356e07f2fc5431c9df641