From 51b98b0d06d37f90eb377d8899e4d814e5dfd620 Mon Sep 17 00:00:00 2001 From: Anand Date: Sat, 2 May 2026 10:55:28 +0000 Subject: [PATCH 01/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Ctrl ntwrk state based on PowerMode transitions Test procedure: Change the PowerMode state and verify the behavior Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/CMakeLists.txt | 12 ++ plugin/NetworkManagerImplementation.cpp | 61 ++++++++ plugin/NetworkManagerImplementation.h | 18 +++ plugin/NetworkManagerPowerClient.cpp | 187 ++++++++++++++++++++++++ plugin/NetworkManagerPowerClient.h | 155 ++++++++++++++++++++ 5 files changed, 433 insertions(+) create mode 100644 plugin/NetworkManagerPowerClient.cpp create mode 100644 plugin/NetworkManagerPowerClient.h diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index a5b12d94..2f3fd6e1 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -26,6 +26,13 @@ find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) find_package(CURL) +option(ENABLE_POWERMANAGER "Enable PowerManager COMRPC integration for DeepSleep WiFi management" ON) +if(ENABLE_POWERMANAGER) + find_package(${NAMESPACE}Definitions REQUIRED) + add_definitions(-DENABLE_POWERMANAGER) + message("NetworkManager: PowerManager integration enabled") +endif() + if (USE_RDK_LOGGER) find_package(rdklogger REQUIRED) add_definitions(-DUSE_RDK_LOGGER) @@ -83,6 +90,11 @@ add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerLogger.cpp Module.cpp) +if(ENABLE_POWERMANAGER) + target_sources(${MODULE_IMPL_NAME} PRIVATE NetworkManagerPowerClient.cpp) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${NAMESPACE}Definitions::${NAMESPACE}Definitions) +endif() + if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_GNOME_GDBUS) message("networkmanager building with gdbus") diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index c1fe15f8..dd637315 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -20,6 +20,9 @@ #include #include #include "NetworkManagerImplementation.h" +#ifdef ENABLE_POWERMANAGER +#include "NetworkManagerPowerClient.h" +#endif #if USE_TELEMETRY #include "NetworkManagerJsonEnum.h" @@ -71,6 +74,9 @@ namespace WPEFramework NetworkManagerImplementation::~NetworkManagerImplementation() { NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); +#ifdef ENABLE_POWERMANAGER + _powerClient.reset(); +#endif connectivityMonitor.stopConnectivityMonitor(); _instance = nullptr; platform_deinit(); @@ -199,6 +205,9 @@ namespace WPEFramework NetworkManagerImplementation::platform_init(); /* change gnome networkmanager or netsrvmgr logg level */ NetworkManagerImplementation::platform_logging(static_cast (config.loglevel.Value())); +#ifdef ENABLE_POWERMANAGER + _powerClient.reset(new NetworkManagerPowerClient(*this)); +#endif return(Core::ERROR_NONE); } @@ -1197,5 +1206,57 @@ namespace WPEFramework } #endif } + +#ifdef ENABLE_POWERMANAGER + void NetworkManagerImplementation::OnPowerModePreChange( + const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState, + std::function sendAck) + { + NMLOG_INFO("OnPowerModePreChange: current=%d new=%d", + static_cast(currentState), static_cast(newState)); + + using PowerState = Exchange::IPowerManager::PowerState; + + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + // Transitioning TO DeepSleep + bool standbyMode = _powerClient ? _powerClient->getNetworkStandbyMode() : false; + if (!standbyMode) { + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep, Network Standby OFF — disconnecting WiFi"); + // WiFiDisconnect(); + } else { + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep, Network Standby ON — WiFi left connected"); + } + sendAck(); + } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + // Waking FROM DeepSleep + bool standbyMode = _powerClient ? _powerClient->getNetworkStandbyMode() : false; + if (!standbyMode) { + if (!m_lastConnectedSSID.empty()) { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep, Network Standby OFF — reconnecting to '%s'", + m_lastConnectedSSID.c_str()); + // ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget + } else { + NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep, Network Standby OFF — no last SSID, skipping reconnect"); + } + } else { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep, Network Standby ON — no reconnect needed"); + } + sendAck(); + } else { + // All other transitions: fast-path ack + sendAck(); + } + } + + void NetworkManagerImplementation::OnPowerModeChanged( + const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState) + { + NMLOG_INFO("OnPowerModeChanged: current=%d new=%d", + static_cast(currentState), static_cast(newState)); + // Reserved for future use (e.g., suppress connectivity checks during deep sleep) + } +#endif // ENABLE_POWERMANAGER } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index a1563787..e9a00eed 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -34,6 +34,9 @@ using namespace std; #include "NetworkManagerLogger.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" +#ifdef ENABLE_POWERMANAGER +#include "NetworkManagerPowerClient.h" +#endif /* Forward declarations to avoid pulling GLib/libnm headers into this header */ typedef struct _NMClient NMClient; @@ -63,6 +66,9 @@ namespace WPEFramework namespace Plugin { class NetworkManagerImplementation : public Exchange::INetworkManager +#ifdef ENABLE_POWERMANAGER + , public INetworkPowerCallback +#endif { enum NetworkEvents { @@ -277,6 +283,15 @@ namespace WPEFramework void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); void logTelemetry(const std::string& eventName, const std::string& message); +#ifdef ENABLE_POWERMANAGER + // INetworkPowerCallback overrides + void OnPowerModePreChange(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState, + std::function sendAck) override; + void OnPowerModeChanged(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState) override; +#endif + private: void platform_init(void); void platform_deinit(void); @@ -314,6 +329,9 @@ namespace WPEFramework std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; +#ifdef ENABLE_POWERMANAGER + std::unique_ptr _powerClient; +#endif public: IPAddress m_ethIPv4Address; IPAddress m_wlanIPv4Address; diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp new file mode 100644 index 00000000..c9d5efc8 --- /dev/null +++ b/plugin/NetworkManagerPowerClient.cpp @@ -0,0 +1,187 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#ifdef ENABLE_POWERMANAGER + +#include "NetworkManagerPowerClient.h" +#include "NetworkManagerLogger.h" +#include + +using namespace WPEFramework; +using namespace WPEFramework::Exchange; +using namespace WPEFramework::Plugin; + +// --------------------------------------------------------------------------- +// NetworkManagerPowerClient +// --------------------------------------------------------------------------- + +NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& callback) + : mPreChangeNotification(callback, *this) + , mChangedNotification(callback) +{ + NMLOG_INFO("NetworkManagerPowerClient: connecting to PowerManager"); + if (auto r = Open(RPC::CommunicationTimeOut, Connector(), "org.rdk.PowerManager"); r == Core::ERROR_NONE) { + // Connected; Operational() will be called by the framework when the proxy is ready + } else { + NMLOG_ERROR("NetworkManagerPowerClient: failed to open link to PowerManager (error %u)", r); + } +} + +NetworkManagerPowerClient::~NetworkManagerPowerClient() +{ + NMLOG_INFO("NetworkManagerPowerClient: shutting down"); + Close(Core::infinite); + unregisterEventsAndDeactivate(); +} + +bool NetworkManagerPowerClient::IsValid() const +{ + return mPowerManager != nullptr; +} + +bool NetworkManagerPowerClient::getNetworkStandbyMode() const +{ + bool standbyMode = false; + if (IsValid()) { + if (auto r = mPowerManager->GetNetworkStandbyMode(standbyMode); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: GetNetworkStandbyMode failed (%u)", r); + } + } + return standbyMode; +} + +void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId) +{ + if (IsValid()) { + // Return value intentionally ignored; a stale transactionId is harmless + mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); + } +} + +void NetworkManagerPowerClient::sendDelayPowerModeChange(int transactionId, int seconds) +{ + if (IsValid()) { + if (auto r = mPowerManager->DelayPowerModeChangeBy(mClientId, transactionId, seconds); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: DelayPowerModeChangeBy failed (%u)", r); + } + } +} + +void NetworkManagerPowerClient::Operational(bool upAndRunning) +{ + NMLOG_INFO("NetworkManagerPowerClient::Operational(%s)", upAndRunning ? "true" : "false"); + if (upAndRunning) { + if (!IsValid()) { + mPowerManager = Interface(); + registerEvents(); + } + } else { + unregisterEventsAndDeactivate(); + } +} + +void NetworkManagerPowerClient::registerEvents() +{ + NMLOG_INFO("NetworkManagerPowerClient: registering events"); + if (!IsValid()) { + NMLOG_ERROR("NetworkManagerPowerClient: not in valid state, skipping event registration"); + return; + } + if (auto r = mPowerManager->AddPowerModePreChangeClient("org.rdk.NetworkManager", mClientId); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: AddPowerModePreChangeClient failed (%u)", r); + } + if (auto r = mPowerManager->Register(&mPreChangeNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: Register(preChange) failed (%u)", r); + } + if (auto r = mPowerManager->Register(&mChangedNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: Register(changed) failed (%u)", r); + } +} + +void NetworkManagerPowerClient::unregisterEvents() +{ + NMLOG_INFO("NetworkManagerPowerClient: unregistering events"); + if (!IsValid()) { + NMLOG_ERROR("NetworkManagerPowerClient: not in valid state, skipping event unregistration"); + return; + } + // NOTE: RemovePowerModePreChangeClient MUST be called before Unregister(IModePreChangeNotification) + // per the IPowerManager API contract. + if (auto r = mPowerManager->RemovePowerModePreChangeClient(mClientId); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: RemovePowerModePreChangeClient failed (%u)", r); + } + if (auto r = mPowerManager->Unregister(&mPreChangeNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: Unregister(preChange) failed (%u)", r); + } + if (auto r = mPowerManager->Unregister(&mChangedNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: Unregister(changed) failed (%u)", r); + } +} + +void NetworkManagerPowerClient::unregisterEventsAndDeactivate() +{ + if (IsValid()) { + unregisterEvents(); + mPowerManager->Release(); + mPowerManager = nullptr; + } +} + +// --------------------------------------------------------------------------- +// PreChangeNotification +// --------------------------------------------------------------------------- + +void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( + const PowerState currentState, const PowerState newState, + const int transactionId, const int stateChangeAfter) +{ + NMLOG_INFO("NetworkManagerPowerClient::OnPowerModePreChange current=%d new=%d txId=%d after=%ds", + static_cast(currentState), static_cast(newState), transactionId, stateChangeAfter); + + auto sendAck = [transactionId, this]() { + mClient.sendPowerModePreChangeComplete(transactionId); + }; + + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + // Transitioning TO DeepSleep: request a 5-second window so WiFiDisconnect + // can complete before PowerManager proceeds. + mClient.sendDelayPowerModeChange(transactionId, 5); + mCallback.OnPowerModePreChange(currentState, newState, sendAck); + } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + // Waking FROM DeepSleep: reconnect is fire-and-forget; no delay needed. + mCallback.OnPowerModePreChange(currentState, newState, sendAck); + } else { + // All other transitions: fast-path ack, no network action needed. + sendAck(); + } +} + +// --------------------------------------------------------------------------- +// ChangedNotification +// --------------------------------------------------------------------------- + +void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( + const PowerState currentState, const PowerState newState) +{ + NMLOG_INFO("NetworkManagerPowerClient::OnPowerModeChanged current=%d new=%d", + static_cast(currentState), static_cast(newState)); + mCallback.OnPowerModeChanged(currentState, newState); +} + +#endif // ENABLE_POWERMANAGER diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h new file mode 100644 index 00000000..7fa995d6 --- /dev/null +++ b/plugin/NetworkManagerPowerClient.h @@ -0,0 +1,155 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#ifdef ENABLE_POWERMANAGER + +#include "Module.h" +#include +#include + +namespace WPEFramework { +namespace Plugin { + +/** + * Callback interface that decouples NetworkManagerPowerClient from + * NetworkManagerImplementation. The implementation receives power state + * transitions and must call sendAck() exactly once per OnPowerModePreChange + * invocation to release the PowerManager pre-change lock. + */ +struct INetworkPowerCallback { + virtual ~INetworkPowerCallback() = default; + + /** + * Called when a power mode pre-change event arrives that involves + * POWER_STATE_STANDBY_DEEP_SLEEP (either as the new state or the current + * state). The implementation MUST call sendAck() exactly once. + */ + virtual void OnPowerModePreChange(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState, + std::function sendAck) = 0; + + /** + * Called when a power mode changed event arrives (informational only; + * no ack required). + */ + virtual void OnPowerModeChanged(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState) = 0; +}; + +/** + * Thunder COMRPC client to the PowerManager plugin. + * + * Follows the same pattern as Mediarite's PowerManagerPluginClient: + * - Inherits SmartInterfaceType for automatic + * reconnect / Operational() lifecycle callbacks. + * - Registers as an AddPowerModePreChangeClient so it participates + * in the pre-change ack protocol. + * - Delegates DeepSleep transitions to INetworkPowerCallback. + * - Sends a fast-path PowerModePreChangeComplete for all other transitions. + * + * Lifecycle: + * Construction → Open() connects to PowerManager (async). + * Operational(true) → registers events; IsValid() returns true. + * Operational(false) → unregisters events and releases proxy. + * Destruction → Close() then unregisterEventsAndDeactivate(). + */ +class NetworkManagerPowerClient : protected RPC::SmartInterfaceType { +public: + using PowerState = Exchange::IPowerManager::PowerState; + + explicit NetworkManagerPowerClient(INetworkPowerCallback& callback); + ~NetworkManagerPowerClient() override; + + NetworkManagerPowerClient(const NetworkManagerPowerClient&) = delete; + NetworkManagerPowerClient& operator=(const NetworkManagerPowerClient&) = delete; + + /** Returns true when the PowerManager COMRPC proxy is available. */ + bool IsValid() const; + + /** Queries the current Network Standby mode from PowerManager. */ + bool getNetworkStandbyMode() const; + + /** Sends PowerModePreChangeComplete to PowerManager; ignores return value. */ + void sendPowerModePreChangeComplete(int transactionId); + + /** Requests a delay window extension via DelayPowerModeChangeBy. */ + void sendDelayPowerModeChange(int transactionId, int seconds); + +private: + // ----------------------------------------------------------------------- + // IModePreChangeNotification sink + // ----------------------------------------------------------------------- + class PreChangeNotification : public Exchange::IPowerManager::IModePreChangeNotification { + public: + PreChangeNotification(INetworkPowerCallback& callback, NetworkManagerPowerClient& client) + : mCallback(callback), mClient(client) {} + + void OnPowerModePreChange(const PowerState currentState, const PowerState newState, + const int transactionId, const int stateChangeAfter) override; + + BEGIN_INTERFACE_MAP(PreChangeNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModePreChangeNotification) + END_INTERFACE_MAP + + private: + INetworkPowerCallback& mCallback; + NetworkManagerPowerClient& mClient; + }; + + // ----------------------------------------------------------------------- + // IModeChangedNotification sink + // ----------------------------------------------------------------------- + class ChangedNotification : public Exchange::IPowerManager::IModeChangedNotification { + public: + explicit ChangedNotification(INetworkPowerCallback& callback) : mCallback(callback) {} + + void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override; + + BEGIN_INTERFACE_MAP(ChangedNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) + END_INTERFACE_MAP + + private: + INetworkPowerCallback& mCallback; + }; + + // ----------------------------------------------------------------------- + // SmartInterfaceType lifecycle callback + // ----------------------------------------------------------------------- + void Operational(bool upAndRunning) override; + + void registerEvents(); + void unregisterEvents(); + void unregisterEventsAndDeactivate(); + + // ----------------------------------------------------------------------- + // Members + // ----------------------------------------------------------------------- + Exchange::IPowerManager* mPowerManager{nullptr}; + Core::Sink mPreChangeNotification; + Core::Sink mChangedNotification; + uint32_t mClientId{0}; +}; + +} // namespace Plugin +} // namespace WPEFramework + +#endif // ENABLE_POWERMANAGER From b546d29518506ad0c98a2bc4ecb37bf65c086298 Mon Sep 17 00:00:00 2001 From: Anand Date: Mon, 4 May 2026 05:44:14 +0000 Subject: [PATCH 02/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Add log to know cliendId Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerPowerClient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index c9d5efc8..773d3274 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -105,6 +105,8 @@ void NetworkManagerPowerClient::registerEvents() } if (auto r = mPowerManager->AddPowerModePreChangeClient("org.rdk.NetworkManager", mClientId); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: AddPowerModePreChangeClient failed (%u)", r); + } else { + NMLOG_INFO("NetworkManagerPowerClient: registered as pre-change client, mClientId=%u, sink=%p", mClientId, static_cast(&mPreChangeNotification)); } if (auto r = mPowerManager->Register(&mPreChangeNotification); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: Register(preChange) failed (%u)", r); From 6c7be38f4130440dbcae2513b083de6ea21af0a0 Mon Sep 17 00:00:00 2001 From: Anand Date: Tue, 5 May 2026 04:53:38 +0000 Subject: [PATCH 03/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: fix crash from power worker thread Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 19 ++++++++++++------- plugin/NetworkManagerPowerClient.cpp | 2 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 20 +++++++++++++++++++- plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index dd637315..59a37afd 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1217,25 +1217,33 @@ namespace WPEFramework static_cast(currentState), static_cast(newState)); using PowerState = Exchange::IPowerManager::PowerState; + bool standbyMode = _powerClient ? _powerClient->getNetworkStandbyMode() : false; + + + if (newState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && + currentState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + // Fast path for non-deep-sleep transitions + NMLOG_INFO("OnPowerModePreChange: non-deep-sleep transition, fast-path ack"); + sendAck(); + return; + } if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { // Transitioning TO DeepSleep - bool standbyMode = _powerClient ? _powerClient->getNetworkStandbyMode() : false; if (!standbyMode) { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep, Network Standby OFF — disconnecting WiFi"); - // WiFiDisconnect(); + WiFiDisconnect(); } else { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep, Network Standby ON — WiFi left connected"); } sendAck(); } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { // Waking FROM DeepSleep - bool standbyMode = _powerClient ? _powerClient->getNetworkStandbyMode() : false; if (!standbyMode) { if (!m_lastConnectedSSID.empty()) { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep, Network Standby OFF — reconnecting to '%s'", m_lastConnectedSSID.c_str()); - // ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget + // ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget } else { NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep, Network Standby OFF — no last SSID, skipping reconnect"); } @@ -1243,9 +1251,6 @@ namespace WPEFramework NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep, Network Standby ON — no reconnect needed"); } sendAck(); - } else { - // All other transitions: fast-path ack - sendAck(); } } diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 773d3274..74761b56 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -106,7 +106,7 @@ void NetworkManagerPowerClient::registerEvents() if (auto r = mPowerManager->AddPowerModePreChangeClient("org.rdk.NetworkManager", mClientId); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: AddPowerModePreChangeClient failed (%u)", r); } else { - NMLOG_INFO("NetworkManagerPowerClient: registered as pre-change client, mClientId=%u, sink=%p", mClientId, static_cast(&mPreChangeNotification)); + NMLOG_INFO("NetworkManagerPowerClient: registered as pre-change client, mClientId=%u", mClientId); } if (auto r = mPowerManager->Register(&mPreChangeNotification); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: Register(preChange) failed (%u)", r); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 7fb4bb5d..98cb2d1b 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -45,7 +45,11 @@ namespace WPEFramework wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false), m_objectPath(nullptr), m_wifidevice(nullptr), m_source(nullptr), m_cancellable(nullptr){ NMLOG_INFO("wifiManager"); m_nmContext = g_main_context_new(); - g_main_context_push_thread_default(m_nmContext); + // g_main_context_push_thread_default(m_nmContext); + // Do NOT push m_nmContext here. Pushing here permanently locks ownership + // to the constructor thread (owner_count stays at 1, never released). + // All callers — including power-event threads — must push/pop around + // each createClientNewConnection()/deleteClientConnection() pair instead. m_loop = g_main_loop_new(m_nmContext, FALSE); } @@ -53,12 +57,21 @@ namespace WPEFramework { GError *error = NULL; + // Serialize concurrent wifi operations from different threads + m_opMutex.lock(); + // Push our private context as thread-default so nm_client_new (and any + // internal g_dbus_proxy_new_sync it calls) uses m_nmContext instead of + // the global default context, which is owned by nm_event_thrd. + g_main_context_push_thread_default(m_nmContext); + m_client = nm_client_new(NULL, &error); if (!m_client || !m_loop) { if (error) { NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); g_error_free(error); } + g_main_context_pop_thread_default(m_nmContext); + m_opMutex.unlock(); return false; } @@ -102,6 +115,11 @@ namespace WPEFramework g_free(m_objectPath); m_objectPath = NULL; } + + // Pop the context pushed in createClientNewConnection() + g_main_context_pop_thread_default(m_nmContext); + // Release operation lock acquired in createClientNewConnection() + m_opMutex.unlock(); } bool wifiManager::quit(NMDevice *wifiNMDevice) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 4d0fa086..f2924751 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -107,6 +107,7 @@ namespace WPEFramework GSource *m_source; GCancellable *m_cancellable; std::mutex m_cancellableMutex; + std::mutex m_opMutex; // serializes concurrent wifi operations from different threads bool m_isSuccess = false; SecretAgent m_secretAgent; }; From 4d59a20b003106df32eaf496f27599d07d5920d2 Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 6 May 2026 06:24:09 +0000 Subject: [PATCH 04/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: offload prechange WiFi disc to dedicated powerthrd Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 40 +++------ plugin/NetworkManagerPowerClient.cpp | 104 ++++++++++++++++++++---- plugin/NetworkManagerPowerClient.h | 30 ++++++- 3 files changed, 128 insertions(+), 46 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 59a37afd..97517f1e 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1213,45 +1213,27 @@ namespace WPEFramework const Exchange::IPowerManager::PowerState newState, std::function sendAck) { + // Called from NetworkManagerPowerClient's power thread. + // Policy (standbyMode check, DeepSleep filter) has already been + // applied by the power thread before calling here. NMLOG_INFO("OnPowerModePreChange: current=%d new=%d", static_cast(currentState), static_cast(newState)); using PowerState = Exchange::IPowerManager::PowerState; - bool standbyMode = _powerClient ? _powerClient->getNetworkStandbyMode() : false; - - - if (newState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && - currentState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - // Fast path for non-deep-sleep transitions - NMLOG_INFO("OnPowerModePreChange: non-deep-sleep transition, fast-path ack"); - sendAck(); - return; - } if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - // Transitioning TO DeepSleep - if (!standbyMode) { - NMLOG_INFO("OnPowerModePreChange: going to DeepSleep, Network Standby OFF — disconnecting WiFi"); - WiFiDisconnect(); - } else { - NMLOG_INFO("OnPowerModePreChange: going to DeepSleep, Network Standby ON — WiFi left connected"); - } - sendAck(); + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); + WiFiDisconnect(); } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - // Waking FROM DeepSleep - if (!standbyMode) { - if (!m_lastConnectedSSID.empty()) { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep, Network Standby OFF — reconnecting to '%s'", - m_lastConnectedSSID.c_str()); - // ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget - } else { - NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep, Network Standby OFF — no last SSID, skipping reconnect"); - } + if (!m_lastConnectedSSID.empty()) { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", + m_lastConnectedSSID.c_str()); + // ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget } else { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep, Network Standby ON — no reconnect needed"); + NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); } - sendAck(); } + sendAck(); } void NetworkManagerImplementation::OnPowerModeChanged( diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 74761b56..a5f00f38 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -32,7 +32,8 @@ using namespace WPEFramework::Plugin; // --------------------------------------------------------------------------- NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& callback) - : mPreChangeNotification(callback, *this) + : mCallback(callback) + , mPreChangeNotification(*this) , mChangedNotification(callback) { NMLOG_INFO("NetworkManagerPowerClient: connecting to PowerManager"); @@ -46,6 +47,13 @@ NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& call NetworkManagerPowerClient::~NetworkManagerPowerClient() { NMLOG_INFO("NetworkManagerPowerClient: shutting down"); + // Stop the power-event thread first so any in-flight work completes + // before we release the COM-RPC proxy. + mStopThread = true; + mQueueCv.notify_one(); + if (mPowerThread.joinable()) { + mPowerThread.join(); + } Close(Core::infinite); unregisterEventsAndDeactivate(); } @@ -90,8 +98,19 @@ void NetworkManagerPowerClient::Operational(bool upAndRunning) if (!IsValid()) { mPowerManager = Interface(); registerEvents(); + // Start the dedicated power-event thread after registration so it + // is ready to handle events as soon as they can arrive. + mStopThread = false; + mPowerThread = std::thread(&NetworkManagerPowerClient::powerThreadLoop, this); } } else { + // Stop the power-event thread before unregistering so any in-flight + // event that was already enqueued is drained with a fast ack. + mStopThread = true; + mQueueCv.notify_one(); + if (mPowerThread.joinable()) { + mPowerThread.join(); + } unregisterEventsAndDeactivate(); } } @@ -145,6 +164,63 @@ void NetworkManagerPowerClient::unregisterEventsAndDeactivate() } } +// --------------------------------------------------------------------------- +// Power event thread +// --------------------------------------------------------------------------- + +void NetworkManagerPowerClient::powerThreadLoop() +{ + NMLOG_INFO("NetworkManagerPowerClient: power event thread started"); + while (true) { + PowerEvent event{}; + { + std::unique_lock lock(mQueueMutex); + mQueueCv.wait(lock, [this]{ return !mEventQueue.empty() || mStopThread.load(); }); + + if (mStopThread) { + // Drain remaining events with fast acks before exiting so + // PowerManager is never left waiting on a stale transaction. + std::vector pending; + while (!mEventQueue.empty()) { + pending.push_back(mEventQueue.front().transactionId); + mEventQueue.pop(); + } + lock.unlock(); + for (int txId : pending) { + sendPowerModePreChangeComplete(txId); + } + break; + } + + event = mEventQueue.front(); + mEventQueue.pop(); + } + // Lock released — process event on this thread (blocking is fine here) + + auto sendAck = [transactionId = event.transactionId, this]() { + sendPowerModePreChangeComplete(transactionId); + }; + + const bool toDeepSleep = (event.newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + + if ((toDeepSleep || fromDeepSleep) && !event.standbyMode) { + // Deep-sleep transition with Network Standby OFF: delegate to + // NetworkManagerImplementation (WiFiDisconnect / reconnect) which + // will call sendAck() when done. + NMLOG_INFO("NetworkManagerPowerClient: power thread — %s DeepSleep standby OFF", + toDeepSleep ? "to" : "from"); + mCallback.OnPowerModePreChange(event.currentState, event.newState, sendAck); + } else { + // standby ON or non-DeepSleep: no WiFi action needed, ack immediately. + NMLOG_INFO("NetworkManagerPowerClient: power thread — fast-path ack (standbyMode=%d toDeepSleep=%d fromDeepSleep=%d)", + event.standbyMode, toDeepSleep, fromDeepSleep); + sendAck(); + } + } + NMLOG_INFO("NetworkManagerPowerClient: power event thread stopped"); +} + // --------------------------------------------------------------------------- // PreChangeNotification // --------------------------------------------------------------------------- @@ -156,22 +232,22 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( NMLOG_INFO("NetworkManagerPowerClient::OnPowerModePreChange current=%d new=%d txId=%d after=%ds", static_cast(currentState), static_cast(newState), transactionId, stateChangeAfter); - auto sendAck = [transactionId, this]() { - mClient.sendPowerModePreChangeComplete(transactionId); - }; + // Query standby mode inline on the COM-RPC dispatcher thread — it is a + // COM-RPC call and must not be made from the power thread. + const bool standbyMode = mClient.getNetworkStandbyMode(); - if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - // Transitioning TO DeepSleep: request a 5-second window so WiFiDisconnect - // can complete before PowerManager proceeds. + // Reserve a delay window now (before returning) so PowerManager knows to + // wait at least 5 s. Only needed when we will actually disconnect WiFi. + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && !standbyMode) { mClient.sendDelayPowerModeChange(transactionId, 5); - mCallback.OnPowerModePreChange(currentState, newState, sendAck); - } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - // Waking FROM DeepSleep: reconnect is fire-and-forget; no delay needed. - mCallback.OnPowerModePreChange(currentState, newState, sendAck); - } else { - // All other transitions: fast-path ack, no network action needed. - sendAck(); } + + // Enqueue and return immediately — the power thread does the real work. + { + std::lock_guard lock(mClient.mQueueMutex); + mClient.mEventQueue.push(PowerEvent{currentState, newState, standbyMode, transactionId}); + } + mClient.mQueueCv.notify_one(); } // --------------------------------------------------------------------------- diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h index 7fa995d6..b3a45fe2 100644 --- a/plugin/NetworkManagerPowerClient.h +++ b/plugin/NetworkManagerPowerClient.h @@ -23,7 +23,13 @@ #include "Module.h" #include +#include +#include #include +#include +#include +#include +#include namespace WPEFramework { namespace Plugin { @@ -99,8 +105,8 @@ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType mPreChangeNotification; Core::Sink mChangedNotification; uint32_t mClientId{0}; + + // Power-event thread: receives events enqueued by the COM-RPC dispatcher + // thread and processes them (WiFiDisconnect etc.) without blocking the + // dispatcher. + struct PowerEvent { + PowerState currentState; + PowerState newState; + bool standbyMode; + int transactionId; + }; + + std::thread mPowerThread; + std::queue mEventQueue; + std::mutex mQueueMutex; + std::condition_variable mQueueCv; + std::atomic mStopThread{false}; + + void powerThreadLoop(); }; } // namespace Plugin From 7c8996e1c97869f68ac97e53a3dd7dd3f5f1b8d3 Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 6 May 2026 13:52:32 +0000 Subject: [PATCH 05/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: enabled ConnectToKnownSSID() Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 97517f1e..f11ae8c0 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1228,7 +1228,7 @@ namespace WPEFramework if (!m_lastConnectedSSID.empty()) { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", m_lastConnectedSSID.c_str()); - // ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget + ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget } else { NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); } From 524ce4c8149e7b290926c7335b98dcd6b49478bc Mon Sep 17 00:00:00 2001 From: Anand Date: Mon, 11 May 2026 03:59:41 +0000 Subject: [PATCH 06/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: trigger normal WiFi scan on DeepSleep wakeup with Network Standby ON to handle AP channel changes Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 8 ++++- plugin/NetworkManagerPowerClient.cpp | 45 +++++++++++++++++++++---- plugin/NetworkManagerPowerClient.h | 13 ++++--- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index f11ae8c0..ab1ccf2c 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1242,7 +1242,13 @@ namespace WPEFramework { NMLOG_INFO("OnPowerModeChanged: current=%d new=%d", static_cast(currentState), static_cast(newState)); - // Reserved for future use (e.g., suppress connectivity checks during deep sleep) + if (currentState == Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP) { + // Waking from DeepSleep with Network Standby ON: the AP may have + // changed channel while the device slept (802.11 CSA). Trigger an + // active scan so the driver discovers the AP on its new channel. + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); + StartWiFiScan("", nullptr); + } } #endif // ENABLE_POWERMANAGER } diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index a5f00f38..92c3be06 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -34,7 +34,7 @@ using namespace WPEFramework::Plugin; NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& callback) : mCallback(callback) , mPreChangeNotification(*this) - , mChangedNotification(callback) + , mChangedNotification(*this) { NMLOG_INFO("NetworkManagerPowerClient: connecting to PowerManager"); if (auto r = Open(RPC::CommunicationTimeOut, Connector(), "org.rdk.PowerManager"); r == Core::ERROR_NONE) { @@ -180,14 +180,17 @@ void NetworkManagerPowerClient::powerThreadLoop() if (mStopThread) { // Drain remaining events with fast acks before exiting so // PowerManager is never left waiting on a stale transaction. - std::vector pending; + // CHANGED events have no ack protocol — skip them. + std::vector pending; while (!mEventQueue.empty()) { - pending.push_back(mEventQueue.front().transactionId); + pending.push_back(mEventQueue.front()); mEventQueue.pop(); } lock.unlock(); - for (int txId : pending) { - sendPowerModePreChangeComplete(txId); + for (const auto& e : pending) { + if (e.type == PowerEvent::EventType::PRE_CHANGE) { + sendPowerModePreChangeComplete(e.transactionId); + } } break; } @@ -197,6 +200,20 @@ void NetworkManagerPowerClient::powerThreadLoop() } // Lock released — process event on this thread (blocking is fine here) + if (event.type == PowerEvent::EventType::CHANGED) { + // Wakeup notification — no ack required. + const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + if (fromDeepSleep && event.standbyMode) { + NMLOG_INFO("NetworkManagerPowerClient: power thread — wakeup from DeepSleep standby ON, triggering WiFi scan"); + mCallback.OnPowerModeChanged(event.currentState, event.newState); + } else { + NMLOG_INFO("NetworkManagerPowerClient: power thread — CHANGED event, no action (fromDeepSleep=%d standbyMode=%d)", + fromDeepSleep, event.standbyMode); + } + continue; + } + + // PRE_CHANGE event processing below auto sendAck = [transactionId = event.transactionId, this]() { sendPowerModePreChangeComplete(transactionId); }; @@ -236,6 +253,9 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( // COM-RPC call and must not be made from the power thread. const bool standbyMode = mClient.getNetworkStandbyMode(); + // Cache for use by ChangedNotification + mClient.mLastChangeStandbyMode = standbyMode; + // Reserve a delay window now (before returning) so PowerManager knows to // wait at least 5 s. Only needed when we will actually disconnect WiFi. if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && !standbyMode) { @@ -245,7 +265,8 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( // Enqueue and return immediately — the power thread does the real work. { std::lock_guard lock(mClient.mQueueMutex); - mClient.mEventQueue.push(PowerEvent{currentState, newState, standbyMode, transactionId}); + mClient.mEventQueue.push(PowerEvent{PowerEvent::EventType::PRE_CHANGE, + currentState, newState, standbyMode, transactionId}); } mClient.mQueueCv.notify_one(); } @@ -259,7 +280,17 @@ void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( { NMLOG_INFO("NetworkManagerPowerClient::OnPowerModeChanged current=%d new=%d", static_cast(currentState), static_cast(newState)); - mCallback.OnPowerModeChanged(currentState, newState); + + // Use the standby mode cached + const bool standbyMode = mClient.mLastChangeStandbyMode; + + // Enqueue and return immediately so the COM-RPC dispatcher thread is freed. + { + std::lock_guard lock(mClient.mQueueMutex); + mClient.mEventQueue.push(PowerEvent{PowerEvent::EventType::CHANGED, + currentState, newState, standbyMode, 0}); + } + mClient.mQueueCv.notify_one(); } #endif // ENABLE_POWERMANAGER diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h index b3a45fe2..14009200 100644 --- a/plugin/NetworkManagerPowerClient.h +++ b/plugin/NetworkManagerPowerClient.h @@ -37,8 +37,7 @@ namespace Plugin { /** * Callback interface that decouples NetworkManagerPowerClient from * NetworkManagerImplementation. The implementation receives power state - * transitions and must call sendAck() exactly once per OnPowerModePreChange - * invocation to release the PowerManager pre-change lock. + * transitions and must call sendAck() exactly once per OnPowerModePreChange. */ struct INetworkPowerCallback { virtual ~INetworkPowerCallback() = default; @@ -124,7 +123,7 @@ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType mStopThread{false}; + // Cached standby mode from the last PRE_CHANGE event. + bool mLastChangeStandbyMode{false}; + void powerThreadLoop(); }; From 28058da0e10c1d89885387df8f35c9ff51e1452b Mon Sep 17 00:00:00 2001 From: Anand Date: Mon, 11 May 2026 16:32:29 +0000 Subject: [PATCH 07/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: check before initiating wifi connect and disconnect Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index ab1ccf2c..f2dbd9e3 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1222,10 +1222,16 @@ namespace WPEFramework using PowerState = Exchange::IPowerManager::PowerState; if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); - WiFiDisconnect(); + if (m_wlanEnabled.load() && m_wlanConnected.load()) { + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); + WiFiDisconnect(); + } + else + { + NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); + } } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - if (!m_lastConnectedSSID.empty()) { + if (m_wlanEnabled.load() && !m_lastConnectedSSID.empty()) { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", m_lastConnectedSSID.c_str()); ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget From b66c9708981c8df281cee6fb975c1215e7719bc0 Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 13 May 2026 01:42:09 +0000 Subject: [PATCH 08/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Disconnect ethernet on DeepSleep entry and reconnect on wakeup OnPowerModePreChange Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 22 ++++++++++++++++-- plugin/NetworkManagerImplementation.h | 2 ++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 16 +++++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.cpp | 28 +++++++++++++++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index f2dbd9e3..908ad6cc 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1224,20 +1224,38 @@ namespace WPEFramework if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { if (m_wlanEnabled.load() && m_wlanConnected.load()) { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); - WiFiDisconnect(); + uint32_t rcWifiDown = WiFiDisconnect(); + if (rcWifiDown != Core::ERROR_NONE) + NMLOG_WARNING("OnPowerModePreChange: WiFiDisconnect failed (rc=%u)", rcWifiDown); } else { NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); } + if (m_ethEnabled.load() && m_ethConnected.load()) { + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting Ethernet"); + uint32_t rcEthDown = EthernetDisconnect(); + if (rcEthDown != Core::ERROR_NONE) + NMLOG_WARNING("OnPowerModePreChange: EthernetDisconnect failed (rc=%u)", rcEthDown); + } else { + NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not connected, skipping disconnect"); + } } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { if (m_wlanEnabled.load() && !m_lastConnectedSSID.empty()) { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", m_lastConnectedSSID.c_str()); - ConnectToKnownSSID(m_lastConnectedSSID); // fire-and-forget + uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); + if (rcWifiUp != Core::ERROR_NONE) + NMLOG_WARNING("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); } else { NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); } + if (m_ethEnabled.load()) { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting Ethernet"); + uint32_t rcEthUp = EthernetConnect(); + if (rcEthUp != Core::ERROR_NONE) + NMLOG_WARNING("OnPowerModePreChange: EthernetConnect failed (rc=%u)", rcEthUp); + } } sendAck(); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index e9a00eed..cbdd641a 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -232,6 +232,8 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; + uint32_t EthernetDisconnect(void); + uint32_t EthernetConnect(void); uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index b2010fe9..7984a1c2 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1147,6 +1147,22 @@ namespace WPEFramework return rc; } + uint32_t NetworkManagerImplementation::EthernetDisconnect(void) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->ethernetDisconnect()) + rc = Core::ERROR_NONE; + return rc; + } + + uint32_t NetworkManagerImplementation::EthernetConnect(void) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1")) + rc = Core::ERROR_NONE; + return rc; + } + uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 98cb2d1b..8e69c44b 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -425,6 +425,34 @@ namespace WPEFramework return m_isSuccess; } + bool wifiManager::ethernetDisconnect() + { + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + if(!createClientNewConnection()) + return false; + + NMDevice *ethDevice = nm_client_get_device_by_iface(m_client, nmUtils::ethIface()); + if(ethDevice == NULL) { + NMLOG_WARNING("ethernet device not found !"); + deleteClientConnection(); + return true; + } + + deviceState = nm_device_get_state(ethDevice); + NMLOG_DEBUG("ethernet device current state is %d !", deviceState); + if (deviceState <= NM_DEVICE_STATE_DISCONNECTED || deviceState == NM_DEVICE_STATE_FAILED || deviceState == NM_DEVICE_STATE_DEACTIVATING) + { + NMLOG_WARNING("ethernet already disconnected !"); + deleteClientConnection(); + return true; + } + + nm_device_disconnect_async(ethDevice, m_cancellable, disconnectCb, this); + wait(m_loop); + deleteClientConnection(); + return m_isSuccess; + } + static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, Exchange::INetworkManager::WiFiConnectTo& ssidInfo) { NMAccessPoint *AccessPoint = nullptr; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index f2924751..7feb4942 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,6 +52,7 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); + bool ethernetDisconnect(); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); From cb9c5052eef828aa1bedda3f535b0cf9753b025b Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 13 May 2026 07:01:57 +0000 Subject: [PATCH 09/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: guard ethernet wakeup reconnect with m_ethDisconnectedForSleep Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 13 ++++++++++--- plugin/NetworkManagerImplementation.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 908ad6cc..be17e058 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -57,6 +57,7 @@ namespace WPEFramework m_wlanConnected.store(false); m_ethEnabled.store(false); m_wlanEnabled.store(false); + m_ethDisconnectedForSleep.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ Core::ProcessInfo().Name("NWMgrPlugin"); @@ -1235,8 +1236,11 @@ namespace WPEFramework if (m_ethEnabled.load() && m_ethConnected.load()) { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting Ethernet"); uint32_t rcEthDown = EthernetDisconnect(); - if (rcEthDown != Core::ERROR_NONE) - NMLOG_WARNING("OnPowerModePreChange: EthernetDisconnect failed (rc=%u)", rcEthDown); + if (rcEthDown == Core::ERROR_NONE) { + m_ethDisconnectedForSleep.store(true); + } else { + NMLOG_WARNING("OnPowerModePreChange: EthernetDisconnect failed (rc=%u), will not reconnect on wakeup", rcEthDown); + } } else { NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not connected, skipping disconnect"); } @@ -1250,11 +1254,14 @@ namespace WPEFramework } else { NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); } - if (m_ethEnabled.load()) { + if (m_ethDisconnectedForSleep.load()) { + m_ethDisconnectedForSleep.store(false); NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting Ethernet"); uint32_t rcEthUp = EthernetConnect(); if (rcEthUp != Core::ERROR_NONE) NMLOG_WARNING("OnPowerModePreChange: EthernetConnect failed (rc=%u)", rcEthUp); + } else { + NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — Ethernet was not disconnected for sleep, skipping reconnect"); } } sendAck(); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index cbdd641a..ab22b349 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -343,6 +343,7 @@ namespace WPEFramework std::atomic m_wlanConnected; std::atomic m_ethEnabled; std::atomic m_wlanEnabled; + std::atomic m_ethDisconnectedForSleep; std::string m_lastConnectedSSID; NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ GMainContext *m_nmContext{nullptr}; /* isolated context, not the global default */ From 5be7870e33e67cfc24506e13d8c36e5c6ccaf4ed Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 13 May 2026 17:00:29 +0000 Subject: [PATCH 10/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: guard wifi wakeup reconnect with m_wlanDisconnectedForSleep Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 21 ++++++++++++++++++--- plugin/NetworkManagerImplementation.h | 1 + 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index be17e058..23e1fd6b 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -58,6 +58,7 @@ namespace WPEFramework m_ethEnabled.store(false); m_wlanEnabled.store(false); m_ethDisconnectedForSleep.store(false); + m_wlanDisconnectedForSleep.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ Core::ProcessInfo().Name("NWMgrPlugin"); @@ -1222,19 +1223,32 @@ namespace WPEFramework using PowerState = Exchange::IPowerManager::PowerState; + if (newState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && + currentState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + NMLOG_INFO("OnPowerModePreChange: not entering or exiting DeepSleep, no action needed"); + sendAck(); + return; + } + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { if (m_wlanEnabled.load() && m_wlanConnected.load()) { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); + uint32_t rcWifiDown = WiFiDisconnect(); - if (rcWifiDown != Core::ERROR_NONE) - NMLOG_WARNING("OnPowerModePreChange: WiFiDisconnect failed (rc=%u)", rcWifiDown); + if (rcWifiDown == Core::ERROR_NONE) { + m_wlanDisconnectedForSleep.store(true); + } else { + NMLOG_WARNING("OnPowerModePreChange: WiFiDisconnect failed (rc=%u), will not reconnect on wakeup", rcWifiDown); + } } else { NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); } + if (m_ethEnabled.load() && m_ethConnected.load()) { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting Ethernet"); + uint32_t rcEthDown = EthernetDisconnect(); if (rcEthDown == Core::ERROR_NONE) { m_ethDisconnectedForSleep.store(true); @@ -1245,9 +1259,10 @@ namespace WPEFramework NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not connected, skipping disconnect"); } } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - if (m_wlanEnabled.load() && !m_lastConnectedSSID.empty()) { + if (m_wlanDisconnectedForSleep.load() && !m_lastConnectedSSID.empty()) { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", m_lastConnectedSSID.c_str()); + m_wlanDisconnectedForSleep.store(false); uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); if (rcWifiUp != Core::ERROR_NONE) NMLOG_WARNING("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index ab22b349..0d555420 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -344,6 +344,7 @@ namespace WPEFramework std::atomic m_ethEnabled; std::atomic m_wlanEnabled; std::atomic m_ethDisconnectedForSleep; + std::atomic m_wlanDisconnectedForSleep; std::string m_lastConnectedSSID; NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ GMainContext *m_nmContext{nullptr}; /* isolated context, not the global default */ From 707e810407ed2afb332b6e167d7ab230810f4083 Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 14 May 2026 05:02:49 +0000 Subject: [PATCH 11/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Additional logging and code alignment Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 70 +++++++++++++++++-------- plugin/NetworkManagerPowerClient.cpp | 1 + 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 23e1fd6b..78f4e0e8 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1224,20 +1224,26 @@ namespace WPEFramework using PowerState = Exchange::IPowerManager::PowerState; if (newState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && - currentState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + currentState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) + { NMLOG_INFO("OnPowerModePreChange: not entering or exiting DeepSleep, no action needed"); sendAck(); return; } - if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - if (m_wlanEnabled.load() && m_wlanConnected.load()) { + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) + { + if (m_wlanEnabled.load() && m_wlanConnected.load()) + { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); uint32_t rcWifiDown = WiFiDisconnect(); - if (rcWifiDown == Core::ERROR_NONE) { + if (rcWifiDown == Core::ERROR_NONE) + { m_wlanDisconnectedForSleep.store(true); - } else { + } + else + { NMLOG_WARNING("OnPowerModePreChange: WiFiDisconnect failed (rc=%u), will not reconnect on wakeup", rcWifiDown); } } @@ -1246,37 +1252,59 @@ namespace WPEFramework NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); } - if (m_ethEnabled.load() && m_ethConnected.load()) { + if (m_ethEnabled.load() && m_ethConnected.load()) + { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting Ethernet"); uint32_t rcEthDown = EthernetDisconnect(); - if (rcEthDown == Core::ERROR_NONE) { + if (rcEthDown == Core::ERROR_NONE) + { m_ethDisconnectedForSleep.store(true); - } else { + } + else + { NMLOG_WARNING("OnPowerModePreChange: EthernetDisconnect failed (rc=%u), will not reconnect on wakeup", rcEthDown); } - } else { + } + else + { NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not connected, skipping disconnect"); } - } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { - if (m_wlanDisconnectedForSleep.load() && !m_lastConnectedSSID.empty()) { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", + } + else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) + { + if (m_wlanDisconnectedForSleep.load()) + { + if (!m_lastConnectedSSID.empty()) + { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", m_lastConnectedSSID.c_str()); - m_wlanDisconnectedForSleep.store(false); - uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); - if (rcWifiUp != Core::ERROR_NONE) - NMLOG_WARNING("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); - } else { - NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); + m_wlanDisconnectedForSleep.store(false); + uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); + if (rcWifiUp != Core::ERROR_NONE) + NMLOG_WARNING("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); + } + else + { + NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); + } } - if (m_ethDisconnectedForSleep.load()) { + else + { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — WiFi was not connected or was already down before sleep, skipping reconnect"); + } + + if (m_ethDisconnectedForSleep.load()) + { m_ethDisconnectedForSleep.store(false); NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting Ethernet"); uint32_t rcEthUp = EthernetConnect(); if (rcEthUp != Core::ERROR_NONE) NMLOG_WARNING("OnPowerModePreChange: EthernetConnect failed (rc=%u)", rcEthUp); - } else { - NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — Ethernet was not disconnected for sleep, skipping reconnect"); + } + else + { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — Ethernet was not connected or was already down before sleep, skipping reconnect"); } } sendAck(); diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 92c3be06..6619f217 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -77,6 +77,7 @@ bool NetworkManagerPowerClient::getNetworkStandbyMode() const void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId) { if (IsValid()) { + NMLOG_INFO("NetworkManagerPowerClient: sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); // Return value intentionally ignored; a stale transactionId is harmless mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); } From 1ec7b2a55d9e797c76daf83e5eec7b9450eabef1 Mon Sep 17 00:00:00 2001 From: Anand Date: Fri, 15 May 2026 06:05:25 +0000 Subject: [PATCH 12/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Fix for trigger Wi-Fi scan OnPowerMode Changed Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 7 +++++-- plugin/NetworkManagerImplementation.h | 2 ++ plugin/NetworkManagerPowerClient.cpp | 5 ++--- plugin/gnome/NetworkManagerGnomeProxy.cpp | 2 ++ plugin/gnome/NetworkManagerGnomeWIFI.cpp | 6 ++---- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 78f4e0e8..2a735d57 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1320,8 +1320,11 @@ namespace WPEFramework // Waking from DeepSleep with Network Standby ON: the AP may have // changed channel while the device slept (802.11 CSA). Trigger an // active scan so the driver discovers the AP on its new channel. - NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); - StartWiFiScan("", nullptr); + if (m_wlanEnabled.load() && m_wlanConnected.load()) + { + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); + StartWiFiScan("", nullptr); + } } } #endif // ENABLE_POWERMANAGER diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 0d555420..47ddf0cb 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -232,8 +232,10 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; +#ifdef ENABLE_POWERMANAGER uint32_t EthernetDisconnect(void); uint32_t EthernetConnect(void); +#endif //ENABLE_POWERMANAGER uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 6619f217..ab8e4e47 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -78,7 +78,6 @@ void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId { if (IsValid()) { NMLOG_INFO("NetworkManagerPowerClient: sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); - // Return value intentionally ignored; a stale transactionId is harmless mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); } } @@ -205,7 +204,7 @@ void NetworkManagerPowerClient::powerThreadLoop() // Wakeup notification — no ack required. const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); if (fromDeepSleep && event.standbyMode) { - NMLOG_INFO("NetworkManagerPowerClient: power thread — wakeup from DeepSleep standby ON, triggering WiFi scan"); + NMLOG_INFO("NetworkManagerPowerClient: power thread — wakeup from DeepSleep standby ON"); mCallback.OnPowerModeChanged(event.currentState, event.newState); } else { NMLOG_INFO("NetworkManagerPowerClient: power thread — CHANGED event, no action (fromDeepSleep=%d standbyMode=%d)", @@ -258,7 +257,7 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( mClient.mLastChangeStandbyMode = standbyMode; // Reserve a delay window now (before returning) so PowerManager knows to - // wait at least 5 s. Only needed when we will actually disconnect WiFi. + // wait at least 5 s. if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && !standbyMode) { mClient.sendDelayPowerModeChange(transactionId, 5); } diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 7984a1c2..340891a1 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1147,6 +1147,7 @@ namespace WPEFramework return rc; } +#ifdef ENABLE_POWERMANAGER uint32_t NetworkManagerImplementation::EthernetDisconnect(void) { uint32_t rc = Core::ERROR_GENERAL; @@ -1162,6 +1163,7 @@ namespace WPEFramework rc = Core::ERROR_NONE; return rc; } +#endif //ENABLE_POWERMANAGER uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) { diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 8e69c44b..f918fb02 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -48,7 +48,7 @@ namespace WPEFramework // g_main_context_push_thread_default(m_nmContext); // Do NOT push m_nmContext here. Pushing here permanently locks ownership // to the constructor thread (owner_count stays at 1, never released). - // All callers — including power-event threads — must push/pop around + // All callers — must push/pop around // each createClientNewConnection()/deleteClientConnection() pair instead. m_loop = g_main_loop_new(m_nmContext, FALSE); } @@ -59,9 +59,7 @@ namespace WPEFramework // Serialize concurrent wifi operations from different threads m_opMutex.lock(); - // Push our private context as thread-default so nm_client_new (and any - // internal g_dbus_proxy_new_sync it calls) uses m_nmContext instead of - // the global default context, which is owned by nm_event_thrd. + g_main_context_push_thread_default(m_nmContext); m_client = nm_client_new(NULL, &error); From 830cff9bc2bb6029008d96cc9103626419f60d3e Mon Sep 17 00:00:00 2001 From: Anand Date: Tue, 19 May 2026 06:39:12 +0000 Subject: [PATCH 13/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: code cleanup Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/CMakeLists.txt | 15 ++------------- plugin/NetworkManagerImplementation.cpp | 9 --------- plugin/NetworkManagerImplementation.h | 10 ---------- plugin/NetworkManagerPowerClient.cpp | 6 +----- plugin/NetworkManagerPowerClient.h | 6 +----- plugin/gnome/NetworkManagerGnomeProxy.cpp | 2 -- 6 files changed, 4 insertions(+), 44 deletions(-) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 2f3fd6e1..c211d894 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -26,13 +26,6 @@ find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) find_package(CURL) -option(ENABLE_POWERMANAGER "Enable PowerManager COMRPC integration for DeepSleep WiFi management" ON) -if(ENABLE_POWERMANAGER) - find_package(${NAMESPACE}Definitions REQUIRED) - add_definitions(-DENABLE_POWERMANAGER) - message("NetworkManager: PowerManager integration enabled") -endif() - if (USE_RDK_LOGGER) find_package(rdklogger REQUIRED) add_definitions(-DUSE_RDK_LOGGER) @@ -88,12 +81,8 @@ add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp NetworkManagerLogger.cpp - Module.cpp) - -if(ENABLE_POWERMANAGER) - target_sources(${MODULE_IMPL_NAME} PRIVATE NetworkManagerPowerClient.cpp) - target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${NAMESPACE}Definitions::${NAMESPACE}Definitions) -endif() + Module.cpp + NetworkManagerPowerClient.cpp) if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_GNOME_GDBUS) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 2a735d57..3a2523b0 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -20,9 +20,6 @@ #include #include #include "NetworkManagerImplementation.h" -#ifdef ENABLE_POWERMANAGER -#include "NetworkManagerPowerClient.h" -#endif #if USE_TELEMETRY #include "NetworkManagerJsonEnum.h" @@ -76,9 +73,7 @@ namespace WPEFramework NetworkManagerImplementation::~NetworkManagerImplementation() { NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); -#ifdef ENABLE_POWERMANAGER _powerClient.reset(); -#endif connectivityMonitor.stopConnectivityMonitor(); _instance = nullptr; platform_deinit(); @@ -207,9 +202,7 @@ namespace WPEFramework NetworkManagerImplementation::platform_init(); /* change gnome networkmanager or netsrvmgr logg level */ NetworkManagerImplementation::platform_logging(static_cast (config.loglevel.Value())); -#ifdef ENABLE_POWERMANAGER _powerClient.reset(new NetworkManagerPowerClient(*this)); -#endif return(Core::ERROR_NONE); } @@ -1209,7 +1202,6 @@ namespace WPEFramework #endif } -#ifdef ENABLE_POWERMANAGER void NetworkManagerImplementation::OnPowerModePreChange( const Exchange::IPowerManager::PowerState currentState, const Exchange::IPowerManager::PowerState newState, @@ -1327,6 +1319,5 @@ namespace WPEFramework } } } -#endif // ENABLE_POWERMANAGER } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 47ddf0cb..406064ff 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -34,9 +34,7 @@ using namespace std; #include "NetworkManagerLogger.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" -#ifdef ENABLE_POWERMANAGER #include "NetworkManagerPowerClient.h" -#endif /* Forward declarations to avoid pulling GLib/libnm headers into this header */ typedef struct _NMClient NMClient; @@ -66,9 +64,7 @@ namespace WPEFramework namespace Plugin { class NetworkManagerImplementation : public Exchange::INetworkManager -#ifdef ENABLE_POWERMANAGER , public INetworkPowerCallback -#endif { enum NetworkEvents { @@ -232,10 +228,8 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; -#ifdef ENABLE_POWERMANAGER uint32_t EthernetDisconnect(void); uint32_t EthernetConnect(void); -#endif //ENABLE_POWERMANAGER uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; @@ -287,14 +281,12 @@ namespace WPEFramework void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); void logTelemetry(const std::string& eventName, const std::string& message); -#ifdef ENABLE_POWERMANAGER // INetworkPowerCallback overrides void OnPowerModePreChange(const Exchange::IPowerManager::PowerState currentState, const Exchange::IPowerManager::PowerState newState, std::function sendAck) override; void OnPowerModeChanged(const Exchange::IPowerManager::PowerState currentState, const Exchange::IPowerManager::PowerState newState) override; -#endif private: void platform_init(void); @@ -333,9 +325,7 @@ namespace WPEFramework std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; -#ifdef ENABLE_POWERMANAGER std::unique_ptr _powerClient; -#endif public: IPAddress m_ethIPv4Address; IPAddress m_wlanIPv4Address; diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index ab8e4e47..5ed9e403 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2024 RDK Management +* Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,6 @@ * limitations under the License. **/ -#ifdef ENABLE_POWERMANAGER - #include "NetworkManagerPowerClient.h" #include "NetworkManagerLogger.h" #include @@ -292,5 +290,3 @@ void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( } mClient.mQueueCv.notify_one(); } - -#endif // ENABLE_POWERMANAGER diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h index 14009200..216dd189 100644 --- a/plugin/NetworkManagerPowerClient.h +++ b/plugin/NetworkManagerPowerClient.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2024 RDK Management +* Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,8 +19,6 @@ #pragma once -#ifdef ENABLE_POWERMANAGER - #include "Module.h" #include #include @@ -180,5 +178,3 @@ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType Date: Thu, 21 May 2026 05:10:56 +0000 Subject: [PATCH 14/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: code cleanup Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 10 ------ plugin/NetworkManagerPowerClient.cpp | 41 ++++++++++++------------- plugin/NetworkManagerPowerClient.h | 13 +++----- 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 3a2523b0..93b50e85 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1208,21 +1208,11 @@ namespace WPEFramework std::function sendAck) { // Called from NetworkManagerPowerClient's power thread. - // Policy (standbyMode check, DeepSleep filter) has already been - // applied by the power thread before calling here. NMLOG_INFO("OnPowerModePreChange: current=%d new=%d", static_cast(currentState), static_cast(newState)); using PowerState = Exchange::IPowerManager::PowerState; - if (newState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && - currentState != PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) - { - NMLOG_INFO("OnPowerModePreChange: not entering or exiting DeepSleep, no action needed"); - sendAck(); - return; - } - if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { if (m_wlanEnabled.load() && m_wlanConnected.load()) diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 5ed9e403..907b2dae 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -53,16 +53,20 @@ NetworkManagerPowerClient::~NetworkManagerPowerClient() mPowerThread.join(); } Close(Core::infinite); - unregisterEventsAndDeactivate(); + unregisterEvents(); } bool NetworkManagerPowerClient::IsValid() const { + LOG_ENTRY_FUNCTION(); + return mPowerManager != nullptr; } bool NetworkManagerPowerClient::getNetworkStandbyMode() const { + LOG_ENTRY_FUNCTION(); + bool standbyMode = false; if (IsValid()) { if (auto r = mPowerManager->GetNetworkStandbyMode(standbyMode); r != Core::ERROR_NONE) { @@ -74,6 +78,8 @@ bool NetworkManagerPowerClient::getNetworkStandbyMode() const void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId) { + LOG_ENTRY_FUNCTION(); + if (IsValid()) { NMLOG_INFO("NetworkManagerPowerClient: sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); @@ -82,6 +88,8 @@ void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId void NetworkManagerPowerClient::sendDelayPowerModeChange(int transactionId, int seconds) { + LOG_ENTRY_FUNCTION(); + if (IsValid()) { if (auto r = mPowerManager->DelayPowerModeChangeBy(mClientId, transactionId, seconds); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: DelayPowerModeChangeBy failed (%u)", r); @@ -103,13 +111,13 @@ void NetworkManagerPowerClient::Operational(bool upAndRunning) } } else { // Stop the power-event thread before unregistering so any in-flight - // event that was already enqueued is drained with a fast ack. + // event that was already enqueued is drained. mStopThread = true; mQueueCv.notify_one(); if (mPowerThread.joinable()) { mPowerThread.join(); } - unregisterEventsAndDeactivate(); + unregisterEvents(); } } @@ -140,8 +148,7 @@ void NetworkManagerPowerClient::unregisterEvents() NMLOG_ERROR("NetworkManagerPowerClient: not in valid state, skipping event unregistration"); return; } - // NOTE: RemovePowerModePreChangeClient MUST be called before Unregister(IModePreChangeNotification) - // per the IPowerManager API contract. + // NOTE: RemovePowerModePreChangeClient MUST be called before Unregister if (auto r = mPowerManager->RemovePowerModePreChangeClient(mClientId); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: RemovePowerModePreChangeClient failed (%u)", r); } @@ -151,15 +158,9 @@ void NetworkManagerPowerClient::unregisterEvents() if (auto r = mPowerManager->Unregister(&mChangedNotification); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: Unregister(changed) failed (%u)", r); } -} -void NetworkManagerPowerClient::unregisterEventsAndDeactivate() -{ - if (IsValid()) { - unregisterEvents(); - mPowerManager->Release(); - mPowerManager = nullptr; - } + mPowerManager->Release(); + mPowerManager = nullptr; } // --------------------------------------------------------------------------- @@ -198,9 +199,11 @@ void NetworkManagerPowerClient::powerThreadLoop() } // Lock released — process event on this thread (blocking is fine here) + const bool toDeepSleep = (event.newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + if (event.type == PowerEvent::EventType::CHANGED) { // Wakeup notification — no ack required. - const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); if (fromDeepSleep && event.standbyMode) { NMLOG_INFO("NetworkManagerPowerClient: power thread — wakeup from DeepSleep standby ON"); mCallback.OnPowerModeChanged(event.currentState, event.newState); @@ -216,9 +219,6 @@ void NetworkManagerPowerClient::powerThreadLoop() sendPowerModePreChangeComplete(transactionId); }; - const bool toDeepSleep = (event.newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); - const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); - if ((toDeepSleep || fromDeepSleep) && !event.standbyMode) { // Deep-sleep transition with Network Standby OFF: delegate to // NetworkManagerImplementation (WiFiDisconnect / reconnect) which @@ -247,8 +247,7 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( NMLOG_INFO("NetworkManagerPowerClient::OnPowerModePreChange current=%d new=%d txId=%d after=%ds", static_cast(currentState), static_cast(newState), transactionId, stateChangeAfter); - // Query standby mode inline on the COM-RPC dispatcher thread — it is a - // COM-RPC call and must not be made from the power thread. + // Query standby mode const bool standbyMode = mClient.getNetworkStandbyMode(); // Cache for use by ChangedNotification @@ -260,7 +259,7 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( mClient.sendDelayPowerModeChange(transactionId, 5); } - // Enqueue and return immediately — the power thread does the real work. + // Enqueue and return immediately so the COM-RPC dispatcher thread is freed. { std::lock_guard lock(mClient.mQueueMutex); mClient.mEventQueue.push(PowerEvent{PowerEvent::EventType::PRE_CHANGE, @@ -279,7 +278,7 @@ void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( NMLOG_INFO("NetworkManagerPowerClient::OnPowerModeChanged current=%d new=%d", static_cast(currentState), static_cast(newState)); - // Use the standby mode cached + // Use the cached standby mode const bool standbyMode = mClient.mLastChangeStandbyMode; // Enqueue and return immediately so the COM-RPC dispatcher thread is freed. diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h index 216dd189..d9a53be3 100644 --- a/plugin/NetworkManagerPowerClient.h +++ b/plugin/NetworkManagerPowerClient.h @@ -58,9 +58,6 @@ struct INetworkPowerCallback { }; /** - * Thunder COMRPC client to the PowerManager plugin. - * - * Follows the same pattern as Mediarite's PowerManagerPluginClient: * - Inherits SmartInterfaceType for automatic * reconnect / Operational() lifecycle callbacks. * - Registers as an AddPowerModePreChangeClient so it participates @@ -72,7 +69,7 @@ struct INetworkPowerCallback { * Construction → Open() connects to PowerManager (async). * Operational(true) → registers events; IsValid() returns true. * Operational(false) → unregisters events and releases proxy. - * Destruction → Close() then unregisterEventsAndDeactivate(). + * Destruction → Close() then unregisterEvents(). */ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType { public: @@ -90,7 +87,7 @@ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType mStopThread{false}; - // Cached standby mode from the last PRE_CHANGE event. bool mLastChangeStandbyMode{false}; - - void powerThreadLoop(); }; } // namespace Plugin From 49a38c34a86709c0a6ac9c5d1eb6ce9253dc2a70 Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 21 May 2026 06:44:08 +0000 Subject: [PATCH 15/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: reapply wlan0 on wakeup from DeepSleep with NSM ON Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 3 + plugin/NetworkManagerImplementation.h | 1 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 8 ++ plugin/gnome/NetworkManagerGnomeWIFI.cpp | 110 ++++++++++++++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + 5 files changed, 123 insertions(+) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 93b50e85..a857c3d1 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1306,6 +1306,9 @@ namespace WPEFramework { NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); StartWiFiScan("", nullptr); + + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, toggling auto-route-ext-gw on wlan0"); + ReapplyWifiSettings(); } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 406064ff..a869edc3 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -230,6 +230,7 @@ namespace WPEFramework uint32_t WiFiDisconnect(void) override; uint32_t EthernetDisconnect(void); uint32_t EthernetConnect(void); + uint32_t ReapplyWifiSettings(void); uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 7984a1c2..539f39d9 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1163,6 +1163,14 @@ namespace WPEFramework return rc; } + uint32_t NetworkManagerImplementation::ReapplyWifiSettings(void) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->toggleAutoRouteExtGw(nmUtils::wlanIface())) + rc = Core::ERROR_NONE; + return rc; + } + uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index f918fb02..39364162 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -451,6 +451,116 @@ namespace WPEFramework return m_isSuccess; } + static void onUpdate2Done(GObject *src, GAsyncResult *res, gpointer user_data) + { + wifiManager *_wifiManager = static_cast(user_data); + GError *error = NULL; + nm_remote_connection_update2_finish(NM_REMOTE_CONNECTION(src), res, &error); + if (error) { + NMLOG_ERROR("toggleAutoRouteExtGw: update2 failed: %s", error->message); + g_error_free(error); + _wifiManager->m_isSuccess = false; + } else { + _wifiManager->m_isSuccess = true; + } + g_main_loop_quit(_wifiManager->m_loop); + NMLOG_INFO("toggleAutoRouteExtGw: update2 completed for '%s'", nm_connection_get_id(NM_CONNECTION(src))); + } + + static void onReapplyDone(GObject *src, GAsyncResult *res, gpointer user_data) + { + wifiManager *_wifiManager = static_cast(user_data); + GError *error = NULL; + nm_device_reapply_finish(NM_DEVICE(src), res, &error); + if (error) { + NMLOG_ERROR("toggleAutoRouteExtGw: reapply failed: %s", error->message); + g_error_free(error); + _wifiManager->m_isSuccess = false; + } else { + _wifiManager->m_isSuccess = true; + } + g_main_loop_quit(_wifiManager->m_loop); + NMLOG_INFO("toggleAutoRouteExtGw: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); + } + + bool wifiManager::toggleAutoRouteExtGw(const std::string& iface) + { + if(!createClientNewConnection()) + return false; + + NMDevice *device = nm_client_get_device_by_iface(m_client, iface.c_str()); + if (device == NULL) { + NMLOG_WARNING("toggleAutoRouteExtGw: device '%s' not found", iface.c_str()); + deleteClientConnection(); + return false; + } + + NMActiveConnection *activeConn = nm_device_get_active_connection(device); + if (activeConn == NULL) { + NMLOG_WARNING("toggleAutoRouteExtGw: no active connection on '%s'", iface.c_str()); + deleteClientConnection(); + return false; + } + + NMRemoteConnection *remoteConn = nm_active_connection_get_connection(activeConn); + if (remoteConn == NULL) { + NMLOG_WARNING("toggleAutoRouteExtGw: could not get connection profile for '%s'", iface.c_str()); + deleteClientConnection(); + return false; + } + + /* Clone locally to modify */ + NMConnection *conn = nm_simple_connection_new_clone(NM_CONNECTION(remoteConn)); + NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG( + nm_connection_get_setting(conn, NM_TYPE_SETTING_IP4_CONFIG)); + if (s_ip4 == NULL) { + NMLOG_WARNING("toggleAutoRouteExtGw: no IPv4 settings on '%s'", iface.c_str()); + g_object_unref(conn); + deleteClientConnection(); + return false; + } + + /* Read current value and toggle */ + NMTernary currentVal = NM_TERNARY_DEFAULT; + g_object_get(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, ¤tVal, NULL); + + NMTernary newVal = (currentVal == NM_TERNARY_DEFAULT) ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT; + NMLOG_INFO("toggleAutoRouteExtGw: '%s' auto-route-ext-gw %d -> %d", + iface.c_str(), static_cast(currentVal), static_cast(newVal)); + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, newVal, NULL); + + /* Save to disk */ + m_isSuccess = false; + nm_remote_connection_update2(remoteConn, + nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL), + NM_SETTINGS_UPDATE2_FLAG_TO_DISK, + NULL, m_cancellable, + onUpdate2Done, this); + wait(m_loop); + + if (!m_isSuccess) { + NMLOG_ERROR("toggleAutoRouteExtGw: failed to save connection for '%s'", iface.c_str()); + g_object_unref(conn); + deleteClientConnection(); + return false; + } + + /* Reapply to live connection */ + m_isSuccess = false; + nm_device_reapply_async(device, conn, 0, 0, m_cancellable, onReapplyDone, this); + wait(m_loop); + + if (!m_isSuccess) { + NMLOG_ERROR("toggleAutoRouteExtGw: reapply failed for '%s'", iface.c_str()); + } else { + NMLOG_INFO("toggleAutoRouteExtGw: reapply successful on '%s'", iface.c_str()); + } + + g_object_unref(conn); + deleteClientConnection(); + return m_isSuccess; + } + static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, Exchange::INetworkManager::WiFiConnectTo& ssidInfo) { NMAccessPoint *AccessPoint = nullptr; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 7feb4942..642da6ae 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -53,6 +53,7 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); bool ethernetDisconnect(); + bool toggleAutoRouteExtGw(const std::string& iface); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); From 400f9a3a13c0debbf69482f1550472029a83bc36 Mon Sep 17 00:00:00 2001 From: Anand Date: Fri, 22 May 2026 09:20:37 +0000 Subject: [PATCH 16/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: On wakeup from DeepSleep with Network Standby ON, request DHCP lease for both wlan0 and eth0. Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 44 +++++++++++++++-------- plugin/NetworkManagerImplementation.h | 6 ++-- plugin/gnome/NetworkManagerGnomeProxy.cpp | 10 +++--- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 41 +++++++++++---------- plugin/gnome/NetworkManagerGnomeWIFI.h | 4 +-- plugin/rdk/NetworkManagerRDKProxy.cpp | 21 +++++++++++ 6 files changed, 84 insertions(+), 42 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index a857c3d1..c1b58955 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1236,21 +1236,21 @@ namespace WPEFramework if (m_ethEnabled.load() && m_ethConnected.load()) { - NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting Ethernet"); + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — deactivating Ethernet"); - uint32_t rcEthDown = EthernetDisconnect(); + uint32_t rcEthDown = EthernetDeactivate(); if (rcEthDown == Core::ERROR_NONE) { m_ethDisconnectedForSleep.store(true); } else { - NMLOG_WARNING("OnPowerModePreChange: EthernetDisconnect failed (rc=%u), will not reconnect on wakeup", rcEthDown); + NMLOG_WARNING("OnPowerModePreChange: EthernetDeactivate failed (rc=%u), will not activate on wakeup", rcEthDown); } } else { - NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not connected, skipping disconnect"); + NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not activated, skipping deactivate"); } } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) @@ -1279,14 +1279,14 @@ namespace WPEFramework if (m_ethDisconnectedForSleep.load()) { m_ethDisconnectedForSleep.store(false); - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting Ethernet"); - uint32_t rcEthUp = EthernetConnect(); + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — activating Ethernet"); + uint32_t rcEthUp = EthernetActivate(); if (rcEthUp != Core::ERROR_NONE) - NMLOG_WARNING("OnPowerModePreChange: EthernetConnect failed (rc=%u)", rcEthUp); + NMLOG_WARNING("OnPowerModePreChange: EthernetActivate failed (rc=%u)", rcEthUp); } else { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — Ethernet was not connected or was already down before sleep, skipping reconnect"); + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — Ethernet was not activated or was already deactivated before sleep, skipping activate"); } } sendAck(); @@ -1299,16 +1299,32 @@ namespace WPEFramework NMLOG_INFO("OnPowerModeChanged: current=%d new=%d", static_cast(currentState), static_cast(newState)); if (currentState == Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP) { - // Waking from DeepSleep with Network Standby ON: the AP may have - // changed channel while the device slept (802.11 CSA). Trigger an - // active scan so the driver discovers the AP on its new channel. + if (m_wlanEnabled.load() && m_wlanConnected.load()) { + // Waking from DeepSleep with Network Standby ON: the AP may have + // changed channel while the device slept (802.11 CSA). Trigger an + // active scan so the driver discovers the AP on its new channel. NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); - StartWiFiScan("", nullptr); + if (StartWiFiScan("", nullptr) != Core::ERROR_NONE) + { + NMLOG_WARNING("OnPowerModeChanged: StartWiFiScan failed"); + } - NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, toggling auto-route-ext-gw on wlan0"); - ReapplyWifiSettings(); + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on wlan0"); + if (RequestDHCPLease("wlan0") != Core::ERROR_NONE) + { + NMLOG_WARNING("OnPowerModeChanged: RequestDHCPLease(wlan0) failed"); + } + } + + if (m_ethEnabled.load() && m_ethConnected.load()) + { + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on eth0"); + if (RequestDHCPLease("eth0") != Core::ERROR_NONE) + { + NMLOG_WARNING("OnPowerModeChanged: RequestDHCPLease(eth0) failed"); + } } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index a869edc3..ebdb71c2 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -228,9 +228,9 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; - uint32_t EthernetDisconnect(void); - uint32_t EthernetConnect(void); - uint32_t ReapplyWifiSettings(void); + uint32_t EthernetDeactivate(void); + uint32_t EthernetActivate(void); + uint32_t RequestDHCPLease(const string& iface); uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 539f39d9..43252fd8 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1147,15 +1147,15 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::EthernetDisconnect(void) + uint32_t NetworkManagerImplementation::EthernetDeactivate(void) { uint32_t rc = Core::ERROR_GENERAL; - if(wifi->ethernetDisconnect()) + if(wifi->ethernetDeactivate()) rc = Core::ERROR_NONE; return rc; } - uint32_t NetworkManagerImplementation::EthernetConnect(void) + uint32_t NetworkManagerImplementation::EthernetActivate(void) { uint32_t rc = Core::ERROR_GENERAL; if(wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1")) @@ -1163,10 +1163,10 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::ReapplyWifiSettings(void) + uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) { uint32_t rc = Core::ERROR_GENERAL; - if(wifi->toggleAutoRouteExtGw(nmUtils::wlanIface())) + if(wifi->requestDhcpLease(iface)) rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 39364162..931c692e 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -423,7 +423,7 @@ namespace WPEFramework return m_isSuccess; } - bool wifiManager::ethernetDisconnect() + bool wifiManager::ethernetDeactivate() { NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; if(!createClientNewConnection()) @@ -451,60 +451,65 @@ namespace WPEFramework return m_isSuccess; } - static void onUpdate2Done(GObject *src, GAsyncResult *res, gpointer user_data) + static void settingsSavedCb(GObject *src, GAsyncResult *res, gpointer user_data) { wifiManager *_wifiManager = static_cast(user_data); GError *error = NULL; nm_remote_connection_update2_finish(NM_REMOTE_CONNECTION(src), res, &error); if (error) { - NMLOG_ERROR("toggleAutoRouteExtGw: update2 failed: %s", error->message); + NMLOG_ERROR("requestDhcpLease: update2 failed: %s", error->message); g_error_free(error); _wifiManager->m_isSuccess = false; } else { _wifiManager->m_isSuccess = true; } g_main_loop_quit(_wifiManager->m_loop); - NMLOG_INFO("toggleAutoRouteExtGw: update2 completed for '%s'", nm_connection_get_id(NM_CONNECTION(src))); + NMLOG_DEBUG("requestDhcpLease: update2 completed for '%s'", nm_connection_get_id(NM_CONNECTION(src))); } - static void onReapplyDone(GObject *src, GAsyncResult *res, gpointer user_data) + static void reappliedCb(GObject *src, GAsyncResult *res, gpointer user_data) { wifiManager *_wifiManager = static_cast(user_data); GError *error = NULL; nm_device_reapply_finish(NM_DEVICE(src), res, &error); if (error) { - NMLOG_ERROR("toggleAutoRouteExtGw: reapply failed: %s", error->message); + NMLOG_ERROR("requestDhcpLease: reapply failed: %s", error->message); g_error_free(error); _wifiManager->m_isSuccess = false; } else { _wifiManager->m_isSuccess = true; } g_main_loop_quit(_wifiManager->m_loop); - NMLOG_INFO("toggleAutoRouteExtGw: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); + NMLOG_DEBUG("requestDhcpLease: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); } - bool wifiManager::toggleAutoRouteExtGw(const std::string& iface) + bool wifiManager::requestDhcpLease(const std::string& iface) { + /* There is no direct libnm API to trigger a DHCP renew on an active connection. + * As a workaround, we toggle the ipv4.auto-route-ext-gw property and call + * nm_device_reapply(). This causes NetworkManager to re-evaluate the IP + * configuration and send a new DHCP request for the same lease. + */ if(!createClientNewConnection()) return false; NMDevice *device = nm_client_get_device_by_iface(m_client, iface.c_str()); if (device == NULL) { - NMLOG_WARNING("toggleAutoRouteExtGw: device '%s' not found", iface.c_str()); + NMLOG_ERROR("requestDhcpLease: device '%s' not found", iface.c_str()); deleteClientConnection(); return false; } NMActiveConnection *activeConn = nm_device_get_active_connection(device); if (activeConn == NULL) { - NMLOG_WARNING("toggleAutoRouteExtGw: no active connection on '%s'", iface.c_str()); + NMLOG_ERROR("requestDhcpLease: no active connection on '%s'", iface.c_str()); deleteClientConnection(); return false; } NMRemoteConnection *remoteConn = nm_active_connection_get_connection(activeConn); if (remoteConn == NULL) { - NMLOG_WARNING("toggleAutoRouteExtGw: could not get connection profile for '%s'", iface.c_str()); + NMLOG_ERROR("requestDhcpLease: could not get connection profile for '%s'", iface.c_str()); deleteClientConnection(); return false; } @@ -514,7 +519,7 @@ namespace WPEFramework NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG( nm_connection_get_setting(conn, NM_TYPE_SETTING_IP4_CONFIG)); if (s_ip4 == NULL) { - NMLOG_WARNING("toggleAutoRouteExtGw: no IPv4 settings on '%s'", iface.c_str()); + NMLOG_ERROR("requestDhcpLease: no IPv4 settings on '%s'", iface.c_str()); g_object_unref(conn); deleteClientConnection(); return false; @@ -525,7 +530,7 @@ namespace WPEFramework g_object_get(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, ¤tVal, NULL); NMTernary newVal = (currentVal == NM_TERNARY_DEFAULT) ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT; - NMLOG_INFO("toggleAutoRouteExtGw: '%s' auto-route-ext-gw %d -> %d", + NMLOG_DEBUG("requestDhcpLease: '%s' auto-route-ext-gw %d -> %d", iface.c_str(), static_cast(currentVal), static_cast(newVal)); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, newVal, NULL); @@ -535,11 +540,11 @@ namespace WPEFramework nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL), NM_SETTINGS_UPDATE2_FLAG_TO_DISK, NULL, m_cancellable, - onUpdate2Done, this); + settingsSavedCb, this); wait(m_loop); if (!m_isSuccess) { - NMLOG_ERROR("toggleAutoRouteExtGw: failed to save connection for '%s'", iface.c_str()); + NMLOG_ERROR("requestDhcpLease: failed to save connection for '%s'", iface.c_str()); g_object_unref(conn); deleteClientConnection(); return false; @@ -547,13 +552,13 @@ namespace WPEFramework /* Reapply to live connection */ m_isSuccess = false; - nm_device_reapply_async(device, conn, 0, 0, m_cancellable, onReapplyDone, this); + nm_device_reapply_async(device, conn, 0, 0, m_cancellable, reappliedCb, this); wait(m_loop); if (!m_isSuccess) { - NMLOG_ERROR("toggleAutoRouteExtGw: reapply failed for '%s'", iface.c_str()); + NMLOG_ERROR("requestDhcpLease: reapply failed for '%s'", iface.c_str()); } else { - NMLOG_INFO("toggleAutoRouteExtGw: reapply successful on '%s'", iface.c_str()); + NMLOG_INFO("requestDhcpLease: reapply successful on '%s'", iface.c_str()); } g_object_unref(conn); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 642da6ae..54078329 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,8 +52,8 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); - bool ethernetDisconnect(); - bool toggleAutoRouteExtGw(const std::string& iface); + bool ethernetDeactivate(); + bool requestDhcpLease(const std::string& iface); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 0bbde194..65a32369 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1180,6 +1180,27 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } + uint32_t NetworkManagerImplementation::EthernetDeactivate(void) + { + /* No-op on RDK platform */ + NMLOG_INFO("EthernetDeactivate: no-op on RDK platform"); + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::EthernetActivate(void) + { + /* No-op on RDK platform */ + NMLOG_INFO("EthernetActivate: no-op on RDK platform"); + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) + { + /* No-op on RDK platform */ + NMLOG_INFO("RequestDHCPLease: no-op on RDK platform (iface=%s)", iface.c_str()); + return Core::ERROR_NONE; + } + uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) { LOG_ENTRY_FUNCTION(); From 7936e2f9eba6cb2b6707e9e50db9fde6b7064569 Mon Sep 17 00:00:00 2001 From: Anand Date: Mon, 25 May 2026 14:54:59 +0000 Subject: [PATCH 17/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: fix for ethernet activation on deepsleep wakeup with NSM OFF. Wait for carrier UP before activating Ethernet. Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 19 ++++++++++++++++--- plugin/gnome/NetworkManagerGnomeProxy.cpp | 18 ++++++++++++++---- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 18 ++++++++++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index c1b58955..48030927 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1223,6 +1223,7 @@ namespace WPEFramework if (rcWifiDown == Core::ERROR_NONE) { m_wlanDisconnectedForSleep.store(true); + m_wlanConnected.store(false); } else { @@ -1263,8 +1264,14 @@ namespace WPEFramework m_lastConnectedSSID.c_str()); m_wlanDisconnectedForSleep.store(false); uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); - if (rcWifiUp != Core::ERROR_NONE) + if (rcWifiUp == Core::ERROR_NONE) + { + m_wlanConnected.store(true); // Mark WiFi as connected. + } + else + { NMLOG_WARNING("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); + } } else { @@ -1278,11 +1285,17 @@ namespace WPEFramework if (m_ethDisconnectedForSleep.load()) { - m_ethDisconnectedForSleep.store(false); NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — activating Ethernet"); uint32_t rcEthUp = EthernetActivate(); - if (rcEthUp != Core::ERROR_NONE) + if (rcEthUp == Core::ERROR_NONE) + { + m_ethConnected.store(true); // Mark Ethernet as connected. + m_ethDisconnectedForSleep.store(false); + } + else + { NMLOG_WARNING("OnPowerModePreChange: EthernetActivate failed (rc=%u)", rcEthUp); + } } else { diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 43252fd8..6b400b84 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1157,10 +1157,20 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::EthernetActivate(void) { - uint32_t rc = Core::ERROR_GENERAL; - if(wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1")) - rc = Core::ERROR_NONE; - return rc; + const int maxProbes = 3; + for(int probe = 0; probe < maxProbes; ++probe) + { + NMDeviceState state = wifi->getEthDeviceState(); + if(state == NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_INFO("EthernetActivate: eth0 carrier ready, activating connection"); + return wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1") ? Core::ERROR_NONE : Core::ERROR_GENERAL; + } + NMLOG_WARNING("EthernetActivate: eth0 not ready (state %d), probe %d/%d", (int)state, probe + 1, maxProbes); + sleep(1); + } + NMLOG_ERROR("EthernetActivate: eth0 carrier not ready after %d probes, giving up", maxProbes); + return Core::ERROR_GENERAL; } uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 931c692e..8274af53 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -451,6 +451,24 @@ namespace WPEFramework return m_isSuccess; } + NMDeviceState wifiManager::getEthDeviceState() + { + if(!createClientNewConnection()) + return NM_DEVICE_STATE_UNKNOWN; + + NMDevice *ethDevice = nm_client_get_device_by_iface(m_client, nmUtils::ethIface()); + if(ethDevice == NULL) { + NMLOG_WARNING("ethernet device not found !"); + deleteClientConnection(); + return NM_DEVICE_STATE_UNKNOWN; + } + + NMDeviceState deviceState = nm_device_get_state(ethDevice); + NMLOG_DEBUG("ethernet device state is %d !", deviceState); + deleteClientConnection(); + return deviceState; + } + static void settingsSavedCb(GObject *src, GAsyncResult *res, gpointer user_data) { wifiManager *_wifiManager = static_cast(user_data); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 54078329..9756ca03 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -53,6 +53,7 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); bool ethernetDeactivate(); + NMDeviceState getEthDeviceState(); bool requestDhcpLease(const std::string& iface); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); From f35ea063e624f343f9fc4419ea0ffe307c3b0278 Mon Sep 17 00:00:00 2001 From: Anand Date: Tue, 26 May 2026 05:50:03 +0000 Subject: [PATCH 18/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: ensure EthernetDeactivate waits until disconnected Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 6b400b84..257ea952 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1151,13 +1151,33 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; if(wifi->ethernetDeactivate()) - rc = Core::ERROR_NONE; + { + /* ethernetDeactivate() returns as soon as NM accepts the disconnect + * request, but the device may still be in DEACTIVATING (110). + * Poll until the device settles to an idle state before returning, + * so sendAck() is not sent while NM is mid-teardown. */ + const int maxProbes = 5; + for(int probe = 0; probe < maxProbes; ++probe) + { + NMDeviceState state = wifi->getEthDeviceState(); + if(state <= NM_DEVICE_STATE_DISCONNECTED || state == NM_DEVICE_STATE_FAILED) + { + NMLOG_INFO("EthernetDeactivate: eth0 (state %d) after %d probe(s)", (int)state, probe + 1); + rc = Core::ERROR_NONE; + break; + } + NMLOG_WARNING("EthernetDeactivate: eth0 still deactivating (state %d), probe %d/%d", (int)state, probe + 1, maxProbes); + sleep(1); + } + if(rc != Core::ERROR_NONE) + NMLOG_ERROR("EthernetDeactivate: eth0 did not reach idle state after %d probes", maxProbes); + } return rc; } uint32_t NetworkManagerImplementation::EthernetActivate(void) { - const int maxProbes = 3; + const int maxProbes = 5; for(int probe = 0; probe < maxProbes; ++probe) { NMDeviceState state = wifi->getEthDeviceState(); From a8db4bda9bb20b1e19e3758d818192cbc56205ca Mon Sep 17 00:00:00 2001 From: Anand Date: Tue, 26 May 2026 08:14:47 +0000 Subject: [PATCH 19/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: reverted EthernetDeactivate waits until disconnected Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 257ea952..740db435 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1151,27 +1151,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; if(wifi->ethernetDeactivate()) - { - /* ethernetDeactivate() returns as soon as NM accepts the disconnect - * request, but the device may still be in DEACTIVATING (110). - * Poll until the device settles to an idle state before returning, - * so sendAck() is not sent while NM is mid-teardown. */ - const int maxProbes = 5; - for(int probe = 0; probe < maxProbes; ++probe) - { - NMDeviceState state = wifi->getEthDeviceState(); - if(state <= NM_DEVICE_STATE_DISCONNECTED || state == NM_DEVICE_STATE_FAILED) - { - NMLOG_INFO("EthernetDeactivate: eth0 (state %d) after %d probe(s)", (int)state, probe + 1); - rc = Core::ERROR_NONE; - break; - } - NMLOG_WARNING("EthernetDeactivate: eth0 still deactivating (state %d), probe %d/%d", (int)state, probe + 1, maxProbes); - sleep(1); - } - if(rc != Core::ERROR_NONE) - NMLOG_ERROR("EthernetDeactivate: eth0 did not reach idle state after %d probes", maxProbes); - } + rc = Core::ERROR_NONE; return rc; } From 312f095a02c639fc5fabee88040e28de3f089c86 Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 27 May 2026 09:45:48 +0000 Subject: [PATCH 20/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Added macro to enable pre-sleep Ethernet deactivation and on wake activation Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- CMakeLists.txt | 7 ++++ plugin/NetworkManagerImplementation.cpp | 24 +++----------- plugin/NetworkManagerImplementation.h | 5 ++- plugin/gnome/NetworkManagerGnomeProxy.cpp | 20 ++---------- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 39 ++++++++++++++++++++++- plugin/rdk/NetworkManagerRDKProxy.cpp | 9 ++---- 6 files changed, 57 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a04ad16b..fb1f67b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,13 @@ option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON) option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) option(USE_TELEMETRY "Enable Telemetry T2 support" OFF) +option(ENABLE_ETHERNET_CONNECTION_HANDLING + "Enable pre-sleep Ethernet deactivation and post-wake activation" OFF) + +if(ENABLE_ETHERNET_CONNECTION_HANDLING) + add_definitions(-DENABLE_ETHERNET_CONNECTION_HANDLING) + message(STATUS "Ethernet connection handling: enabled") +endif() if (USE_TELEMETRY) find_package(T2 REQUIRED) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 48030927..30d1cab9 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -54,7 +54,9 @@ namespace WPEFramework m_wlanConnected.store(false); m_ethEnabled.store(false); m_wlanEnabled.store(false); +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING m_ethDisconnectedForSleep.store(false); +#endif m_wlanDisconnectedForSleep.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ @@ -1234,7 +1236,7 @@ namespace WPEFramework { NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); } - +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING if (m_ethEnabled.load() && m_ethConnected.load()) { NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — deactivating Ethernet"); @@ -1253,6 +1255,7 @@ namespace WPEFramework { NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not activated, skipping deactivate"); } +#endif } else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { @@ -1282,25 +1285,6 @@ namespace WPEFramework { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — WiFi was not connected or was already down before sleep, skipping reconnect"); } - - if (m_ethDisconnectedForSleep.load()) - { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — activating Ethernet"); - uint32_t rcEthUp = EthernetActivate(); - if (rcEthUp == Core::ERROR_NONE) - { - m_ethConnected.store(true); // Mark Ethernet as connected. - m_ethDisconnectedForSleep.store(false); - } - else - { - NMLOG_WARNING("OnPowerModePreChange: EthernetActivate failed (rc=%u)", rcEthUp); - } - } - else - { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — Ethernet was not activated or was already deactivated before sleep, skipping activate"); - } } sendAck(); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index ebdb71c2..241e0261 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -228,8 +228,9 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING uint32_t EthernetDeactivate(void); - uint32_t EthernetActivate(void); +#endif uint32_t RequestDHCPLease(const string& iface); uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; @@ -336,7 +337,9 @@ namespace WPEFramework std::atomic m_wlanConnected; std::atomic m_ethEnabled; std::atomic m_wlanEnabled; +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING std::atomic m_ethDisconnectedForSleep; +#endif std::atomic m_wlanDisconnectedForSleep; std::string m_lastConnectedSSID; NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 740db435..6fbba768 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1147,6 +1147,7 @@ namespace WPEFramework return rc; } +#ifdef DENABLE_ETHERNET_CONNECTION_HANDLING uint32_t NetworkManagerImplementation::EthernetDeactivate(void) { uint32_t rc = Core::ERROR_GENERAL; @@ -1154,24 +1155,7 @@ namespace WPEFramework rc = Core::ERROR_NONE; return rc; } - - uint32_t NetworkManagerImplementation::EthernetActivate(void) - { - const int maxProbes = 5; - for(int probe = 0; probe < maxProbes; ++probe) - { - NMDeviceState state = wifi->getEthDeviceState(); - if(state == NM_DEVICE_STATE_DISCONNECTED) - { - NMLOG_INFO("EthernetActivate: eth0 carrier ready, activating connection"); - return wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1") ? Core::ERROR_NONE : Core::ERROR_GENERAL; - } - NMLOG_WARNING("EthernetActivate: eth0 not ready (state %d), probe %d/%d", (int)state, probe + 1, maxProbes); - sleep(1); - } - NMLOG_ERROR("EthernetActivate: eth0 carrier not ready after %d probes, giving up", maxProbes); - return Core::ERROR_GENERAL; - } +#endif uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) { diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 8274af53..dc564ce1 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -423,6 +423,35 @@ namespace WPEFramework return m_isSuccess; } +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING + static void ethernetDeactivateCb(GObject *object, GAsyncResult *result, gpointer user_data) + { + NMClient *client = NM_CLIENT(object); + GError *error = NULL; + wifiManager *_wifiManager = static_cast(user_data); + + NMLOG_DEBUG("ethernet connection deactivating..."); + _wifiManager->m_isSuccess = true; + if (!nm_client_deactivate_connection_finish(client, result, &error)) + { + NMLOG_ERROR("ethernet connection deactivate failed !"); + if(error != NULL) + { + if(g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + NMLOG_DEBUG("Deactivate operation was cancelled"); + } + else + { + NMLOG_ERROR("Deactivate error: %s", error->message); + } + g_error_free(error); + } + _wifiManager->m_isSuccess = false; + } + _wifiManager->quit(NULL); + } + bool wifiManager::ethernetDeactivate() { NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; @@ -445,11 +474,19 @@ namespace WPEFramework return true; } - nm_device_disconnect_async(ethDevice, m_cancellable, disconnectCb, this); + NMActiveConnection *activeConn = nm_device_get_active_connection(ethDevice); + if(activeConn == NULL) { + NMLOG_WARNING("ethernet has no active connection, nothing to deactivate !"); + deleteClientConnection(); + return true; + } + + nm_client_deactivate_connection_async(m_client, activeConn, m_cancellable, ethernetDeactivateCb, this); wait(m_loop); deleteClientConnection(); return m_isSuccess; } +#endif NMDeviceState wifiManager::getEthDeviceState() { diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 65a32369..a809d3af 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1180,19 +1180,14 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING uint32_t NetworkManagerImplementation::EthernetDeactivate(void) { /* No-op on RDK platform */ NMLOG_INFO("EthernetDeactivate: no-op on RDK platform"); return Core::ERROR_NONE; } - - uint32_t NetworkManagerImplementation::EthernetActivate(void) - { - /* No-op on RDK platform */ - NMLOG_INFO("EthernetActivate: no-op on RDK platform"); - return Core::ERROR_NONE; - } +#endif uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) { From 6983a700416de5f95e3957ec35346bde2def7a45 Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 27 May 2026 10:40:35 +0000 Subject: [PATCH 21/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Addressed copilot review comments. Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 6 ++--- plugin/NetworkManagerImplementation.h | 3 ++- plugin/NetworkManagerPowerClient.cpp | 30 ++++++++++++++++------- plugin/gnome/NetworkManagerGnomeProxy.cpp | 2 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 2 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 4 +-- 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 30d1cab9..60c6a28e 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -75,7 +75,7 @@ namespace WPEFramework NetworkManagerImplementation::~NetworkManagerImplementation() { NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); - _powerClient.reset(); + m_powerClient.reset(); connectivityMonitor.stopConnectivityMonitor(); _instance = nullptr; platform_deinit(); @@ -204,7 +204,7 @@ namespace WPEFramework NetworkManagerImplementation::platform_init(); /* change gnome networkmanager or netsrvmgr logg level */ NetworkManagerImplementation::platform_logging(static_cast (config.loglevel.Value())); - _powerClient.reset(new NetworkManagerPowerClient(*this)); + m_powerClient.reset(new NetworkManagerPowerClient(*this)); return(Core::ERROR_NONE); } @@ -1295,7 +1295,7 @@ namespace WPEFramework { NMLOG_INFO("OnPowerModeChanged: current=%d new=%d", static_cast(currentState), static_cast(newState)); - if (currentState == Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP) { + if (currentState == Exchange::IPowerManager::PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { if (m_wlanEnabled.load() && m_wlanConnected.load()) { diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 241e0261..b6a3000a 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -27,6 +27,7 @@ #include #include #include +#include using namespace std; @@ -327,7 +328,7 @@ namespace WPEFramework std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; - std::unique_ptr _powerClient; + std::unique_ptr m_powerClient; public: IPAddress m_ethIPv4Address; IPAddress m_wlanIPv4Address; diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 907b2dae..05a6fab2 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -81,6 +81,10 @@ void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId LOG_ENTRY_FUNCTION(); if (IsValid()) { + if (mClientId == 0) { + NMLOG_ERROR("NetworkManagerPowerClient: sendPowerModePreChangeComplete called with invalid clientId=0, skipping"); + return; + } NMLOG_INFO("NetworkManagerPowerClient: sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); } @@ -91,6 +95,10 @@ void NetworkManagerPowerClient::sendDelayPowerModeChange(int transactionId, int LOG_ENTRY_FUNCTION(); if (IsValid()) { + if (mClientId == 0) { + NMLOG_ERROR("NetworkManagerPowerClient: sendDelayPowerModeChange called with invalid clientId=0, skipping"); + return; + } if (auto r = mPowerManager->DelayPowerModeChangeBy(mClientId, transactionId, seconds); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: DelayPowerModeChangeBy failed (%u)", r); } @@ -129,12 +137,13 @@ void NetworkManagerPowerClient::registerEvents() return; } if (auto r = mPowerManager->AddPowerModePreChangeClient("org.rdk.NetworkManager", mClientId); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: AddPowerModePreChangeClient failed (%u)", r); + NMLOG_ERROR("NetworkManagerPowerClient: AddPowerModePreChangeClient failed (%u) — skipping pre-change sink", r); + // mClientId stays 0; do NOT register mPreChangeNotification } else { NMLOG_INFO("NetworkManagerPowerClient: registered as pre-change client, mClientId=%u", mClientId); - } - if (auto r = mPowerManager->Register(&mPreChangeNotification); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: Register(preChange) failed (%u)", r); + if (auto r2 = mPowerManager->Register(&mPreChangeNotification); r2 != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: Register(preChange) failed (%u)", r2); + } } if (auto r = mPowerManager->Register(&mChangedNotification); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: Register(changed) failed (%u)", r); @@ -149,11 +158,14 @@ void NetworkManagerPowerClient::unregisterEvents() return; } // NOTE: RemovePowerModePreChangeClient MUST be called before Unregister - if (auto r = mPowerManager->RemovePowerModePreChangeClient(mClientId); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: RemovePowerModePreChangeClient failed (%u)", r); - } - if (auto r = mPowerManager->Unregister(&mPreChangeNotification); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: Unregister(preChange) failed (%u)", r); + if (mClientId != 0) { + if (auto r = mPowerManager->RemovePowerModePreChangeClient(mClientId); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: RemovePowerModePreChangeClient failed (%u)", r); + } + if (auto r = mPowerManager->Unregister(&mPreChangeNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("NetworkManagerPowerClient: Unregister(preChange) failed (%u)", r); + } + mClientId = 0; } if (auto r = mPowerManager->Unregister(&mChangedNotification); r != Core::ERROR_NONE) { NMLOG_ERROR("NetworkManagerPowerClient: Unregister(changed) failed (%u)", r); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 6fbba768..afbe4dda 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1147,7 +1147,7 @@ namespace WPEFramework return rc; } -#ifdef DENABLE_ETHERNET_CONNECTION_HANDLING +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING uint32_t NetworkManagerImplementation::EthernetDeactivate(void) { uint32_t rc = Core::ERROR_GENERAL; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index dc564ce1..1a04acf8 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -462,7 +462,7 @@ namespace WPEFramework if(ethDevice == NULL) { NMLOG_WARNING("ethernet device not found !"); deleteClientConnection(); - return true; + return false; } deviceState = nm_device_get_state(ethDevice); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index a809d3af..03337980 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1185,7 +1185,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { /* No-op on RDK platform */ NMLOG_INFO("EthernetDeactivate: no-op on RDK platform"); - return Core::ERROR_NONE; + return Core::ERROR_UNAVAILABLE; } #endif @@ -1193,7 +1193,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { /* No-op on RDK platform */ NMLOG_INFO("RequestDHCPLease: no-op on RDK platform (iface=%s)", iface.c_str()); - return Core::ERROR_NONE; + return Core::ERROR_UNAVAILABLE; } uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) From 336477573ab9f7af97d569c68d4ce885d5c35a70 Mon Sep 17 00:00:00 2001 From: Anand Date: Wed, 27 May 2026 14:43:51 +0000 Subject: [PATCH 22/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Addressed copilot review comments. Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 3 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 39 +++++++++--------------- plugin/gnome/NetworkManagerGnomeWIFI.h | 3 +- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 60c6a28e..1c4676e2 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1314,7 +1314,7 @@ namespace WPEFramework NMLOG_WARNING("OnPowerModeChanged: RequestDHCPLease(wlan0) failed"); } } - +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING if (m_ethEnabled.load() && m_ethConnected.load()) { NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on eth0"); @@ -1323,6 +1323,7 @@ namespace WPEFramework NMLOG_WARNING("OnPowerModeChanged: RequestDHCPLease(eth0) failed"); } } +#endif } } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 1a04acf8..414139b2 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -68,6 +68,8 @@ namespace WPEFramework NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); g_error_free(error); } + g_clear_object(&m_client); + m_client = nullptr; g_main_context_pop_thread_default(m_nmContext); m_opMutex.unlock(); return false; @@ -90,7 +92,7 @@ namespace WPEFramework NMLOG_DEBUG("Cancelling pending async operations"); g_cancellable_cancel(m_cancellable); g_clear_object(&m_cancellable); - m_cancellable = NULL; + m_cancellable = nullptr; } } @@ -104,18 +106,19 @@ namespace WPEFramework g_main_context_iteration(context, TRUE); } g_main_context_unref(context); - m_client = NULL; + m_client = nullptr; } if(m_objectPath) { NMLOG_DEBUG("Freeing object path"); g_free(m_objectPath); - m_objectPath = NULL; + m_objectPath = nullptr; } // Pop the context pushed in createClientNewConnection() - g_main_context_pop_thread_default(m_nmContext); + if (m_nmContext) + g_main_context_pop_thread_default(m_nmContext); // Release operation lock acquired in createClientNewConnection() m_opMutex.unlock(); } @@ -488,24 +491,6 @@ namespace WPEFramework } #endif - NMDeviceState wifiManager::getEthDeviceState() - { - if(!createClientNewConnection()) - return NM_DEVICE_STATE_UNKNOWN; - - NMDevice *ethDevice = nm_client_get_device_by_iface(m_client, nmUtils::ethIface()); - if(ethDevice == NULL) { - NMLOG_WARNING("ethernet device not found !"); - deleteClientConnection(); - return NM_DEVICE_STATE_UNKNOWN; - } - - NMDeviceState deviceState = nm_device_get_state(ethDevice); - NMLOG_DEBUG("ethernet device state is %d !", deviceState); - deleteClientConnection(); - return deviceState; - } - static void settingsSavedCb(GObject *src, GAsyncResult *res, gpointer user_data) { wifiManager *_wifiManager = static_cast(user_data); @@ -518,7 +503,8 @@ namespace WPEFramework } else { _wifiManager->m_isSuccess = true; } - g_main_loop_quit(_wifiManager->m_loop); + if (_wifiManager->m_loop) + g_main_loop_quit(_wifiManager->m_loop); NMLOG_DEBUG("requestDhcpLease: update2 completed for '%s'", nm_connection_get_id(NM_CONNECTION(src))); } @@ -534,7 +520,8 @@ namespace WPEFramework } else { _wifiManager->m_isSuccess = true; } - g_main_loop_quit(_wifiManager->m_loop); + if (_wifiManager->m_loop) + g_main_loop_quit(_wifiManager->m_loop); NMLOG_DEBUG("requestDhcpLease: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); } @@ -591,11 +578,13 @@ namespace WPEFramework /* Save to disk */ m_isSuccess = false; + GVariant *connSettings = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); nm_remote_connection_update2(remoteConn, - nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL), + connSettings, NM_SETTINGS_UPDATE2_FLAG_TO_DISK, NULL, m_cancellable, settingsSavedCb, this); + g_variant_unref(connSettings); wait(m_loop); if (!m_isSuccess) { diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 9756ca03..2195bffd 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,8 +52,9 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING bool ethernetDeactivate(); - NMDeviceState getEthDeviceState(); +#endif bool requestDhcpLease(const std::string& iface); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); From 40a8d16bb9dec123286eeb8351bebfdfd5b6a4ba Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 28 May 2026 08:16:38 +0000 Subject: [PATCH 23/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: fix for reacquireDHCPLease -> use applied connection in-memory instead of cloning stored profile and writing to disk. Test procedure: Change the PowerMode and verify the log Risks: low Priority: P1 Signed-off-by: Anand N --- CMakeLists.txt | 2 +- plugin/CMakeLists.txt | 4 +- plugin/NetworkManagerImplementation.cpp | 14 ++-- plugin/NetworkManagerImplementation.h | 6 +- plugin/NetworkManagerPowerClient.cpp | 2 +- plugin/NetworkManagerPowerClient.h | 2 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 6 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 88 +++++++++-------------- plugin/gnome/NetworkManagerGnomeWIFI.h | 14 ++-- plugin/rdk/NetworkManagerRDKProxy.cpp | 6 +- 10 files changed, 55 insertions(+), 89 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb1f67b4..9638b12c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) option(USE_TELEMETRY "Enable Telemetry T2 support" OFF) option(ENABLE_ETHERNET_CONNECTION_HANDLING - "Enable pre-sleep Ethernet deactivation and post-wake activation" OFF) + "Enable pre-sleep Ethernet deactivation" OFF) if(ENABLE_ETHERNET_CONNECTION_HANDLING) add_definitions(-DENABLE_ETHERNET_CONNECTION_HANDLING) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index c211d894..6090b8f1 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -81,8 +81,8 @@ add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp NetworkManagerLogger.cpp - Module.cpp - NetworkManagerPowerClient.cpp) + NetworkManagerPowerClient.cpp + Module.cpp) if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_GNOME_GDBUS) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 1c4676e2..29c14f68 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -54,9 +54,7 @@ namespace WPEFramework m_wlanConnected.store(false); m_ethEnabled.store(false); m_wlanEnabled.store(false); -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING m_ethDisconnectedForSleep.store(false); -#endif m_wlanDisconnectedForSleep.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ @@ -1265,10 +1263,10 @@ namespace WPEFramework { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", m_lastConnectedSSID.c_str()); - m_wlanDisconnectedForSleep.store(false); uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); if (rcWifiUp == Core::ERROR_NONE) { + m_wlanDisconnectedForSleep.store(false); m_wlanConnected.store(true); // Mark WiFi as connected. } else @@ -1309,21 +1307,19 @@ namespace WPEFramework } NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on wlan0"); - if (RequestDHCPLease("wlan0") != Core::ERROR_NONE) + if (ReacquireDHCPLease("wlan0") != Core::ERROR_NONE) { - NMLOG_WARNING("OnPowerModeChanged: RequestDHCPLease(wlan0) failed"); + NMLOG_WARNING("OnPowerModeChanged: ReacquireDHCPLease(wlan0) failed"); } } -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING if (m_ethEnabled.load() && m_ethConnected.load()) { NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on eth0"); - if (RequestDHCPLease("eth0") != Core::ERROR_NONE) + if (ReacquireDHCPLease("eth0") != Core::ERROR_NONE) { - NMLOG_WARNING("OnPowerModeChanged: RequestDHCPLease(eth0) failed"); + NMLOG_WARNING("OnPowerModeChanged: ReacquireDHCPLease(eth0) failed"); } } -#endif } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index b6a3000a..bff75ba7 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -229,10 +229,8 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING uint32_t EthernetDeactivate(void); -#endif - uint32_t RequestDHCPLease(const string& iface); + uint32_t ReacquireDHCPLease(const string& iface); uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; @@ -338,9 +336,7 @@ namespace WPEFramework std::atomic m_wlanConnected; std::atomic m_ethEnabled; std::atomic m_wlanEnabled; -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING std::atomic m_ethDisconnectedForSleep; -#endif std::atomic m_wlanDisconnectedForSleep; std::string m_lastConnectedSSID; NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 05a6fab2..d95e5dce 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -52,8 +52,8 @@ NetworkManagerPowerClient::~NetworkManagerPowerClient() if (mPowerThread.joinable()) { mPowerThread.join(); } - Close(Core::infinite); unregisterEvents(); + Close(Core::infinite); } bool NetworkManagerPowerClient::IsValid() const diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h index d9a53be3..4d3d2408 100644 --- a/plugin/NetworkManagerPowerClient.h +++ b/plugin/NetworkManagerPowerClient.h @@ -168,7 +168,7 @@ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType mStopThread{false}; // Cached standby mode from the last PRE_CHANGE event. - bool mLastChangeStandbyMode{false}; + std::atomic mLastChangeStandbyMode{false}; }; } // namespace Plugin diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index afbe4dda..c376ed1d 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1147,7 +1147,6 @@ namespace WPEFramework return rc; } -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING uint32_t NetworkManagerImplementation::EthernetDeactivate(void) { uint32_t rc = Core::ERROR_GENERAL; @@ -1155,12 +1154,11 @@ namespace WPEFramework rc = Core::ERROR_NONE; return rc; } -#endif - uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) + uint32_t NetworkManagerImplementation::ReacquireDHCPLease(const string& iface) { uint32_t rc = Core::ERROR_GENERAL; - if(wifi->requestDhcpLease(iface)) + if(wifi->reacquireDhcpLease(iface)) rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 414139b2..01a676d3 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -426,7 +426,6 @@ namespace WPEFramework return m_isSuccess; } -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING static void ethernetDeactivateCb(GObject *object, GAsyncResult *result, gpointer user_data) { NMClient *client = NM_CLIENT(object); @@ -489,23 +488,26 @@ namespace WPEFramework deleteClientConnection(); return m_isSuccess; } -#endif - static void settingsSavedCb(GObject *src, GAsyncResult *res, gpointer user_data) + static void appliedConnCb(GObject *src, GAsyncResult *res, gpointer user_data) { wifiManager *_wifiManager = static_cast(user_data); GError *error = NULL; - nm_remote_connection_update2_finish(NM_REMOTE_CONNECTION(src), res, &error); + guint64 versionId = 0; + NMConnection *conn = nm_device_get_applied_connection_finish( + NM_DEVICE(src), res, &versionId, &error); if (error) { - NMLOG_ERROR("requestDhcpLease: update2 failed: %s", error->message); + NMLOG_ERROR("reacquireDhcpLease: get_applied_connection failed: %s", error->message); g_error_free(error); + _wifiManager->m_appliedConn = nullptr; _wifiManager->m_isSuccess = false; } else { + _wifiManager->m_appliedConn = conn; + _wifiManager->m_versionId = versionId; _wifiManager->m_isSuccess = true; } if (_wifiManager->m_loop) g_main_loop_quit(_wifiManager->m_loop); - NMLOG_DEBUG("requestDhcpLease: update2 completed for '%s'", nm_connection_get_id(NM_CONNECTION(src))); } static void reappliedCb(GObject *src, GAsyncResult *res, gpointer user_data) @@ -514,7 +516,7 @@ namespace WPEFramework GError *error = NULL; nm_device_reapply_finish(NM_DEVICE(src), res, &error); if (error) { - NMLOG_ERROR("requestDhcpLease: reapply failed: %s", error->message); + NMLOG_ERROR("reacquireDhcpLease: reapply failed: %s", error->message); g_error_free(error); _wifiManager->m_isSuccess = false; } else { @@ -522,90 +524,66 @@ namespace WPEFramework } if (_wifiManager->m_loop) g_main_loop_quit(_wifiManager->m_loop); - NMLOG_DEBUG("requestDhcpLease: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); + NMLOG_DEBUG("reacquireDhcpLease: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); } - bool wifiManager::requestDhcpLease(const std::string& iface) + bool wifiManager::reacquireDhcpLease(const std::string& iface) { - /* There is no direct libnm API to trigger a DHCP renew on an active connection. - * As a workaround, we toggle the ipv4.auto-route-ext-gw property and call - * nm_device_reapply(). This causes NetworkManager to re-evaluate the IP - * configuration and send a new DHCP request for the same lease. - */ + /* No direct libnm API to trigger a DHCP renew, hence by toggling ipv4.auto-route-ext-gw on the + * APPLIED connection (not the stored profile) and calling reapply(). + */ if(!createClientNewConnection()) return false; NMDevice *device = nm_client_get_device_by_iface(m_client, iface.c_str()); if (device == NULL) { - NMLOG_ERROR("requestDhcpLease: device '%s' not found", iface.c_str()); + NMLOG_ERROR("reacquireDhcpLease: device '%s' not found", iface.c_str()); deleteClientConnection(); return false; } - NMActiveConnection *activeConn = nm_device_get_active_connection(device); - if (activeConn == NULL) { - NMLOG_ERROR("requestDhcpLease: no active connection on '%s'", iface.c_str()); - deleteClientConnection(); - return false; - } + /* Round 1: fetch what NM actually has applied in memory */ + m_isSuccess = false; + m_appliedConn = nullptr; + nm_device_get_applied_connection_async(device, 0, m_cancellable, appliedConnCb, this); + wait(m_loop); - NMRemoteConnection *remoteConn = nm_active_connection_get_connection(activeConn); - if (remoteConn == NULL) { - NMLOG_ERROR("requestDhcpLease: could not get connection profile for '%s'", iface.c_str()); + if (!m_isSuccess || m_appliedConn == nullptr) { + NMLOG_ERROR("reacquireDhcpLease: could not get applied connection for '%s'", iface.c_str()); deleteClientConnection(); return false; } - /* Clone locally to modify */ - NMConnection *conn = nm_simple_connection_new_clone(NM_CONNECTION(remoteConn)); NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG( - nm_connection_get_setting(conn, NM_TYPE_SETTING_IP4_CONFIG)); + nm_connection_get_setting(m_appliedConn, NM_TYPE_SETTING_IP4_CONFIG)); if (s_ip4 == NULL) { - NMLOG_ERROR("requestDhcpLease: no IPv4 settings on '%s'", iface.c_str()); - g_object_unref(conn); + NMLOG_ERROR("reacquireDhcpLease: no IPv4 settings on '%s'", iface.c_str()); + g_object_unref(m_appliedConn); + m_appliedConn = nullptr; deleteClientConnection(); return false; } - /* Read current value and toggle */ NMTernary currentVal = NM_TERNARY_DEFAULT; g_object_get(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, ¤tVal, NULL); - NMTernary newVal = (currentVal == NM_TERNARY_DEFAULT) ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT; - NMLOG_DEBUG("requestDhcpLease: '%s' auto-route-ext-gw %d -> %d", + NMLOG_DEBUG("reacquireDhcpLease: '%s' auto-route-ext-gw %d -> %d (in-memory only)", iface.c_str(), static_cast(currentVal), static_cast(newVal)); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, newVal, NULL); - /* Save to disk */ - m_isSuccess = false; - GVariant *connSettings = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - nm_remote_connection_update2(remoteConn, - connSettings, - NM_SETTINGS_UPDATE2_FLAG_TO_DISK, - NULL, m_cancellable, - settingsSavedCb, this); - g_variant_unref(connSettings); - wait(m_loop); - - if (!m_isSuccess) { - NMLOG_ERROR("requestDhcpLease: failed to save connection for '%s'", iface.c_str()); - g_object_unref(conn); - deleteClientConnection(); - return false; - } - - /* Reapply to live connection */ + /* Round 2: reapply with version_id for race safety — no disk write */ m_isSuccess = false; - nm_device_reapply_async(device, conn, 0, 0, m_cancellable, reappliedCb, this); + nm_device_reapply_async(device, m_appliedConn, m_versionId, 0, m_cancellable, reappliedCb, this); wait(m_loop); if (!m_isSuccess) { - NMLOG_ERROR("requestDhcpLease: reapply failed for '%s'", iface.c_str()); + NMLOG_ERROR("reacquireDhcpLease: reapply failed for '%s'", iface.c_str()); } else { - NMLOG_INFO("requestDhcpLease: reapply successful on '%s'", iface.c_str()); + NMLOG_INFO("reacquireDhcpLease: reapply successful on '%s'", iface.c_str()); } - g_object_unref(conn); + g_object_unref(m_appliedConn); + m_appliedConn = nullptr; deleteClientConnection(); return m_isSuccess; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 2195bffd..cfc741fb 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,10 +52,8 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING bool ethernetDeactivate(); -#endif - bool requestDhcpLease(const std::string& iface); + bool reacquireDhcpLease(const std::string& iface); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); @@ -80,14 +78,14 @@ namespace WPEFramework wifiManager(); ~wifiManager() { NMLOG_INFO("~wifiManager"); + if(m_client != NULL) { + deleteClientConnection(); // handles pop + } if (m_nmContext) { - g_main_context_pop_thread_default(m_nmContext); + // Do NOT pop here — deleteClientConnection already popped g_main_context_unref(m_nmContext); m_nmContext = NULL; } - if(m_client != NULL) { - deleteClientConnection(); - } if(m_loop != NULL) { g_main_loop_unref(m_loop); m_loop = NULL; @@ -113,6 +111,8 @@ namespace WPEFramework std::mutex m_cancellableMutex; std::mutex m_opMutex; // serializes concurrent wifi operations from different threads bool m_isSuccess = false; + NMConnection *m_appliedConn = nullptr; + guint64 m_versionId = 0; SecretAgent m_secretAgent; }; } // Plugin diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 03337980..b163ae3c 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1180,19 +1180,17 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } -#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING uint32_t NetworkManagerImplementation::EthernetDeactivate(void) { /* No-op on RDK platform */ NMLOG_INFO("EthernetDeactivate: no-op on RDK platform"); return Core::ERROR_UNAVAILABLE; } -#endif - uint32_t NetworkManagerImplementation::RequestDHCPLease(const string& iface) + uint32_t NetworkManagerImplementation::ReacquireDHCPLease(const string& iface) { /* No-op on RDK platform */ - NMLOG_INFO("RequestDHCPLease: no-op on RDK platform (iface=%s)", iface.c_str()); + NMLOG_INFO("ReacquireDHCPLease: no-op on RDK platform (iface=%s)", iface.c_str()); return Core::ERROR_UNAVAILABLE; } From 95697c24b409f9b44818cb799ea5ddf44bfd05dd Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 28 May 2026 14:35:45 +0000 Subject: [PATCH 24/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: fix workflow failures. Test procedure: Check workflow run. Risks: low Priority: P1 Signed-off-by: Anand N --- .github/workflows/gdbus_proxy_L1_test.yml | 5 ++ .github/workflows/legacy_L1_L2_test.yml | 5 ++ .github/workflows/libnm_proxy_L1_test.yml | 43 ++++++----- .github/workflows/rdk_proxy_L1_L2_test.yml | 5 ++ plugin/NetworkManagerImplementation.cpp | 2 +- tests/l2Test/libnm/CMakeLists.txt | 1 + tests/l2Test/rdk/CMakeLists.txt | 1 + tests/mocks/NetworkManagerPowerClient.cpp | 69 ++++++++++++++++++ tests/mocks/thunder/IPowerManager.h | 85 ++++++++++++++++++++++ 9 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 tests/mocks/NetworkManagerPowerClient.cpp create mode 100644 tests/mocks/thunder/IPowerManager.h diff --git a/.github/workflows/gdbus_proxy_L1_test.yml b/.github/workflows/gdbus_proxy_L1_test.yml index 242ca6bd..16edc038 100644 --- a/.github/workflows/gdbus_proxy_L1_test.yml +++ b/.github/workflows/gdbus_proxy_L1_test.yml @@ -107,6 +107,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Build networkmanager with Gnome GDBUS Proxy run: > cmake diff --git a/.github/workflows/legacy_L1_L2_test.yml b/.github/workflows/legacy_L1_L2_test.yml index b3645cce..03538a0a 100644 --- a/.github/workflows/legacy_L1_L2_test.yml +++ b/.github/workflows/legacy_L1_L2_test.yml @@ -110,6 +110,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index 80d945d5..e04036f0 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -12,7 +12,7 @@ env: jobs: L1-tests: name: Build and run unit tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: # Set up Thunder cache @@ -21,24 +21,24 @@ jobs: uses: actions/cache@v3 with: path: | - build/Thunder - build/ThunderInterfaces - build/ThunderTools - install - !install/etc/WPEFramework/plugins - !install/usr/bin/libnmproxy_l1_test - !install/usr/include/gmock - !install/usr/include/gtest - !install/usr/lib/libgmockd.a - !install/usr/lib/libgmock_maind.a - !install/usr/lib/libgtestd.a - !install/usr/lib/libgtest_maind.a - !install/usr/lib/cmake/GTest - !install/usr/lib/pkgconfig/gmock.pc - !install/usr/lib/pkgconfig/gmock_main.pc - !install/usr/lib/pkgconfig/gtest.pc - !install/usr/lib/pkgconfig/gtest_main.pc - !install/usr/lib/wpeframework/plugins + # build/Thunder + # build/ThunderInterfaces + # build/ThunderTools + # install + # !install/etc/WPEFramework/plugins + # !install/usr/bin/libnmproxy_l1_test + # !install/usr/include/gmock + # !install/usr/include/gtest + # !install/usr/lib/libgmockd.a + # !install/usr/lib/libgmock_maind.a + # !install/usr/lib/libgtestd.a + # !install/usr/lib/libgtest_maind.a + # !install/usr/lib/cmake/GTest + # !install/usr/lib/pkgconfig/gmock.pc + # !install/usr/lib/pkgconfig/gmock_main.pc + # !install/usr/lib/pkgconfig/gtest.pc + # !install/usr/lib/pkgconfig/gtest_main.pc + # !install/usr/lib/wpeframework/plugins key: thunder-${{ env.THUNDER_REF }}-libnm - name: Install packages run: | @@ -107,6 +107,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Generate dependency files run: | sudo bash -c 'echo "ETHERNET_INTERFACE=eth0 diff --git a/.github/workflows/rdk_proxy_L1_L2_test.yml b/.github/workflows/rdk_proxy_L1_L2_test.yml index 4fb464fe..fc89bc38 100644 --- a/.github/workflows/rdk_proxy_L1_L2_test.yml +++ b/.github/workflows/rdk_proxy_L1_L2_test.yml @@ -107,6 +107,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 29c14f68..117e21a2 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1301,7 +1301,7 @@ namespace WPEFramework // changed channel while the device slept (802.11 CSA). Trigger an // active scan so the driver discovers the AP on its new channel. NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); - if (StartWiFiScan("", nullptr) != Core::ERROR_NONE) + if (StartWiFiScan(nullptr, nullptr) != Core::ERROR_NONE) { NMLOG_WARNING("OnPowerModeChanged: StartWiFiScan failed"); } diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 092cc1d3..9a76f977 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -31,6 +31,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/LibnmWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/GLibWraps.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index ed5d4fab..6744355b 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -32,6 +32,7 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp diff --git a/tests/mocks/NetworkManagerPowerClient.cpp b/tests/mocks/NetworkManagerPowerClient.cpp new file mode 100644 index 00000000..ed81a2cb --- /dev/null +++ b/tests/mocks/NetworkManagerPowerClient.cpp @@ -0,0 +1,69 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +/** + * Stub implementation of NetworkManagerPowerClient for unit/L2 test builds. + * + * The real implementation requires WPEFramework COM-RPC infrastructure + * (SmartInterfaceType::Open/Close) which is not exercised in test builds. + * This stub satisfies the linker while keeping the test binary free of + * live COM connections. + */ + +#include "NetworkManagerPowerClient.h" + +namespace WPEFramework { +namespace Plugin { + +NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& callback) + : mCallback(callback) + , mPreChangeNotification(*this) + , mChangedNotification(*this) +{ +} + +NetworkManagerPowerClient::~NetworkManagerPowerClient() +{ +} + +bool NetworkManagerPowerClient::IsValid() const { return false; } + +bool NetworkManagerPowerClient::getNetworkStandbyMode() const { return false; } + +void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int /* transactionId */) {} + +void NetworkManagerPowerClient::sendDelayPowerModeChange(int /* transactionId */, int /* seconds */) {} + +void NetworkManagerPowerClient::Operational(bool /* upAndRunning */) {} + +void NetworkManagerPowerClient::registerEvents() {} + +void NetworkManagerPowerClient::unregisterEvents() {} + +void NetworkManagerPowerClient::powerThreadLoop() {} + +void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( + const PowerState /* currentState */, const PowerState /* newState */, + const int /* transactionId */, const int /* stateChangeAfter */) {} + +void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( + const PowerState /* currentState */, const PowerState /* newState */) {} + +} // namespace Plugin +} // namespace WPEFramework diff --git a/tests/mocks/thunder/IPowerManager.h b/tests/mocks/thunder/IPowerManager.h new file mode 100644 index 00000000..2131f879 --- /dev/null +++ b/tests/mocks/thunder/IPowerManager.h @@ -0,0 +1,85 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +/** + * Minimal CI stub for IPowerManager — compatible with Thunder R4.4.3. + * + * This file is used only during CI builds (gdbus/libnm L1 proxy tests) where + * the full entservices-apis stack is not available. It defines exactly the + * surface consumed by NetworkManagerPowerClient and nothing more. + * + * DO NOT use this file outside of test/CI contexts. + */ + +#include + +namespace WPEFramework { +namespace Exchange { + + struct EXTERNAL IPowerManager : virtual public Core::IUnknown { + + // Stub ID — not used for COM lookup in L1 unit tests. + enum { ID = 0x8180 }; + + enum PowerState : uint8_t { + POWER_STATE_UNKNOWN = 0, + POWER_STATE_OFF = 1, + POWER_STATE_STANDBY = 2, + POWER_STATE_ON = 3, + POWER_STATE_STANDBY_LIGHT_SLEEP = 4, + POWER_STATE_STANDBY_DEEP_SLEEP = 5, + }; + + // @event + struct EXTERNAL IModePreChangeNotification : virtual public Core::IUnknown { + enum { ID = 0x8182 }; + virtual void OnPowerModePreChange(const PowerState currentState, + const PowerState newState, + const int transactionId, + const int stateChangeAfter) {} + }; + + // @event + struct EXTERNAL IModeChangedNotification : virtual public Core::IUnknown { + enum { ID = 0x8183 }; + virtual void OnPowerModeChanged(const PowerState currentState, + const PowerState newState) {} + }; + + virtual Core::hresult Register(IModePreChangeNotification* notification) = 0; + virtual Core::hresult Unregister(const IModePreChangeNotification* notification) = 0; + + virtual Core::hresult Register(IModeChangedNotification* notification) = 0; + virtual Core::hresult Unregister(const IModeChangedNotification* notification) = 0; + + virtual Core::hresult AddPowerModePreChangeClient(const string& clientName, + uint32_t& clientId) = 0; + virtual Core::hresult RemovePowerModePreChangeClient(const uint32_t clientId) = 0; + virtual Core::hresult PowerModePreChangeComplete(const uint32_t clientId, + const int transactionId) = 0; + virtual Core::hresult DelayPowerModeChangeBy(const uint32_t clientId, + const int transactionId, + const int delayPeriod) = 0; + virtual Core::hresult GetNetworkStandbyMode(bool& standbyMode) = 0; + }; + +} // namespace Exchange +} // namespace WPEFramework From 51b6661052a914749cd58e79807b254876a49002 Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 28 May 2026 17:41:06 +0000 Subject: [PATCH 25/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: modified log levels Test procedure: change power state and check logs Risks: low Priority: P1 Signed-off-by: Anand N --- .github/workflows/libnm_proxy_L1_test.yml | 37 +++++++-------- plugin/NetworkManagerImplementation.cpp | 20 ++++---- plugin/NetworkManagerPowerClient.cpp | 56 +++++++++++------------ 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index e04036f0..c225aa36 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -12,6 +12,7 @@ env: jobs: L1-tests: name: Build and run unit tests + # Note: Ubuntu 24.04 is required for libnm 1.46 which is needed for NetworkManagerPowerClient support runs-on: ubuntu-24.04 steps: @@ -21,24 +22,24 @@ jobs: uses: actions/cache@v3 with: path: | - # build/Thunder - # build/ThunderInterfaces - # build/ThunderTools - # install - # !install/etc/WPEFramework/plugins - # !install/usr/bin/libnmproxy_l1_test - # !install/usr/include/gmock - # !install/usr/include/gtest - # !install/usr/lib/libgmockd.a - # !install/usr/lib/libgmock_maind.a - # !install/usr/lib/libgtestd.a - # !install/usr/lib/libgtest_maind.a - # !install/usr/lib/cmake/GTest - # !install/usr/lib/pkgconfig/gmock.pc - # !install/usr/lib/pkgconfig/gmock_main.pc - # !install/usr/lib/pkgconfig/gtest.pc - # !install/usr/lib/pkgconfig/gtest_main.pc - # !install/usr/lib/wpeframework/plugins + build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/bin/libnmproxy_l1_test + !install/usr/include/gmock + !install/usr/include/gtest + !install/usr/lib/libgmockd.a + !install/usr/lib/libgmock_maind.a + !install/usr/lib/libgtestd.a + !install/usr/lib/libgtest_maind.a + !install/usr/lib/cmake/GTest + !install/usr/lib/pkgconfig/gmock.pc + !install/usr/lib/pkgconfig/gmock_main.pc + !install/usr/lib/pkgconfig/gtest.pc + !install/usr/lib/pkgconfig/gtest_main.pc + !install/usr/lib/wpeframework/plugins key: thunder-${{ env.THUNDER_REF }}-libnm - name: Install packages run: | diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 117e21a2..65bf08cc 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1208,7 +1208,7 @@ namespace WPEFramework std::function sendAck) { // Called from NetworkManagerPowerClient's power thread. - NMLOG_INFO("OnPowerModePreChange: current=%d new=%d", + NMLOG_DEBUG("OnPowerModePreChange: current=%d new=%d", static_cast(currentState), static_cast(newState)); using PowerState = Exchange::IPowerManager::PowerState; @@ -1227,12 +1227,12 @@ namespace WPEFramework } else { - NMLOG_WARNING("OnPowerModePreChange: WiFiDisconnect failed (rc=%u), will not reconnect on wakeup", rcWifiDown); + NMLOG_ERROR("OnPowerModePreChange: WiFiDisconnect failed (rc=%u), will not reconnect on wakeup", rcWifiDown); } } else { - NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); + NMLOG_DEBUG("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); } #ifdef ENABLE_ETHERNET_CONNECTION_HANDLING if (m_ethEnabled.load() && m_ethConnected.load()) @@ -1246,12 +1246,12 @@ namespace WPEFramework } else { - NMLOG_WARNING("OnPowerModePreChange: EthernetDeactivate failed (rc=%u), will not activate on wakeup", rcEthDown); + NMLOG_ERROR("OnPowerModePreChange: EthernetDeactivate failed (rc=%u), will not activate on wakeup", rcEthDown); } } else { - NMLOG_WARNING("OnPowerModePreChange: going to DeepSleep — Ethernet not activated, skipping deactivate"); + NMLOG_DEBUG("OnPowerModePreChange: going to DeepSleep — Ethernet not activated, skipping deactivate"); } #endif } @@ -1271,12 +1271,12 @@ namespace WPEFramework } else { - NMLOG_WARNING("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); + NMLOG_ERROR("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); } } else { - NMLOG_WARNING("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); } } else @@ -1303,13 +1303,13 @@ namespace WPEFramework NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); if (StartWiFiScan(nullptr, nullptr) != Core::ERROR_NONE) { - NMLOG_WARNING("OnPowerModeChanged: StartWiFiScan failed"); + NMLOG_ERROR("OnPowerModeChanged: StartWiFiScan failed"); } NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on wlan0"); if (ReacquireDHCPLease("wlan0") != Core::ERROR_NONE) { - NMLOG_WARNING("OnPowerModeChanged: ReacquireDHCPLease(wlan0) failed"); + NMLOG_ERROR("OnPowerModeChanged: ReacquireDHCPLease(wlan0) failed"); } } if (m_ethEnabled.load() && m_ethConnected.load()) @@ -1317,7 +1317,7 @@ namespace WPEFramework NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on eth0"); if (ReacquireDHCPLease("eth0") != Core::ERROR_NONE) { - NMLOG_WARNING("OnPowerModeChanged: ReacquireDHCPLease(eth0) failed"); + NMLOG_ERROR("OnPowerModeChanged: ReacquireDHCPLease(eth0) failed"); } } } diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index d95e5dce..3d6d2ed9 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -34,17 +34,17 @@ NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& call , mPreChangeNotification(*this) , mChangedNotification(*this) { - NMLOG_INFO("NetworkManagerPowerClient: connecting to PowerManager"); + NMLOG_INFO("connecting to PowerManager"); if (auto r = Open(RPC::CommunicationTimeOut, Connector(), "org.rdk.PowerManager"); r == Core::ERROR_NONE) { // Connected; Operational() will be called by the framework when the proxy is ready } else { - NMLOG_ERROR("NetworkManagerPowerClient: failed to open link to PowerManager (error %u)", r); + NMLOG_ERROR("failed to open link to PowerManager (error %u)", r); } } NetworkManagerPowerClient::~NetworkManagerPowerClient() { - NMLOG_INFO("NetworkManagerPowerClient: shutting down"); + NMLOG_INFO("shutting down"); // Stop the power-event thread first so any in-flight work completes // before we release the COM-RPC proxy. mStopThread = true; @@ -70,7 +70,7 @@ bool NetworkManagerPowerClient::getNetworkStandbyMode() const bool standbyMode = false; if (IsValid()) { if (auto r = mPowerManager->GetNetworkStandbyMode(standbyMode); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: GetNetworkStandbyMode failed (%u)", r); + NMLOG_ERROR("GetNetworkStandbyMode failed (%u)", r); } } return standbyMode; @@ -82,10 +82,10 @@ void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId if (IsValid()) { if (mClientId == 0) { - NMLOG_ERROR("NetworkManagerPowerClient: sendPowerModePreChangeComplete called with invalid clientId=0, skipping"); + NMLOG_ERROR("sendPowerModePreChangeComplete called with invalid clientId=0, skipping"); return; } - NMLOG_INFO("NetworkManagerPowerClient: sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); + NMLOG_DEBUG("sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); } } @@ -96,18 +96,18 @@ void NetworkManagerPowerClient::sendDelayPowerModeChange(int transactionId, int if (IsValid()) { if (mClientId == 0) { - NMLOG_ERROR("NetworkManagerPowerClient: sendDelayPowerModeChange called with invalid clientId=0, skipping"); + NMLOG_ERROR("sendDelayPowerModeChange called with invalid clientId=0, skipping"); return; } if (auto r = mPowerManager->DelayPowerModeChangeBy(mClientId, transactionId, seconds); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: DelayPowerModeChangeBy failed (%u)", r); + NMLOG_ERROR("DelayPowerModeChangeBy failed (%u)", r); } } } void NetworkManagerPowerClient::Operational(bool upAndRunning) { - NMLOG_INFO("NetworkManagerPowerClient::Operational(%s)", upAndRunning ? "true" : "false"); + NMLOG_DEBUG("Operational(%s)", upAndRunning ? "true" : "false"); if (upAndRunning) { if (!IsValid()) { mPowerManager = Interface(); @@ -131,44 +131,44 @@ void NetworkManagerPowerClient::Operational(bool upAndRunning) void NetworkManagerPowerClient::registerEvents() { - NMLOG_INFO("NetworkManagerPowerClient: registering events"); + NMLOG_DEBUG("registering events"); if (!IsValid()) { - NMLOG_ERROR("NetworkManagerPowerClient: not in valid state, skipping event registration"); + NMLOG_ERROR("not in valid state, skipping event registration"); return; } if (auto r = mPowerManager->AddPowerModePreChangeClient("org.rdk.NetworkManager", mClientId); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: AddPowerModePreChangeClient failed (%u) — skipping pre-change sink", r); + NMLOG_ERROR("AddPowerModePreChangeClient failed (%u) — skipping pre-change sink", r); // mClientId stays 0; do NOT register mPreChangeNotification } else { - NMLOG_INFO("NetworkManagerPowerClient: registered as pre-change client, mClientId=%u", mClientId); + NMLOG_INFO("registered as pre-change client, mClientId=%u", mClientId); if (auto r2 = mPowerManager->Register(&mPreChangeNotification); r2 != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: Register(preChange) failed (%u)", r2); + NMLOG_ERROR("register(preChange) failed (%u)", r2); } } if (auto r = mPowerManager->Register(&mChangedNotification); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: Register(changed) failed (%u)", r); + NMLOG_ERROR("register(changed) failed (%u)", r); } } void NetworkManagerPowerClient::unregisterEvents() { - NMLOG_INFO("NetworkManagerPowerClient: unregistering events"); + NMLOG_DEBUG("unregistering events"); if (!IsValid()) { - NMLOG_ERROR("NetworkManagerPowerClient: not in valid state, skipping event unregistration"); + NMLOG_ERROR("not in valid state, skipping event unregistration"); return; } // NOTE: RemovePowerModePreChangeClient MUST be called before Unregister if (mClientId != 0) { if (auto r = mPowerManager->RemovePowerModePreChangeClient(mClientId); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: RemovePowerModePreChangeClient failed (%u)", r); + NMLOG_ERROR("removePowerModePreChangeClient failed (%u)", r); } if (auto r = mPowerManager->Unregister(&mPreChangeNotification); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: Unregister(preChange) failed (%u)", r); + NMLOG_ERROR("unregister(preChange) failed (%u)", r); } mClientId = 0; } if (auto r = mPowerManager->Unregister(&mChangedNotification); r != Core::ERROR_NONE) { - NMLOG_ERROR("NetworkManagerPowerClient: Unregister(changed) failed (%u)", r); + NMLOG_ERROR("unregister(changed) failed (%u)", r); } mPowerManager->Release(); @@ -181,7 +181,7 @@ void NetworkManagerPowerClient::unregisterEvents() void NetworkManagerPowerClient::powerThreadLoop() { - NMLOG_INFO("NetworkManagerPowerClient: power event thread started"); + NMLOG_DEBUG("power event thread started"); while (true) { PowerEvent event{}; { @@ -217,10 +217,10 @@ void NetworkManagerPowerClient::powerThreadLoop() if (event.type == PowerEvent::EventType::CHANGED) { // Wakeup notification — no ack required. if (fromDeepSleep && event.standbyMode) { - NMLOG_INFO("NetworkManagerPowerClient: power thread — wakeup from DeepSleep standby ON"); + NMLOG_INFO("power thread — wakeup from DeepSleep standby ON"); mCallback.OnPowerModeChanged(event.currentState, event.newState); } else { - NMLOG_INFO("NetworkManagerPowerClient: power thread — CHANGED event, no action (fromDeepSleep=%d standbyMode=%d)", + NMLOG_DEBUG("power thread — CHANGED event, no action (fromDeepSleep=%d networkStandbyMode=%d)", fromDeepSleep, event.standbyMode); } continue; @@ -235,17 +235,17 @@ void NetworkManagerPowerClient::powerThreadLoop() // Deep-sleep transition with Network Standby OFF: delegate to // NetworkManagerImplementation (WiFiDisconnect / reconnect) which // will call sendAck() when done. - NMLOG_INFO("NetworkManagerPowerClient: power thread — %s DeepSleep standby OFF", + NMLOG_INFO("power thread — %s DeepSleep standby OFF", toDeepSleep ? "to" : "from"); mCallback.OnPowerModePreChange(event.currentState, event.newState, sendAck); } else { // standby ON or non-DeepSleep: no WiFi action needed, ack immediately. - NMLOG_INFO("NetworkManagerPowerClient: power thread — fast-path ack (standbyMode=%d toDeepSleep=%d fromDeepSleep=%d)", + NMLOG_DEBUG("power thread ack (standbyMode=%d toDeepSleep=%d fromDeepSleep=%d)", event.standbyMode, toDeepSleep, fromDeepSleep); sendAck(); } } - NMLOG_INFO("NetworkManagerPowerClient: power event thread stopped"); + NMLOG_INFO("power event thread stopped"); } // --------------------------------------------------------------------------- @@ -256,7 +256,7 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( const PowerState currentState, const PowerState newState, const int transactionId, const int stateChangeAfter) { - NMLOG_INFO("NetworkManagerPowerClient::OnPowerModePreChange current=%d new=%d txId=%d after=%ds", + NMLOG_DEBUG("OnPowerModePreChange current=%d new=%d txId=%d after=%ds", static_cast(currentState), static_cast(newState), transactionId, stateChangeAfter); // Query standby mode @@ -287,7 +287,7 @@ void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( const PowerState currentState, const PowerState newState) { - NMLOG_INFO("NetworkManagerPowerClient::OnPowerModeChanged current=%d new=%d", + NMLOG_DEBUG("OnPowerModeChanged current=%d new=%d", static_cast(currentState), static_cast(newState)); // Use the cached standby mode From f649b91a3e5516375c3e62d5bb2bca877660d5dd Mon Sep 17 00:00:00 2001 From: Anand Date: Thu, 28 May 2026 18:40:25 +0000 Subject: [PATCH 26/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: removed mock for NetworkManagerPowerClient.cpp Test procedure: change power state and check logs Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerPowerClient.h | 2 +- tests/l2Test/libnm/CMakeLists.txt | 1 - tests/l2Test/rdk/CMakeLists.txt | 1 - tests/mocks/NetworkManagerPowerClient.cpp | 69 ----------------------- tests/mocks/thunder/IPowerManager.h | 18 +++--- 5 files changed, 10 insertions(+), 81 deletions(-) delete mode 100644 tests/mocks/NetworkManagerPowerClient.cpp diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h index 4d3d2408..73949e0e 100644 --- a/plugin/NetworkManagerPowerClient.h +++ b/plugin/NetworkManagerPowerClient.h @@ -69,7 +69,7 @@ struct INetworkPowerCallback { * Construction → Open() connects to PowerManager (async). * Operational(true) → registers events; IsValid() returns true. * Operational(false) → unregisters events and releases proxy. - * Destruction → Close() then unregisterEvents(). + * Destruction → unregisterEvents() then Close() . */ class NetworkManagerPowerClient : protected RPC::SmartInterfaceType { public: diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 9a76f977..092cc1d3 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -31,7 +31,6 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/LibnmWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/GLibWraps.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index 6744355b..ed5d4fab 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -32,7 +32,6 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp diff --git a/tests/mocks/NetworkManagerPowerClient.cpp b/tests/mocks/NetworkManagerPowerClient.cpp deleted file mode 100644 index ed81a2cb..00000000 --- a/tests/mocks/NetworkManagerPowerClient.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2026 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -/** - * Stub implementation of NetworkManagerPowerClient for unit/L2 test builds. - * - * The real implementation requires WPEFramework COM-RPC infrastructure - * (SmartInterfaceType::Open/Close) which is not exercised in test builds. - * This stub satisfies the linker while keeping the test binary free of - * live COM connections. - */ - -#include "NetworkManagerPowerClient.h" - -namespace WPEFramework { -namespace Plugin { - -NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& callback) - : mCallback(callback) - , mPreChangeNotification(*this) - , mChangedNotification(*this) -{ -} - -NetworkManagerPowerClient::~NetworkManagerPowerClient() -{ -} - -bool NetworkManagerPowerClient::IsValid() const { return false; } - -bool NetworkManagerPowerClient::getNetworkStandbyMode() const { return false; } - -void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int /* transactionId */) {} - -void NetworkManagerPowerClient::sendDelayPowerModeChange(int /* transactionId */, int /* seconds */) {} - -void NetworkManagerPowerClient::Operational(bool /* upAndRunning */) {} - -void NetworkManagerPowerClient::registerEvents() {} - -void NetworkManagerPowerClient::unregisterEvents() {} - -void NetworkManagerPowerClient::powerThreadLoop() {} - -void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( - const PowerState /* currentState */, const PowerState /* newState */, - const int /* transactionId */, const int /* stateChangeAfter */) {} - -void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( - const PowerState /* currentState */, const PowerState /* newState */) {} - -} // namespace Plugin -} // namespace WPEFramework diff --git a/tests/mocks/thunder/IPowerManager.h b/tests/mocks/thunder/IPowerManager.h index 2131f879..30c1d4d7 100644 --- a/tests/mocks/thunder/IPowerManager.h +++ b/tests/mocks/thunder/IPowerManager.h @@ -64,21 +64,21 @@ namespace Exchange { const PowerState newState) {} }; - virtual Core::hresult Register(IModePreChangeNotification* notification) = 0; - virtual Core::hresult Unregister(const IModePreChangeNotification* notification) = 0; + virtual Core::hresult Register(IModePreChangeNotification* notification) {}; + virtual Core::hresult Unregister(const IModePreChangeNotification* notification) {}; - virtual Core::hresult Register(IModeChangedNotification* notification) = 0; - virtual Core::hresult Unregister(const IModeChangedNotification* notification) = 0; + virtual Core::hresult Register(IModeChangedNotification* notification) {}; + virtual Core::hresult Unregister(const IModeChangedNotification* notification) {}; virtual Core::hresult AddPowerModePreChangeClient(const string& clientName, - uint32_t& clientId) = 0; - virtual Core::hresult RemovePowerModePreChangeClient(const uint32_t clientId) = 0; + uint32_t& clientId) {}; + virtual Core::hresult RemovePowerModePreChangeClient(const uint32_t clientId) {}; virtual Core::hresult PowerModePreChangeComplete(const uint32_t clientId, - const int transactionId) = 0; + const int transactionId) {}; virtual Core::hresult DelayPowerModeChangeBy(const uint32_t clientId, const int transactionId, - const int delayPeriod) = 0; - virtual Core::hresult GetNetworkStandbyMode(bool& standbyMode) = 0; + const int delayPeriod) {}; + virtual Core::hresult GetNetworkStandbyMode(bool& standbyMode) {}; }; } // namespace Exchange From 9bd0963081b9bac3d86a67a946ff0f7779b28286 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 28 May 2026 15:25:55 -0400 Subject: [PATCH 27/29] Include NetworkManagerPowerClient.cpp to the builds Include NetworkManagerPowerClient.cpp to the builds --- tests/l2Test/libnm/CMakeLists.txt | 1 + tests/l2Test/rdk/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 092cc1d3..9b1a44d0 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeProxy.cpp ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeWIFI.cpp ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeEvents.cpp diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index ed5d4fab..3a94c63d 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -38,6 +38,7 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp ${PROXY_STUB_SOURCES} ) From 13d5b8af6a4149b8eac8152c5ed4bce4bfe9154a Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 28 May 2026 15:52:57 -0400 Subject: [PATCH 28/29] updated to not to include external files updated to not to include external files --- .github/workflows/libnm_proxy_L1_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index 008d553f..87002e6d 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -166,7 +166,7 @@ jobs: - name: Generate coverage run: | - lcov -c -o coverage.info -d build/networkmanager_libnm/ + lcov --no-external --rc geninfo_unexecuted_blocks=1 -c -o coverage.info -d build/networkmanager_libnm/ lcov -e coverage.info '*/networkmanager/plugin/gnome/*' -o filtered_coverage.info - name: Generate the html report From 3aada97a86a72cfc3273f1609ba25cfda4afd688 Mon Sep 17 00:00:00 2001 From: Anand Date: Fri, 29 May 2026 02:18:44 +0000 Subject: [PATCH 29/29] RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: fix for libnm_proxy work flow Test procedure: check github workflow Risks: low Priority: P1 Signed-off-by: Anand N --- .github/workflows/libnm_proxy_L1_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index 87002e6d..e5f64def 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -166,7 +166,7 @@ jobs: - name: Generate coverage run: | - lcov --no-external --rc geninfo_unexecuted_blocks=1 -c -o coverage.info -d build/networkmanager_libnm/ + lcov --rc geninfo_unexecuted_blocks=1 -c -o coverage.info -d build/networkmanager_libnm/ --ignore-errors mismatch lcov -e coverage.info '*/networkmanager/plugin/gnome/*' -o filtered_coverage.info - name: Generate the html report