Matter SDK Coverage Report
Current view: top level - app/reporting - ReportSchedulerImpl.cpp (source / functions) Coverage Total Hit
Test: SHA:e98a48c2e59f85a25417956e1d105721433aa5d1 Lines: 96.9 % 64 62
Test Date: 2026-01-09 16:53:50 Functions: 92.3 % 13 12

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2023 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #include <app/AppConfig.h>
      19              : #include <app/InteractionModelEngine.h>
      20              : #include <app/reporting/ReportSchedulerImpl.h>
      21              : 
      22              : namespace chip {
      23              : namespace app {
      24              : namespace reporting {
      25              : 
      26              : using namespace System::Clock;
      27              : using ReadHandlerNode = ReportScheduler::ReadHandlerNode;
      28              : 
      29              : /// @brief Callback called when the report timer expires to schedule an engine run regardless of the state of the ReadHandlers, as
      30              : /// the engine already verifies that read handlers are reportable before sending a report
      31          116 : void ReportSchedulerImpl::ReportTimerCallback()
      32              : {
      33          116 :     TEMPORARY_RETURN_IGNORED InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
      34          116 : }
      35              : 
      36           66 : ReportSchedulerImpl::ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : ReportScheduler(aTimerDelegate)
      37              : {
      38           66 :     VerifyOrDie(nullptr != mTimerDelegate);
      39           66 : }
      40              : 
      41              : /// @brief Method that triggers a report emission on each ReadHandler that is not blocked on its min interval.
      42              : ///        Each read handler that is not blocked is immediately marked dirty so that it will report as soon as possible.
      43            0 : void ReportSchedulerImpl::OnEnterActiveMode()
      44              : {
      45              : #if ICD_REPORT_ON_ENTER_ACTIVE_MODE
      46              :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      47              :     mNodesPool.ForEachActiveObject([this, now](ReadHandlerNode * node) {
      48              :         if (now >= node->GetMinTimestamp())
      49              :         {
      50              :             this->HandlerForceDirtyState(node->GetReadHandler());
      51              :         }
      52              : 
      53              :         return Loop::Continue;
      54              :     });
      55              : #endif
      56            0 : }
      57              : 
      58          310 : void ReportSchedulerImpl::OnSubscriptionEstablished(ReadHandler * aReadHandler)
      59              : {
      60          310 :     ReadHandlerNode * newNode = FindReadHandlerNode(aReadHandler);
      61              :     // Handler must not be registered yet; it's just being constructed.
      62          310 :     VerifyOrDie(nullptr == newNode);
      63              : 
      64          310 :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      65              : 
      66              :     // The NodePool is the same size as the ReadHandler pool from the IM Engine, so we don't need a check for size here since if a
      67              :     // ReadHandler was created, space should be available.
      68          310 :     newNode = mNodesPool.CreateObject(aReadHandler, this, now);
      69              : 
      70          310 :     ChipLogProgress(DataManagement,
      71              :                     "Registered a ReadHandler that will schedule a report between system Timestamp: 0x" ChipLogFormatX64
      72              :                     " and system Timestamp 0x" ChipLogFormatX64 ".",
      73              :                     ChipLogValueX64(newNode->GetMinTimestamp().count()), ChipLogValueX64(newNode->GetMaxTimestamp().count()));
      74              : 
      75          310 :     mNumTotalSubscriptionsEstablished++;
      76          310 : }
      77              : 
      78          765 : void ReportSchedulerImpl::OnBecameReportable(ReadHandler * aReadHandler)
      79              : {
      80          765 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
      81          765 :     VerifyOrReturn(nullptr != node);
      82              : 
      83          505 :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      84              : 
      85              :     Milliseconds32 newTimeout;
      86          505 :     TEMPORARY_RETURN_IGNORED CalculateNextReportTimeout(newTimeout, node, now);
      87          505 :     TEMPORARY_RETURN_IGNORED ScheduleReport(newTimeout, node, now);
      88              : }
      89              : 
      90          108 : void ReportSchedulerImpl::OnSubscriptionReportSent(ReadHandler * aReadHandler)
      91              : {
      92          108 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
      93          108 :     VerifyOrReturn(nullptr != node);
      94              : 
      95          108 :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      96              : 
      97              :     // This method is called after the report is sent, so the ReadHandler is no longer reportable, and thus CanBeSynced and
      98              :     // EngineRunScheduled of the node associated with the ReadHandler are set to false here.
      99          108 :     node->SetCanBeSynced(false);
     100          108 :     node->SetIntervalTimeStamps(aReadHandler, now);
     101              :     Milliseconds32 newTimeout;
     102              :     // Reset the EngineRunScheduled flag so that the next report is scheduled correctly
     103          108 :     node->SetEngineRunScheduled(false);
     104          108 :     TEMPORARY_RETURN_IGNORED CalculateNextReportTimeout(newTimeout, node, now);
     105          108 :     TEMPORARY_RETURN_IGNORED ScheduleReport(newTimeout, node, now);
     106              : }
     107              : 
     108         1109 : void ReportSchedulerImpl::OnReadHandlerDestroyed(ReadHandler * aReadHandler)
     109              : {
     110         1109 :     CancelReport(aReadHandler);
     111              : 
     112         1109 :     ReadHandlerNode * removeNode = FindReadHandlerNode(aReadHandler);
     113              :     // Nothing to remove if the handler is not found in the list
     114         1109 :     VerifyOrReturn(nullptr != removeNode);
     115              : 
     116          284 :     mNodesPool.ReleaseObject(removeNode);
     117              : }
     118              : 
     119          460 : CHIP_ERROR ReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now)
     120              : {
     121              :     // Cancel Report if it is currently scheduled
     122          460 :     mTimerDelegate->CancelTimer(node);
     123          460 :     if (timeout == Milliseconds32(0))
     124              :     {
     125          102 :         node->TimerFired();
     126          102 :         return CHIP_NO_ERROR;
     127              :     }
     128          716 :     ReturnErrorOnFailure(mTimerDelegate->StartTimer(node, timeout));
     129              : 
     130          358 :     return CHIP_NO_ERROR;
     131              : }
     132              : 
     133         1110 : void ReportSchedulerImpl::CancelReport(ReadHandler * aReadHandler)
     134              : {
     135         1110 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
     136         1110 :     VerifyOrReturn(nullptr != node);
     137          285 :     mTimerDelegate->CancelTimer(node);
     138              : }
     139              : 
     140          101 : void ReportSchedulerImpl::UnregisterAllHandlers()
     141              : {
     142          101 :     mNodesPool.ForEachActiveObject([this](ReadHandlerNode * node) {
     143           18 :         this->OnReadHandlerDestroyed(node->GetReadHandler());
     144           18 :         return Loop::Continue;
     145              :     });
     146          101 : }
     147              : 
     148           14 : bool ReportSchedulerImpl::IsReportScheduled(ReadHandler * aReadHandler)
     149              : {
     150           14 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
     151           14 :     VerifyOrReturnValue(nullptr != node, false);
     152           11 :     return mTimerDelegate->IsTimerActive(node);
     153              : }
     154              : 
     155          460 : CHIP_ERROR ReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode, const Timestamp & now)
     156              : {
     157          460 :     VerifyOrReturnError(nullptr != FindReadHandlerNode(aNode->GetReadHandler()), CHIP_ERROR_INVALID_ARGUMENT);
     158              : 
     159              :     // If the handler is reportable now, just schedule a report immediately
     160          460 :     if (aNode->IsReportableNow(now))
     161              :     {
     162              :         // If the handler is reportable now, just schedule a report immediately
     163           93 :         timeout = Milliseconds32(0);
     164              :     }
     165          367 :     else if (IsReadHandlerReportable(aNode->GetReadHandler()) && (aNode->GetMinTimestamp() > now))
     166              :     {
     167              :         // If the handler is reportable now, but the min interval is not elapsed, schedule a report for the moment the min interval
     168              :         // has elapsed
     169            5 :         timeout = aNode->GetMinTimestamp() - now;
     170              :     }
     171              :     else
     172              :     {
     173              :         // If the handler is not reportable now, schedule a report for the max interval
     174          362 :         timeout = aNode->GetMaxTimestamp() - now;
     175              :     }
     176          460 :     return CHIP_NO_ERROR;
     177              : }
     178              : 
     179              : } // namespace reporting
     180              : } // namespace app
     181              : } // namespace chip
        

Generated by: LCOV version 2.0-1