Matter SDK Coverage Report
Current view: top level - app - EventManagement.cpp (source / functions) Coverage Total Hit
Test: SHA:fd700f088ee2d8b07407ec02bd01329ac87109ab Lines: 95.7 % 439 420
Test Date: 2026-01-14 08:11:11 Functions: 91.2 % 34 31

            Line data    Source code
       1              : /**
       2              :  *
       3              :  *    Copyright (c) 2021 Project CHIP Authors
       4              :  *    Copyright (c) 2015-2017 Nest Labs, Inc.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : #include <access/AccessControl.h>
      20              : #include <access/RequestPath.h>
      21              : #include <access/SubjectDescriptor.h>
      22              : #include <app/EventManagement.h>
      23              : #include <app/InteractionModelEngine.h>
      24              : #include <lib/core/TLVUtilities.h>
      25              : #include <lib/support/CodeUtils.h>
      26              : #include <lib/support/logging/CHIPLogging.h>
      27              : 
      28              : #include <cassert>
      29              : #include <cinttypes>
      30              : 
      31              : using namespace chip::TLV;
      32              : 
      33              : namespace chip {
      34              : namespace app {
      35              : EventManagement EventManagement::sInstance;
      36              : 
      37              : /**
      38              :  * @brief
      39              :  *   A TLVReader backed by CircularEventBuffer
      40              :  */
      41              : class CircularEventReader : public TLV::TLVReader
      42              : {
      43              : public:
      44              :     /**
      45              :      * @brief
      46              :      *   Initializes a TLVReader object backed by CircularEventBuffer
      47              :      *
      48              :      * Reading begins in the CircularTLVBuffer belonging to this
      49              :      * CircularEventBuffer.  When the reader runs out of data, it begins
      50              :      * to read from the previous CircularEventBuffer.
      51              :      *
      52              :      * @param[in] apBuf A pointer to a fully initialized CircularEventBuffer
      53              :      *
      54              :      */
      55              :     void Init(CircularEventBufferWrapper * apBuf);
      56              : 
      57          944 :     virtual ~CircularEventReader() = default;
      58              : };
      59              : 
      60          870 : EventManagement & EventManagement::GetInstance()
      61              : {
      62          870 :     return sInstance;
      63              : }
      64              : 
      65              : struct ReclaimEventCtx
      66              : {
      67              :     CircularEventBuffer * mpEventBuffer = nullptr;
      68              :     size_t mSpaceNeededForMovedEvent    = 0;
      69              : };
      70              : 
      71              : /**
      72              :  * @brief
      73              :  *  Internal structure for traversing event list.
      74              :  */
      75              : struct CopyAndAdjustDeltaTimeContext
      76              : {
      77         2167 :     CopyAndAdjustDeltaTimeContext(TLVWriter * aWriter, EventLoadOutContext * inContext) : mpWriter(aWriter), mpContext(inContext) {}
      78              : 
      79              :     TLV::TLVWriter * mpWriter       = nullptr;
      80              :     EventLoadOutContext * mpContext = nullptr;
      81              : };
      82              : 
      83          128 : CHIP_ERROR EventManagement::Init(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
      84              :                                  CircularEventBuffer * apCircularEventBuffer,
      85              :                                  const LogStorageResources * const apLogStorageResources,
      86              :                                  MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
      87              :                                  System::Clock::Milliseconds64 aMonotonicStartupTime, EventReporter * apEventReporter)
      88              : {
      89          128 :     VerifyOrReturnError(apEventReporter != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      90          128 :     VerifyOrReturnError(aNumBuffers != 0, CHIP_ERROR_INVALID_ARGUMENT);
      91          128 :     VerifyOrReturnError(mState == EventManagementStates::Shutdown, CHIP_ERROR_INCORRECT_STATE);
      92              : 
      93          128 :     CircularEventBuffer * current = nullptr;
      94          128 :     CircularEventBuffer * prev    = nullptr;
      95          128 :     CircularEventBuffer * next    = nullptr;
      96              : 
      97          128 :     mpExchangeMgr = apExchangeManager;
      98              : 
      99          512 :     for (uint32_t bufferIndex = 0; bufferIndex < aNumBuffers; bufferIndex++)
     100              :     {
     101          384 :         next = (bufferIndex < aNumBuffers - 1) ? &apCircularEventBuffer[bufferIndex + 1] : nullptr;
     102              : 
     103          384 :         current = &apCircularEventBuffer[bufferIndex];
     104          384 :         current->Init(apLogStorageResources[bufferIndex].mpBuffer, apLogStorageResources[bufferIndex].mBufferSize, prev, next,
     105          384 :                       apLogStorageResources[bufferIndex].mPriority);
     106              : 
     107          384 :         prev = current;
     108              : 
     109          384 :         current->mProcessEvictedElement = nullptr;
     110          384 :         current->mAppData               = nullptr;
     111              :     }
     112              : 
     113          128 :     mpEventNumberCounter = apEventNumberCounter;
     114          128 :     mLastEventNumber     = mpEventNumberCounter->GetValue();
     115              : 
     116          128 :     mpEventBuffer = apCircularEventBuffer;
     117          128 :     mState        = EventManagementStates::Idle;
     118          128 :     mBytesWritten = 0;
     119              : 
     120          128 :     mMonotonicStartupTime = aMonotonicStartupTime;
     121              : 
     122          128 :     mpEventReporter = apEventReporter;
     123              : 
     124          128 :     return CHIP_NO_ERROR;
     125              : }
     126              : 
     127          422 : CHIP_ERROR EventManagement::CopyToNextBuffer(CircularEventBuffer * apEventBuffer)
     128              : {
     129          422 :     CircularTLVWriter writer;
     130          422 :     CircularTLVReader reader;
     131          422 :     CHIP_ERROR err                   = CHIP_NO_ERROR;
     132          422 :     CircularEventBuffer * nextBuffer = apEventBuffer->GetNextCircularEventBuffer();
     133          422 :     if (nextBuffer == nullptr)
     134              :     {
     135            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     136              :     }
     137          422 :     CircularEventBuffer backup = *nextBuffer;
     138              : 
     139              :     // Set up the next buffer s.t. it fails if needs to evict an element
     140          422 :     nextBuffer->mProcessEvictedElement = AlwaysFail;
     141              : 
     142          422 :     writer.Init(*nextBuffer);
     143              : 
     144              :     // Set up the reader s.t. it is positioned to read the head event
     145          422 :     reader.Init(*apEventBuffer);
     146              : 
     147          422 :     err = reader.Next();
     148          422 :     SuccessOrExit(err);
     149              : 
     150          422 :     err = writer.CopyElement(reader);
     151          422 :     SuccessOrExit(err);
     152              : 
     153          422 :     err = writer.Finalize();
     154          422 :     SuccessOrExit(err);
     155              : 
     156          422 :     ChipLogDetail(EventLogging, "Copy Event to next buffer with priority %u", static_cast<unsigned>(nextBuffer->GetPriority()));
     157            0 : exit:
     158          844 :     if (err != CHIP_NO_ERROR)
     159              :     {
     160            0 :         *nextBuffer = backup;
     161              :     }
     162          422 :     return err;
     163          422 : }
     164              : 
     165          665 : CHIP_ERROR EventManagement::EnsureSpaceInCircularBuffer(size_t aRequiredSpace, PriorityLevel aPriority)
     166              : {
     167          665 :     CHIP_ERROR err                    = CHIP_NO_ERROR;
     168          665 :     size_t requiredSpace              = aRequiredSpace;
     169          665 :     CircularEventBuffer * eventBuffer = mpEventBuffer;
     170          665 :     ReclaimEventCtx ctx;
     171              : 
     172              :     // Check that we have this much space in all our event buffers that might
     173              :     // hold the event. If we do not, that will prevent the event from being
     174              :     // properly evicted into higher-priority buffers. We want to discover
     175              :     // this early, so that testing surfaces the need to make those buffers
     176              :     // larger.
     177         1373 :     for (auto * currentBuffer = mpEventBuffer; currentBuffer; currentBuffer = currentBuffer->GetNextCircularEventBuffer())
     178              :     {
     179         1373 :         VerifyOrExit(requiredSpace <= currentBuffer->GetTotalDataLength(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
     180         1373 :         if (currentBuffer->IsFinalDestinationForPriority(aPriority))
     181              :         {
     182          665 :             break;
     183              :         }
     184              :     }
     185              : 
     186          665 :     VerifyOrExit(eventBuffer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
     187              : 
     188              :     // check whether we actually need to do anything, exit if we don't
     189          665 :     VerifyOrExit(requiredSpace > eventBuffer->AvailableDataLength(), err = CHIP_NO_ERROR);
     190              : 
     191              :     while (true)
     192              :     {
     193         1884 :         if (requiredSpace > eventBuffer->AvailableDataLength())
     194              :         {
     195         1100 :             ctx.mpEventBuffer             = eventBuffer;
     196         1100 :             ctx.mSpaceNeededForMovedEvent = 0;
     197              : 
     198         1100 :             eventBuffer->mProcessEvictedElement = EvictEvent;
     199         1100 :             eventBuffer->mAppData               = &ctx;
     200         1100 :             err                                 = eventBuffer->EvictHead();
     201              : 
     202              :             // one of two things happened: either the element was evicted immediately if the head's priority is same as current
     203              :             // buffer(final one), or we figured out how much space we need to evict it into the next buffer, the check happens in
     204              :             // EvictEvent function
     205              : 
     206         2200 :             if (err != CHIP_NO_ERROR)
     207              :             {
     208          735 :                 VerifyOrExit(ctx.mSpaceNeededForMovedEvent != 0, /* no-op, return err */);
     209          735 :                 VerifyOrExit(eventBuffer->GetNextCircularEventBuffer() != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
     210          735 :                 if (ctx.mSpaceNeededForMovedEvent <= eventBuffer->GetNextCircularEventBuffer()->AvailableDataLength())
     211              :                 {
     212              :                     // we can copy the event outright.  copy event and
     213              :                     // subsequently evict head s.t. evicting the head
     214              :                     // element always succeeds.
     215              :                     // Since we're calling CopyElement and we've checked
     216              :                     // that there is space in the next buffer, we don't expect
     217              :                     // this to fail.
     218          422 :                     err = CopyToNextBuffer(eventBuffer);
     219          422 :                     SuccessOrExit(err);
     220              :                     // success; evict head unconditionally
     221          422 :                     eventBuffer->mProcessEvictedElement = nullptr;
     222          422 :                     err                                 = eventBuffer->EvictHead();
     223              :                     // if unconditional eviction failed, this
     224              :                     // means that we have no way of further
     225              :                     // clearing the buffer.  fail out and let the
     226              :                     // caller know that we could not honor the
     227              :                     // request
     228          422 :                     SuccessOrExit(err);
     229          422 :                     continue;
     230              :                 }
     231              :                 // we cannot copy event outright. We remember the
     232              :                 // current required space in mRequiredSpaceForEvicted, we note the
     233              :                 // space requirements for the event in the current
     234              :                 // buffer and make that space in the next buffer.
     235          313 :                 eventBuffer->SetRequiredSpaceforEvicted(requiredSpace);
     236          313 :                 eventBuffer = eventBuffer->GetNextCircularEventBuffer();
     237              : 
     238              :                 // Sanity check: return error  here on null event buffer.  If
     239              :                 // eventBuffer->mpNext were null, then the `EvictBuffer`
     240              :                 // would have succeeded -- the event was
     241              :                 // already in the final buffer.
     242          313 :                 VerifyOrExit(eventBuffer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
     243          313 :                 requiredSpace = ctx.mSpaceNeededForMovedEvent;
     244              :             }
     245              :         }
     246              :         else
     247              :         {
     248              :             // this branch is only taken when we go back in the buffer chain since we have free/spare enough space in next buffer,
     249              :             // and need to retry to copy event from current buffer to next buffer, and free space for current buffer
     250          784 :             if (eventBuffer == mpEventBuffer)
     251          471 :                 break;
     252          313 :             eventBuffer   = eventBuffer->GetPreviousCircularEventBuffer();
     253          313 :             requiredSpace = eventBuffer->GetRequiredSpaceforEvicted();
     254          313 :             err           = CHIP_NO_ERROR;
     255              :         }
     256              :     }
     257              : 
     258          471 :     mpEventBuffer->mProcessEvictedElement = nullptr;
     259          471 :     mpEventBuffer->mAppData               = nullptr;
     260              : 
     261          665 : exit:
     262          665 :     return err;
     263              : }
     264              : 
     265          665 : CHIP_ERROR EventManagement::CalculateEventSize(EventLoggingDelegate * apDelegate, const InternalEventOptions * apOptions,
     266              :                                                uint32_t & requiredSize)
     267              : {
     268          665 :     System::PacketBufferTLVWriter writer;
     269          665 :     EventLoadOutContext ctxt       = EventLoadOutContext(writer, apOptions->mPriority, GetLastEventNumber());
     270          665 :     System::PacketBufferHandle buf = System::PacketBufferHandle::New(kMaxEventSizeReserve);
     271          665 :     if (buf.IsNull())
     272              :     {
     273            0 :         return CHIP_ERROR_NO_MEMORY;
     274              :     }
     275          665 :     writer.Init(std::move(buf));
     276              : 
     277          665 :     ctxt.mCurrentEventNumber = mLastEventNumber;
     278          665 :     ctxt.mCurrentTime        = mLastEventTimestamp;
     279          665 :     CHIP_ERROR err           = ConstructEvent(&ctxt, apDelegate, apOptions);
     280         1330 :     if (err == CHIP_NO_ERROR)
     281              :     {
     282          665 :         requiredSize = writer.GetLengthWritten();
     283              :     }
     284          665 :     return err;
     285          665 : }
     286              : 
     287         1330 : CHIP_ERROR EventManagement::ConstructEvent(EventLoadOutContext * apContext, EventLoggingDelegate * apDelegate,
     288              :                                            const InternalEventOptions * apOptions)
     289              : {
     290         1330 :     VerifyOrReturnError(apContext->mCurrentEventNumber >= apContext->mStartingEventNumber, CHIP_NO_ERROR
     291              :                         /* no-op: don't write event, but advance current event Number */);
     292              : 
     293         1330 :     VerifyOrReturnError(apOptions != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     294              : 
     295         1330 :     EventReportIB::Builder eventReportBuilder;
     296         1330 :     ReturnErrorOnFailure(eventReportBuilder.Init(&(apContext->mWriter)));
     297         1330 :     EventDataIB::Builder & eventDataIBBuilder = eventReportBuilder.CreateEventData();
     298         1330 :     ReturnErrorOnFailure(eventReportBuilder.GetError());
     299         1330 :     EventPathIB::Builder & eventPathBuilder = eventDataIBBuilder.CreatePath();
     300         1330 :     ReturnErrorOnFailure(eventDataIBBuilder.GetError());
     301              : 
     302         1330 :     CHIP_ERROR err = eventPathBuilder.Endpoint(apOptions->mPath.mEndpointId)
     303         1330 :                          .Cluster(apOptions->mPath.mClusterId)
     304         1330 :                          .Event(apOptions->mPath.mEventId)
     305         1330 :                          .EndOfEventPathIB();
     306         1330 :     ReturnErrorOnFailure(err);
     307         1330 :     eventDataIBBuilder.EventNumber(apContext->mCurrentEventNumber).Priority(chip::to_underlying(apContext->mPriority));
     308         1330 :     ReturnErrorOnFailure(eventDataIBBuilder.GetError());
     309              : 
     310         1330 :     if (apOptions->mTimestamp.IsSystem())
     311              :     {
     312           24 :         eventDataIBBuilder.SystemTimestamp(apOptions->mTimestamp.mValue);
     313              :     }
     314              :     else
     315              :     {
     316         1306 :         eventDataIBBuilder.EpochTimestamp(apOptions->mTimestamp.mValue);
     317              :     }
     318              : 
     319         1330 :     ReturnErrorOnFailure(eventDataIBBuilder.GetError());
     320              : 
     321              :     // Callback to write the EventData
     322         1330 :     ReturnErrorOnFailure(apDelegate->WriteEvent(apContext->mWriter));
     323              : 
     324              :     // The fabricIndex profile tag is internal use only for fabric filtering when retrieving event from circular event buffer,
     325              :     // and would not go on the wire.
     326              :     // Revisit FabricRemovedCB function should the encoding of fabricIndex change in the future.
     327         1330 :     if (apOptions->mFabricIndex != kUndefinedFabricIndex)
     328              :     {
     329            8 :         TEMPORARY_RETURN_IGNORED apContext->mWriter.Put(TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag),
     330            8 :                                                         apOptions->mFabricIndex);
     331              :     }
     332         1330 :     ReturnErrorOnFailure(eventDataIBBuilder.EndOfEventDataIB());
     333         1330 :     ReturnErrorOnFailure(eventReportBuilder.EndOfEventReportIB());
     334         1330 :     ReturnErrorOnFailure(apContext->mWriter.Finalize());
     335         1330 :     apContext->mFirst = false;
     336         1330 :     return CHIP_NO_ERROR;
     337              : }
     338              : 
     339          127 : void EventManagement::CreateEventManagement(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
     340              :                                             CircularEventBuffer * apCircularEventBuffer,
     341              :                                             const LogStorageResources * const apLogStorageResources,
     342              :                                             MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
     343              :                                             System::Clock::Milliseconds64 aMonotonicStartupTime)
     344              : {
     345              : 
     346          127 :     TEMPORARY_RETURN_IGNORED sInstance.Init(apExchangeManager, aNumBuffers, apCircularEventBuffer, apLogStorageResources,
     347              :                                             apEventNumberCounter, aMonotonicStartupTime,
     348          127 :                                             &InteractionModelEngine::GetInstance()->GetReportingEngine());
     349          127 : }
     350              : 
     351              : /**
     352              :  * @brief Perform any actions we need to on shutdown.
     353              :  */
     354          127 : void EventManagement::DestroyEventManagement()
     355              : {
     356          127 :     sInstance.mState        = EventManagementStates::Shutdown;
     357          127 :     sInstance.mpEventBuffer = nullptr;
     358          127 :     sInstance.mpExchangeMgr = nullptr;
     359          127 : }
     360              : 
     361          944 : CircularEventBuffer * EventManagement::GetPriorityBuffer(PriorityLevel aPriority) const
     362              : {
     363          944 :     CircularEventBuffer * buf = mpEventBuffer;
     364         2759 :     while (!buf->IsFinalDestinationForPriority(aPriority))
     365              :     {
     366         1815 :         buf = buf->GetNextCircularEventBuffer();
     367         1815 :         assert(buf != nullptr);
     368              :         // code guarantees that every PriorityLevel has a buffer destination.
     369              :     }
     370          944 :     return buf;
     371              : }
     372              : 
     373        10117 : CHIP_ERROR EventManagement::CopyAndAdjustDeltaTime(const TLVReader & aReader, size_t aDepth, void * apContext)
     374              : {
     375        10117 :     CopyAndAdjustDeltaTimeContext * ctx = static_cast<CopyAndAdjustDeltaTimeContext *>(apContext);
     376        10117 :     TLVReader reader(aReader);
     377              : 
     378        10117 :     if (aReader.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
     379              :     {
     380              :         // Does not go on the wire.
     381           13 :         return CHIP_NO_ERROR;
     382              :     }
     383        10125 :     if ((aReader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kSystemTimestamp)) && !(ctx->mpContext->mFirst) &&
     384           21 :         (ctx->mpContext->mCurrentTime.mType == ctx->mpContext->mPreviousTime.mType))
     385              :     {
     386           21 :         return ctx->mpWriter->Put(TLV::ContextTag(EventDataIB::Tag::kDeltaSystemTimestamp),
     387           42 :                                   ctx->mpContext->mCurrentTime.mValue - ctx->mpContext->mPreviousTime.mValue);
     388              :     }
     389        11259 :     if ((aReader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kEpochTimestamp)) && !(ctx->mpContext->mFirst) &&
     390         1176 :         (ctx->mpContext->mCurrentTime.mType == ctx->mpContext->mPreviousTime.mType))
     391              :     {
     392            0 :         return ctx->mpWriter->Put(TLV::ContextTag(EventDataIB::Tag::kDeltaEpochTimestamp),
     393            0 :                                   ctx->mpContext->mCurrentTime.mValue - ctx->mpContext->mPreviousTime.mValue);
     394              :     }
     395              : 
     396        10083 :     return ctx->mpWriter->CopyElement(reader);
     397              : }
     398              : 
     399          665 : void EventManagement::VendEventNumber()
     400              : {
     401          665 :     CHIP_ERROR err = CHIP_NO_ERROR;
     402              :     // Now advance the counter.
     403          665 :     err = mpEventNumberCounter->Advance();
     404         1330 :     if (err != CHIP_NO_ERROR)
     405              :     {
     406            0 :         ChipLogError(EventLogging, "%s Advance() failed with %" CHIP_ERROR_FORMAT, __FUNCTION__, err.Format());
     407              :     }
     408              : 
     409              :     // Assign event Number to the buffer's counter's value.
     410          665 :     mLastEventNumber = mpEventNumberCounter->GetValue();
     411          665 : }
     412              : 
     413          679 : CHIP_ERROR EventManagement::LogEvent(EventLoggingDelegate * apDelegate, const EventOptions & aEventOptions,
     414              :                                      EventNumber & aEventNumber)
     415              : {
     416          679 :     assertChipStackLockedByCurrentThread();
     417          679 :     VerifyOrReturnError(mState != EventManagementStates::Shutdown, CHIP_ERROR_INCORRECT_STATE);
     418          665 :     return LogEventPrivate(apDelegate, aEventOptions, aEventNumber);
     419              : }
     420              : 
     421          665 : CHIP_ERROR EventManagement::LogEventPrivate(EventLoggingDelegate * apDelegate, const EventOptions & aEventOptions,
     422              :                                             EventNumber & aEventNumber)
     423              : {
     424          665 :     CircularTLVWriter writer;
     425          665 :     CHIP_ERROR err               = CHIP_NO_ERROR;
     426          665 :     uint32_t requestSize         = 0;
     427          665 :     aEventNumber                 = 0;
     428          665 :     CircularTLVWriter checkpoint = writer;
     429          665 :     EventLoadOutContext ctxt     = EventLoadOutContext(writer, aEventOptions.mPriority, mLastEventNumber);
     430          665 :     InternalEventOptions opts;
     431              : 
     432          665 :     Timestamp timestamp;
     433              : #if CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
     434              :     System::Clock::Milliseconds64 utc_time;
     435          665 :     err = System::SystemClock().GetClock_RealTimeMS(utc_time);
     436         1330 :     if (err == CHIP_NO_ERROR)
     437              :     {
     438          653 :         timestamp = Timestamp::Epoch(utc_time);
     439              :     }
     440              :     else
     441              : #endif // CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
     442              :     {
     443           12 :         auto systemTimeMs = System::SystemClock().GetMonotonicMilliseconds64() - mMonotonicStartupTime;
     444           12 :         timestamp         = Timestamp::System(systemTimeMs);
     445              :     }
     446              : 
     447          665 :     opts = InternalEventOptions(timestamp);
     448              :     // Start the event container (anonymous structure) in the circular buffer
     449          665 :     writer.Init(*mpEventBuffer);
     450              : 
     451          665 :     opts.mPriority = aEventOptions.mPriority;
     452              :     // Create all event specific data
     453              :     // Timestamp; encoded as a delta time
     454              : 
     455          665 :     opts.mPath        = aEventOptions.mPath;
     456          665 :     opts.mFabricIndex = aEventOptions.mFabricIndex;
     457              : 
     458          665 :     ctxt.mCurrentEventNumber = mLastEventNumber;
     459          665 :     ctxt.mCurrentTime.mValue = mLastEventTimestamp.mValue;
     460              : 
     461          665 :     err = CalculateEventSize(apDelegate, &opts, requestSize);
     462          665 :     SuccessOrExit(err);
     463              : 
     464              :     // Ensure we have space in the in-memory logging queues
     465          665 :     err = EnsureSpaceInCircularBuffer(requestSize, aEventOptions.mPriority);
     466          665 :     SuccessOrExit(err);
     467              : 
     468          665 :     err = ConstructEvent(&ctxt, apDelegate, &opts);
     469          665 :     SuccessOrExit(err);
     470              : 
     471          665 :     mBytesWritten += writer.GetLengthWritten();
     472              : 
     473          665 : exit:
     474         1330 :     if (err != CHIP_NO_ERROR)
     475              :     {
     476            0 :         ChipLogError(EventLogging, "Log event with error %" CHIP_ERROR_FORMAT, err.Format());
     477            0 :         writer = checkpoint;
     478              :     }
     479              :     else if (opts.mPriority >= CHIP_CONFIG_EVENT_GLOBAL_PRIORITY)
     480              :     {
     481          665 :         aEventNumber = mLastEventNumber;
     482          665 :         VendEventNumber();
     483          665 :         mLastEventTimestamp = timestamp;
     484              : #if CHIP_CONFIG_EVENT_LOGGING_VERBOSE_DEBUG_LOGS
     485          665 :         ChipLogDetail(EventLogging,
     486              :                       "LogEvent event number: 0x" ChipLogFormatX64 " priority: %u, endpoint id:  0x%x"
     487              :                       " cluster id: " ChipLogFormatMEI " event id: 0x%" PRIx32 " %s timestamp: 0x" ChipLogFormatX64,
     488              :                       ChipLogValueX64(aEventNumber), static_cast<unsigned>(opts.mPriority), opts.mPath.mEndpointId,
     489              :                       ChipLogValueMEI(opts.mPath.mClusterId), opts.mPath.mEventId,
     490              :                       opts.mTimestamp.mType == Timestamp::Type::kSystem ? "Sys" : "Epoch", ChipLogValueX64(opts.mTimestamp.mValue));
     491              : #endif // CHIP_CONFIG_EVENT_LOGGING_VERBOSE_DEBUG_LOGS
     492              : 
     493          665 :         err = mpEventReporter->NewEventGenerated(opts.mPath, mBytesWritten);
     494              :     }
     495              : 
     496          665 :     return err;
     497              : }
     498              : 
     499         2167 : CHIP_ERROR EventManagement::CopyEvent(const TLVReader & aReader, TLVWriter & aWriter, EventLoadOutContext * apContext)
     500              : {
     501         2167 :     TLVReader reader;
     502              :     TLVType containerType;
     503              :     TLVType containerType1;
     504         2167 :     CopyAndAdjustDeltaTimeContext context(&aWriter, apContext);
     505         2167 :     CHIP_ERROR err = CHIP_NO_ERROR;
     506              : 
     507         2167 :     reader.Init(aReader);
     508         2167 :     ReturnErrorOnFailure(reader.EnterContainer(containerType));
     509         2167 :     ReturnErrorOnFailure(aWriter.StartContainer(AnonymousTag(), kTLVType_Structure, containerType));
     510              : 
     511         2153 :     ReturnErrorOnFailure(reader.Next());
     512         2153 :     ReturnErrorOnFailure(reader.EnterContainer(containerType1));
     513         2153 :     ReturnErrorOnFailure(
     514              :         aWriter.StartContainer(TLV::ContextTag(EventReportIB::Tag::kEventData), kTLVType_Structure, containerType1));
     515         2123 :     err = TLV::Utilities::Iterate(reader, CopyAndAdjustDeltaTime, &context, false /*recurse*/);
     516         4246 :     if (err == CHIP_END_OF_TLV)
     517              :     {
     518         1661 :         err = CHIP_NO_ERROR;
     519              :     }
     520         2123 :     ReturnErrorOnFailure(err);
     521         1661 :     ReturnErrorOnFailure(aWriter.EndContainer(containerType1));
     522         1656 :     ReturnErrorOnFailure(aWriter.EndContainer(containerType));
     523         1652 :     ReturnErrorOnFailure(aWriter.Finalize());
     524         1652 :     return CHIP_NO_ERROR;
     525              : }
     526              : 
     527         3250 : bool EventManagement::IncludeEventInReport(EventLoadOutContext * eventLoadOutContext,
     528              :                                            const EventManagement::EventEnvelopeContext & event)
     529              : {
     530         3250 :     if (eventLoadOutContext->mCurrentEventNumber < eventLoadOutContext->mStartingEventNumber)
     531              :     {
     532         1033 :         return false;
     533              :     }
     534              : 
     535         2252 :     if (event.mFabricIndex.HasValue() &&
     536           35 :         (event.mFabricIndex.Value() == kUndefinedFabricIndex ||
     537           28 :          eventLoadOutContext->mSubjectDescriptor.fabricIndex != event.mFabricIndex.Value()))
     538              :     {
     539           22 :         return false;
     540              :     }
     541              : 
     542         2195 :     bool isPathInterested = false;
     543         2195 :     ConcreteEventPath path(event.mEndpointId, event.mClusterId, event.mEventId);
     544              :     // Check whether the event path is in the interested paths
     545         2243 :     for (auto * interestedPath = eventLoadOutContext->mpInterestedEventPaths; interestedPath != nullptr;
     546           48 :          interestedPath        = interestedPath->mpNext)
     547              :     {
     548         2221 :         if (interestedPath->mValue.IsEventPathSupersetOf(path))
     549              :         {
     550         2173 :             isPathInterested = true;
     551         2173 :             break;
     552              :         }
     553              :     }
     554         2195 :     if (!isPathInterested)
     555              :     {
     556           22 :         return false;
     557              :     }
     558              : 
     559              :     DataModel::EventEntry eventInfo;
     560         4346 :     if (InteractionModelEngine::GetInstance()->GetDataModelProvider()->EventInfo(path, eventInfo) != CHIP_NO_ERROR)
     561              :     {
     562              :         // If we cannot get event info here, that means the data model doesn't support the
     563              :         // event (eg. the endpoint is removed).  Return false, because we can't even perform ACL checks here,
     564              :         // since we don't know what permissions to check for.  This is not an error condition
     565              :         // (other than omitting the event), because the only way we can end up in this situation
     566              :         // is with a wildcard event path.
     567              :         //
     568              :         // TODO: We should not record the event in the log buffer when the event is not supported by the data model, see #41448.
     569              :         // TODO: We should remove the event from the log buffer when the event path is no longer valid (eg. when the endpoint of the
     570              :         // event path is removed), see #41448
     571            0 :         return false;
     572              :     }
     573              : 
     574         2173 :     Access::RequestPath requestPath{ .cluster     = event.mClusterId,
     575         2173 :                                      .endpoint    = event.mEndpointId,
     576              :                                      .requestType = Access::RequestType::kEventReadRequest,
     577         2173 :                                      .entityId    = event.mEventId };
     578              :     CHIP_ERROR accessControlError =
     579         2173 :         Access::GetAccessControl().Check(eventLoadOutContext->mSubjectDescriptor, requestPath, eventInfo.readPrivilege);
     580         4346 :     if (accessControlError != CHIP_NO_ERROR)
     581              :     {
     582              :         // If we don't have the access for the event, the only way we could have gotten here
     583              :         // is due to a wildcard event path that includes the event.  Return false so that
     584              :         // the event will be excluded in the generated event report.
     585            6 :         return false;
     586              :     }
     587              : 
     588              :     // If all the checks pass, the event will be included in the generated event report.
     589         2167 :     return true;
     590              : }
     591              : 
     592         3250 : CHIP_ERROR EventManagement::EventIterator(const TLVReader & aReader, size_t aDepth, EventLoadOutContext * apEventLoadOutContext,
     593              :                                           EventEnvelopeContext * event, bool & encodeEvent)
     594              : {
     595         3250 :     CHIP_ERROR err = CHIP_NO_ERROR;
     596         3250 :     TLVReader innerReader;
     597              :     TLVType tlvType;
     598              :     TLVType tlvType1;
     599              : 
     600         3250 :     innerReader.Init(aReader);
     601         3250 :     VerifyOrDie(event != nullptr);
     602         3250 :     ReturnErrorOnFailure(innerReader.EnterContainer(tlvType));
     603         3250 :     ReturnErrorOnFailure(innerReader.Next());
     604              : 
     605         3250 :     ReturnErrorOnFailure(innerReader.EnterContainer(tlvType1));
     606         3250 :     err = TLV::Utilities::Iterate(innerReader, FetchEventParameters, event, false /*recurse*/);
     607              : 
     608         3250 :     if (event->mFieldsToRead != kRequiredEventField)
     609              :     {
     610            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     611              :     }
     612              : 
     613         6500 :     if (err == CHIP_END_OF_TLV)
     614              :     {
     615         3250 :         err = CHIP_NO_ERROR;
     616              :     }
     617         3250 :     ReturnErrorOnFailure(err);
     618              : 
     619         3250 :     apEventLoadOutContext->mCurrentTime        = event->mCurrentTime;
     620         3250 :     apEventLoadOutContext->mCurrentEventNumber = event->mEventNumber;
     621              : 
     622         3250 :     encodeEvent = IncludeEventInReport(apEventLoadOutContext, *event);
     623         3250 :     return CHIP_NO_ERROR;
     624              : }
     625              : 
     626         3250 : CHIP_ERROR EventManagement::CopyEventsSince(const TLVReader & aReader, size_t aDepth, void * apContext)
     627              : {
     628         3250 :     EventLoadOutContext * const loadOutContext = static_cast<EventLoadOutContext *>(apContext);
     629         3250 :     EventEnvelopeContext event;
     630         3250 :     bool encodeEvent = false;
     631         3250 :     CHIP_ERROR err   = EventIterator(aReader, aDepth, loadOutContext, &event, encodeEvent);
     632         6500 :     if ((err == CHIP_NO_ERROR) && encodeEvent)
     633              :     {
     634              :         // checkpoint the writer
     635         2167 :         TLV::TLVWriter checkpoint = loadOutContext->mWriter;
     636              : 
     637         2167 :         err = CopyEvent(aReader, loadOutContext->mWriter, loadOutContext);
     638              : 
     639              :         // CHIP_NO_ERROR and CHIP_END_OF_TLV signify a
     640              :         // successful copy.  In all other cases, roll back the
     641              :         // writer state back to the checkpoint, i.e., the state
     642              :         // before we began the copy operation.
     643         4849 :         if ((err != CHIP_NO_ERROR) && (err != CHIP_END_OF_TLV))
     644              :         {
     645          515 :             loadOutContext->mWriter = checkpoint;
     646          515 :             return err;
     647              :         }
     648              : 
     649         1652 :         loadOutContext->mPreviousTime.mValue = loadOutContext->mCurrentTime.mValue;
     650         1652 :         loadOutContext->mFirst               = false;
     651         1652 :         loadOutContext->mEventCount++;
     652              :     }
     653         2735 :     return err;
     654              : }
     655              : 
     656          893 : CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, const SingleLinkedListNode<EventPathParams> * apEventPathList,
     657              :                                              EventNumber & aEventMin, size_t & aEventCount,
     658              :                                              const Access::SubjectDescriptor & aSubjectDescriptor)
     659              : {
     660              :     // TODO: Add particular set of event Paths in FetchEventsSince so that we can filter the interested paths
     661          893 :     CHIP_ERROR err     = CHIP_NO_ERROR;
     662          893 :     const bool recurse = false;
     663          893 :     TLVReader reader;
     664          893 :     CircularEventBufferWrapper bufWrapper;
     665          893 :     EventLoadOutContext context(aWriter, PriorityLevel::Invalid, aEventMin);
     666              : 
     667          893 :     context.mSubjectDescriptor     = aSubjectDescriptor;
     668          893 :     context.mpInterestedEventPaths = apEventPathList;
     669          893 :     err                            = GetEventReader(reader, PriorityLevel::Critical, &bufWrapper);
     670          893 :     SuccessOrExit(err);
     671              : 
     672          893 :     err = TLV::Utilities::Iterate(reader, CopyEventsSince, &context, recurse);
     673         1786 :     if (err == CHIP_END_OF_TLV)
     674              :     {
     675          378 :         err = CHIP_NO_ERROR;
     676              :     }
     677              : 
     678          515 : exit:
     679         2679 :     if (err == CHIP_ERROR_BUFFER_TOO_SMALL || err == CHIP_ERROR_NO_MEMORY)
     680              :     {
     681              :         // We failed to fetch the current event because the buffer is too small, we will start from this one the next time.
     682          515 :         aEventMin = context.mCurrentEventNumber;
     683              :     }
     684              :     else
     685              :     {
     686              :         // For all other cases, continue from the next event.
     687          378 :         aEventMin = context.mCurrentEventNumber + 1;
     688              :     }
     689          893 :     aEventCount += context.mEventCount;
     690         1786 :     return err;
     691          893 : }
     692              : 
     693            8 : CHIP_ERROR EventManagement::FabricRemovedCB(const TLV::TLVReader & aReader, size_t aDepth, void * apContext)
     694              : {
     695              :     // the function does not actually remove the event, instead, it sets the fabric index to an invalid value.
     696            8 :     FabricIndex * invalidFabricIndex = static_cast<FabricIndex *>(apContext);
     697              : 
     698            8 :     TLVReader event;
     699              :     TLVType tlvType;
     700              :     TLVType tlvType1;
     701            8 :     event.Init(aReader);
     702           16 :     VerifyOrReturnError(event.EnterContainer(tlvType) == CHIP_NO_ERROR, CHIP_NO_ERROR);
     703           16 :     VerifyOrReturnError(event.Next(TLV::ContextTag(EventReportIB::Tag::kEventData)) == CHIP_NO_ERROR, CHIP_NO_ERROR);
     704           16 :     VerifyOrReturnError(event.EnterContainer(tlvType1) == CHIP_NO_ERROR, CHIP_NO_ERROR);
     705              : 
     706           96 :     while (CHIP_NO_ERROR == event.Next())
     707              :     {
     708           48 :         if (event.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
     709              :         {
     710            8 :             uint8_t fabricIndex = 0;
     711           16 :             VerifyOrReturnError(event.Get(fabricIndex) == CHIP_NO_ERROR, CHIP_NO_ERROR);
     712            8 :             if (fabricIndex == *invalidFabricIndex)
     713              :             {
     714            4 :                 TLVCircularBuffer * readBuffer = static_cast<TLVCircularBuffer *>(event.GetBackingStore());
     715              :                 // fabricIndex is encoded as an integer; the dataPtr will point to a location immediately after its encoding
     716              :                 // shift the dataPtr to point to the encoding of the fabric index, accounting for wraparound in backing storage
     717              :                 // we cannot get the actual encoding size from current container beginning to the fabric index because of several
     718              :                 // optional parameters, so we are assuming minimal encoding is used and the fabric index is 1 byte.
     719              :                 uint8_t * dataPtr;
     720            4 :                 if (event.GetReadPoint() != readBuffer->GetQueue())
     721              :                 {
     722            4 :                     dataPtr = readBuffer->GetQueue() + (event.GetReadPoint() - readBuffer->GetQueue() - 1);
     723              :                 }
     724              :                 else
     725              :                 {
     726            0 :                     dataPtr = readBuffer->GetQueue() + readBuffer->GetTotalDataLength() - 1;
     727              :                 }
     728              : 
     729            4 :                 *dataPtr = kUndefinedFabricIndex;
     730              :             }
     731            8 :             return CHIP_NO_ERROR;
     732              :         }
     733              :     }
     734            0 :     return CHIP_NO_ERROR;
     735              : }
     736              : 
     737            2 : CHIP_ERROR EventManagement::FabricRemoved(FabricIndex aFabricIndex)
     738              : {
     739            2 :     const bool recurse = false;
     740            2 :     TLVReader reader;
     741            2 :     CircularEventBufferWrapper bufWrapper;
     742              : 
     743            2 :     ReturnErrorOnFailure(GetEventReader(reader, PriorityLevel::Critical, &bufWrapper));
     744            2 :     CHIP_ERROR err = TLV::Utilities::Iterate(reader, FabricRemovedCB, &aFabricIndex, recurse);
     745            4 :     if (err == CHIP_END_OF_TLV)
     746              :     {
     747            2 :         err = CHIP_NO_ERROR;
     748              :     }
     749            2 :     return err;
     750            2 : }
     751              : 
     752          944 : CHIP_ERROR EventManagement::GetEventReader(TLVReader & aReader, PriorityLevel aPriority, CircularEventBufferWrapper * apBufWrapper)
     753              : {
     754          944 :     CircularEventBuffer * buffer = GetPriorityBuffer(aPriority);
     755          944 :     VerifyOrReturnError(buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     756          944 :     apBufWrapper->mpCurrent = buffer;
     757              : 
     758          944 :     CircularEventReader reader;
     759          944 :     reader.Init(apBufWrapper);
     760          944 :     aReader.Init(reader);
     761              : 
     762          944 :     return CHIP_NO_ERROR;
     763          944 : }
     764              : 
     765        21796 : CHIP_ERROR EventManagement::FetchEventParameters(const TLVReader & aReader, size_t, void * apContext)
     766              : {
     767        21796 :     EventEnvelopeContext * const envelope = static_cast<EventEnvelopeContext *>(apContext);
     768        21796 :     TLVReader reader;
     769        21796 :     reader.Init(aReader);
     770              : 
     771        21796 :     if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kPath))
     772              :     {
     773         4350 :         EventPathIB::Parser path;
     774         4350 :         ReturnErrorOnFailure(path.Init(aReader));
     775         4350 :         ReturnErrorOnFailure(path.GetEndpoint(&(envelope->mEndpointId)));
     776         4350 :         ReturnErrorOnFailure(path.GetCluster(&(envelope->mClusterId)));
     777         4350 :         ReturnErrorOnFailure(path.GetEvent(&(envelope->mEventId)));
     778         4350 :         envelope->mFieldsToRead |= 1 << to_underlying(EventDataIB::Tag::kPath);
     779              :     }
     780              : 
     781        21796 :     if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kPriority))
     782              :     {
     783              :         uint16_t extPriority; // Note: the type here matches the type case in EventManagement::LogEvent, priority section
     784         4350 :         ReturnErrorOnFailure(reader.Get(extPriority));
     785         4350 :         envelope->mPriority = static_cast<PriorityLevel>(extPriority);
     786         4350 :         envelope->mFieldsToRead |= 1 << to_underlying(EventDataIB::Tag::kPriority);
     787              :     }
     788              : 
     789        21796 :     if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kEventNumber))
     790              :     {
     791         4350 :         ReturnErrorOnFailure(reader.Get(envelope->mEventNumber));
     792              :     }
     793              : 
     794        21796 :     if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kSystemTimestamp))
     795              :     {
     796              :         uint64_t systemTime;
     797           58 :         ReturnErrorOnFailure(reader.Get(systemTime));
     798           58 :         envelope->mCurrentTime.mType  = Timestamp::Type::kSystem;
     799           58 :         envelope->mCurrentTime.mValue = systemTime;
     800              :     }
     801              : 
     802        21796 :     if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kEpochTimestamp))
     803              :     {
     804              :         uint64_t epochTime;
     805         4292 :         ReturnErrorOnFailure(reader.Get(epochTime));
     806         4292 :         envelope->mCurrentTime.mType  = Timestamp::Type::kEpoch;
     807         4292 :         envelope->mCurrentTime.mValue = epochTime;
     808              :     }
     809              : 
     810        21796 :     if (reader.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
     811              :     {
     812           46 :         uint8_t fabricIndex = kUndefinedFabricIndex;
     813           46 :         ReturnErrorOnFailure(reader.Get(fabricIndex));
     814           46 :         envelope->mFabricIndex.SetValue(fabricIndex);
     815              :     }
     816        21796 :     return CHIP_NO_ERROR;
     817              : }
     818              : 
     819         1100 : CHIP_ERROR EventManagement::EvictEvent(TLVCircularBuffer & apBuffer, void * apAppData, TLVReader & aReader)
     820              : {
     821              :     // pull out the delta time, pull out the priority
     822         1100 :     ReturnErrorOnFailure(aReader.Next());
     823              : 
     824              :     TLVType containerType;
     825              :     TLVType containerType1;
     826         1100 :     ReturnErrorOnFailure(aReader.EnterContainer(containerType));
     827         1100 :     ReturnErrorOnFailure(aReader.Next());
     828              : 
     829         1100 :     ReturnErrorOnFailure(aReader.EnterContainer(containerType1));
     830         1100 :     EventEnvelopeContext context;
     831         1100 :     constexpr bool recurse = false;
     832         1100 :     CHIP_ERROR err         = TLV::Utilities::Iterate(aReader, FetchEventParameters, &context, recurse);
     833         2200 :     if (err == CHIP_END_OF_TLV)
     834              :     {
     835         1100 :         err = CHIP_NO_ERROR;
     836              :     }
     837         1100 :     ReturnErrorOnFailure(err);
     838              : 
     839         1100 :     ReturnErrorOnFailure(aReader.ExitContainer(containerType1));
     840         1100 :     ReturnErrorOnFailure(aReader.ExitContainer(containerType));
     841         1100 :     const PriorityLevel imp = static_cast<PriorityLevel>(context.mPriority);
     842              : 
     843         1100 :     ReclaimEventCtx * const ctx             = static_cast<ReclaimEventCtx *>(apAppData);
     844         1100 :     CircularEventBuffer * const eventBuffer = ctx->mpEventBuffer;
     845         1100 :     if (eventBuffer->IsFinalDestinationForPriority(imp))
     846              :     {
     847          365 :         ChipLogProgress(EventLogging,
     848              :                         "Dropped 1 event from buffer with priority %u and event number  0x" ChipLogFormatX64
     849              :                         " due to overflow: event priority_level: %u",
     850              :                         static_cast<unsigned>(eventBuffer->GetPriority()), ChipLogValueX64(context.mEventNumber),
     851              :                         static_cast<unsigned>(imp));
     852          365 :         ctx->mSpaceNeededForMovedEvent = 0;
     853          365 :         return CHIP_NO_ERROR;
     854              :     }
     855              : 
     856              :     // event is not getting dropped. Note how much space it requires, and return.
     857          735 :     ctx->mSpaceNeededForMovedEvent = aReader.GetLengthRead();
     858          735 :     return CHIP_END_OF_TLV;
     859              : }
     860              : 
     861          345 : void EventManagement::SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) const
     862              : {
     863          345 :     aEventNumber              = mLastEventNumber;
     864          345 :     aInitialWrittenEventBytes = mBytesWritten;
     865          345 : }
     866              : 
     867            0 : CHIP_ERROR EventManagement::GenerateEvent(EventLoggingDelegate * eventPayloadWriter, const EventOptions & options,
     868              :                                           EventNumber & generatedEventNumber)
     869              : {
     870            0 :     return LogEvent(eventPayloadWriter, options, generatedEventNumber);
     871              : }
     872              : 
     873            0 : void EventManagement::ScheduleUrgentEventDeliverySync(std::optional<FabricIndex> fabricIndex)
     874              : {
     875            0 :     mpEventReporter->ScheduleUrgentEventDeliverySync(FromStdOptional(fabricIndex));
     876            0 : }
     877              : 
     878          384 : void CircularEventBuffer::Init(uint8_t * apBuffer, uint32_t aBufferLength, CircularEventBuffer * apPrev,
     879              :                                CircularEventBuffer * apNext, PriorityLevel aPriorityLevel)
     880              : {
     881          384 :     TLVCircularBuffer::Init(apBuffer, aBufferLength);
     882          384 :     mpPrev    = apPrev;
     883          384 :     mpNext    = apNext;
     884          384 :     mPriority = aPriorityLevel;
     885          384 : }
     886              : 
     887         5232 : bool CircularEventBuffer::IsFinalDestinationForPriority(PriorityLevel aPriority) const
     888              : {
     889         5232 :     return !((mpNext != nullptr) && (mpNext->mPriority <= aPriority));
     890              : }
     891              : 
     892              : /**
     893              :  * @brief
     894              :  * TLVCircularBuffer::OnInit can modify the state of the buffer, but we don't want that behavior here.
     895              :  * We want to make sure we don't change our state, and just report the currently-available space.
     896              :  */
     897         1087 : CHIP_ERROR CircularEventBuffer::OnInit(TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen)
     898              : {
     899         1087 :     GetCurrentWritableBuffer(bufStart, bufLen);
     900         1087 :     return CHIP_NO_ERROR;
     901              : }
     902              : 
     903          944 : void CircularEventReader::Init(CircularEventBufferWrapper * apBufWrapper)
     904              : {
     905              :     CircularEventBuffer * prev;
     906              : 
     907          944 :     if (apBufWrapper->mpCurrent == nullptr)
     908            0 :         return;
     909              : 
     910          944 :     TEMPORARY_RETURN_IGNORED TLVReader::Init(*apBufWrapper, apBufWrapper->mpCurrent->DataLength());
     911          944 :     mMaxLen = apBufWrapper->mpCurrent->DataLength();
     912          991 :     for (prev = apBufWrapper->mpCurrent->GetPreviousCircularEventBuffer(); prev != nullptr;
     913           47 :          prev = prev->GetPreviousCircularEventBuffer())
     914              :     {
     915           47 :         CircularEventBufferWrapper bufWrapper;
     916           47 :         bufWrapper.mpCurrent = prev;
     917           47 :         mMaxLen += prev->DataLength();
     918           47 :     }
     919              : }
     920              : 
     921         2936 : CHIP_ERROR CircularEventBufferWrapper::GetNextBuffer(TLVReader & aReader, const uint8_t *& aBufStart, uint32_t & aBufLen)
     922              : {
     923         2936 :     CHIP_ERROR err = CHIP_NO_ERROR;
     924         2936 :     TEMPORARY_RETURN_IGNORED mpCurrent->GetNextBuffer(aReader, aBufStart, aBufLen);
     925         2936 :     SuccessOrExit(err);
     926              : 
     927         2936 :     if ((aBufLen == 0) && (mpCurrent->GetPreviousCircularEventBuffer() != nullptr))
     928              :     {
     929         1815 :         mpCurrent = mpCurrent->GetPreviousCircularEventBuffer();
     930         1815 :         aBufStart = nullptr;
     931         1815 :         err       = GetNextBuffer(aReader, aBufStart, aBufLen);
     932              :     }
     933              : 
     934         1121 : exit:
     935         2936 :     return err;
     936              : }
     937              : 
     938              : } // namespace app
     939              : } // namespace chip
        

Generated by: LCOV version 2.0-1