diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp index 1f3816a7ba9cb0..81098bf93ce3e4 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -263,6 +264,10 @@ CHIP_ERROR writeFabricsIntoFabricsListAttribute() err = CHIP_ERROR_PERSISTED_STORAGE_FAILED; } + // Currently, we only manage FabricsList attribute in endpoint 0, OperationalCredentials cluster is always required to be on + // EP0. + MatterReportingAttributeChangeCallback(0, OperationalCredentials::Id, OperationalCredentials::Attributes::FabricsList::Id); + return err; } @@ -785,6 +790,11 @@ bool emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( gFabricBeingCommissioned.Reset(); emberAfPrintln(EMBER_AF_PRINT_DEBUG, "OpCreds: Failed AddTrustedRootCert request."); } + else + { + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id, + OperationalCredentials::Attributes::TrustedRootCertificates::Id); + } return true; } @@ -795,5 +805,9 @@ bool emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( { EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; emberAfSendImmediateDefaultResponse(status); + + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id, + OperationalCredentials::Attributes::TrustedRootCertificates::Id); + return true; } diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index f5562d151c72a1..60fe2ebd76dbb5 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -334,8 +334,14 @@ void Engine::Run(System::Layer * aSystemLayer, void * apAppState) CHIP_ERROR Engine::ScheduleRun() { + if (mRunScheduled) + { + return CHIP_NO_ERROR; + } + if (InteractionModelEngine::GetInstance()->GetExchangeManager() != nullptr) { + mRunScheduled = true; return InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->ScheduleWork(Run, this); } @@ -352,6 +358,8 @@ void Engine::Run() InteractionModelEngine * imEngine = InteractionModelEngine::GetInstance(); ReadHandler * readHandler = imEngine->mReadHandlers + mCurReadHandlerIdx; + mRunScheduled = false; + while ((mNumReportsInFlight < CHIP_IM_MAX_REPORTS_IN_FLIGHT) && (numReadHandled < CHIP_IM_MAX_NUM_READ_HANDLER)) { if (readHandler->IsReportable()) diff --git a/src/app/reporting/Engine.h b/src/app/reporting/Engine.h index bcd6547c81a330..b5e87e57e617c7 100644 --- a/src/app/reporting/Engine.h +++ b/src/app/reporting/Engine.h @@ -121,6 +121,13 @@ class Engine */ bool mMoreChunkedMessages = false; + /** + * Boolean to indicate if ScheduleRun is pending. This flag is used to prevent calling ScheduleRun multiple times + * within the same execution context to avoid applying too much pressure on platforms that use small, fixed size event queues. + * + */ + bool mRunScheduled = false; + /** * The number of report date request in flight * diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 3d7d6e4d368cd4..7501d96b4ba0f4 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -504,4 +504,9 @@ void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clust info.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info); + + // Schedule work to run asynchronously on the CHIP thread. The scheduled work won't execute until the current execution context + // has completed. This ensures that we can 'gather up' multiple attribute changes that have occurred in the same execution + // context without requiring any explicit 'start' or 'end' change calls into the engine to book-end the change. + InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); }