LCOV - code coverage report
Current view: top level - include/platform - PlatformManager.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 16 33 48.5 %
Date: 2024-02-15 08:20:41 Functions: 6 11 54.5 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020 Project CHIP Authors
       4             :  *    Copyright (c) 2018 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             : /**
      20             :  *    @file
      21             :  *          Defines the public interface for the Device Layer PlatformManager object.
      22             :  */
      23             : 
      24             : #pragma once
      25             : 
      26             : #include <platform/AttributeList.h>
      27             : #include <platform/CHIPDeviceConfig.h>
      28             : #include <platform/CHIPDeviceEvent.h>
      29             : #include <system/PlatformEventSupport.h>
      30             : #include <system/SystemLayer.h>
      31             : 
      32             : namespace chip {
      33             : 
      34             : namespace Dnssd {
      35             : class DiscoveryImplPlatform;
      36             : }
      37             : 
      38             : namespace DeviceLayer {
      39             : 
      40             : static constexpr size_t kMaxCalendarTypes = 12;
      41             : 
      42             : class PlatformManagerImpl;
      43             : class ConnectivityManagerImpl;
      44             : class ConfigurationManagerImpl;
      45             : class DeviceControlServer;
      46             : class TraitManager;
      47             : class ThreadStackManagerImpl;
      48             : 
      49             : namespace Internal {
      50             : class BLEManagerImpl;
      51             : template <class>
      52             : class GenericConfigurationManagerImpl;
      53             : template <class>
      54             : class GenericPlatformManagerImpl;
      55             : template <class>
      56             : class GenericPlatformManagerImpl_FreeRTOS;
      57             : template <class>
      58             : class GenericPlatformManagerImpl_POSIX;
      59             : template <class>
      60             : class GenericPlatformManagerImpl_Zephyr;
      61             : template <class>
      62             : class GenericConnectivityManagerImpl_Thread;
      63             : template <class>
      64             : class GenericThreadStackManagerImpl_OpenThread;
      65             : template <class>
      66             : class GenericThreadStackManagerImpl_OpenThread_LwIP;
      67             : } // namespace Internal
      68             : 
      69             : /**
      70             :  * Defines the delegate class of Platform Manager to notify platform updates.
      71             :  */
      72             : class PlatformManagerDelegate
      73             : {
      74             : public:
      75             :     virtual ~PlatformManagerDelegate() {}
      76             : 
      77             :     /**
      78             :      * @brief
      79             :      *   Called by the current Node after completing a boot or reboot process.
      80             :      */
      81             :     virtual void OnStartUp(uint32_t softwareVersion) {}
      82             : 
      83             :     /**
      84             :      * @brief
      85             :      *   Called by the current Node prior to any orderly shutdown sequence on a
      86             :      *   best-effort basis.
      87             :      */
      88             :     virtual void OnShutDown() {}
      89             : };
      90             : 
      91             : /**
      92             :  * Provides features for initializing and interacting with the chip network
      93             :  * stack on a chip-enabled device.
      94             :  */
      95             : class PlatformManager
      96             : {
      97             :     using ImplClass = ::chip::DeviceLayer::PlatformManagerImpl;
      98             : 
      99             : public:
     100             :     // ===== Members that define the public interface of the PlatformManager
     101             : 
     102             :     typedef void (*EventHandlerFunct)(const ChipDeviceEvent * event, intptr_t arg);
     103             : 
     104             :     /**
     105             :      * InitChipStack() initializes the PlatformManager.  After calling that, a
     106             :      * consumer is allowed to call either StartEventLoopTask or RunEventLoop to
     107             :      * process pending work.  Calling both is not allowed: it must be one or the
     108             :      * other.
     109             :      */
     110             :     CHIP_ERROR InitChipStack();
     111             : 
     112             :     CHIP_ERROR AddEventHandler(EventHandlerFunct handler, intptr_t arg = 0);
     113             :     void RemoveEventHandler(EventHandlerFunct handler, intptr_t arg = 0);
     114             :     void SetDelegate(PlatformManagerDelegate * delegate) { mDelegate = delegate; }
     115             :     PlatformManagerDelegate * GetDelegate() const { return mDelegate; }
     116             : 
     117             :     /**
     118             :      * Should be called after initializing all layers of the Matter stack to
     119             :      * run all needed post-startup actions.
     120             :      */
     121             :     void HandleServerStarted();
     122             : 
     123             :     /**
     124             :      * Should be called before shutting down the Matter stack or restarting the
     125             :      * application to run all needed pre-shutdown actions.
     126             :      */
     127             :     void HandleServerShuttingDown();
     128             : 
     129             :     /**
     130             :      * ScheduleWork can be called after InitChipStack has been called.  Calls
     131             :      * that happen before either StartEventLoopTask or RunEventLoop will queue
     132             :      * the work up but that work will NOT run until one of those functions is
     133             :      * called.
     134             :      *
     135             :      * ScheduleWork can be called safely on any thread without locking the
     136             :      * stack.  When called from a thread that is not doing the stack work item
     137             :      * processing, the callback function may be called (on the work item
     138             :      * processing thread) before ScheduleWork returns.
     139             :      */
     140             :     CHIP_ERROR ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg = 0);
     141             : 
     142             :     /**
     143             :      * Process work items until StopEventLoopTask is called.  RunEventLoop will
     144             :      * not return until work item processing is stopped.  Once it returns it
     145             :      * guarantees that no more work items will be processed unless there's
     146             :      * another call to RunEventLoop.
     147             :      *
     148             :      * Consumers that call RunEventLoop must not call StartEventLoopTask.
     149             :      *
     150             :      * Consumers that call RunEventLoop must ensure that RunEventLoop returns
     151             :      * before calling Shutdown.
     152             :      */
     153             :     void RunEventLoop();
     154             : 
     155             :     /**
     156             :      * Process work items until StopEventLoopTask is called.
     157             :      *
     158             :      * StartEventLoopTask processes items asynchronously.  It can return before
     159             :      * any items are processed, or after some items have been processed, or
     160             :      * while an item is being processed, or even after StopEventLoopTask() has
     161             :      * been called (e.g. if ScheduleWork() was called before StartEventLoopTask
     162             :      * was called, with a work item that calls StopEventLoopTask).
     163             :      *
     164             :      * Consumers that call StartEventLoopTask must not call RunEventLoop.
     165             :      *
     166             :      * Consumers that call StartEventLoopTask must ensure that they call
     167             :      * StopEventLoopTask before calling Shutdown.
     168             :      */
     169             :     CHIP_ERROR StartEventLoopTask();
     170             : 
     171             :     /**
     172             :      * Stop processing of work items by the event loop.
     173             :      *
     174             :      * If called from outside work item processing, StopEventLoopTask guarantees
     175             :      * that any currently-executing work item completes execution and no more
     176             :      * work items will run after StopEventLoopTask returns.  This is generally
     177             :      * how StopEventLoopTask is used in conjunction with StartEventLoopTask.
     178             :      *
     179             :      * If called from inside work item processing, StopEventLoopTask makes no
     180             :      * guarantees about exactly when work item processing will stop.  What it
     181             :      * does guarantee is that if it is used this way in conjunction with
     182             :      * RunEventLoop then all work item processing will stop before RunEventLoop
     183             :      * returns.
     184             :      */
     185             :     CHIP_ERROR StopEventLoopTask();
     186             : 
     187             :     void LockChipStack();
     188             :     bool TryLockChipStack();
     189             :     void UnlockChipStack();
     190             :     void Shutdown();
     191             : 
     192             : #if CHIP_STACK_LOCK_TRACKING_ENABLED
     193             :     bool IsChipStackLockedByCurrentThread() const;
     194             : #endif
     195             : 
     196             :     /*
     197             :      * PostEvent can be called safely on any thread without locking the stack.
     198             :      * When called from a thread that is not doing the stack work item
     199             :      * processing, the event might get dispatched (on the work item processing
     200             :      * thread) before PostEvent returns.
     201             :      */
     202             :     [[nodiscard]] CHIP_ERROR PostEvent(const ChipDeviceEvent * event);
     203             :     void PostEventOrDie(const ChipDeviceEvent * event);
     204             : 
     205             :     /**
     206             :      * Generally this function has the same semantics as ScheduleWork
     207             :      * except it applies to background processing.
     208             :      *
     209             :      * Delegates to PostBackgroundEvent (which will delegate to PostEvent if
     210             :      * CHIP_DEVICE_CONFIG_ENABLE_BG_EVENT_PROCESSING is not true).
     211             :      */
     212             :     CHIP_ERROR ScheduleBackgroundWork(AsyncWorkFunct workFunct, intptr_t arg = 0);
     213             : 
     214             :     /**
     215             :      * Generally this function has the same semantics as PostEvent
     216             :      * except it applies to background processing.
     217             :      *
     218             :      * If CHIP_DEVICE_CONFIG_ENABLE_BG_EVENT_PROCESSING is not true, will delegate
     219             :      * to PostEvent.
     220             :      *
     221             :      * Only accepts events of type kCallWorkFunct or kNoOp.
     222             :      *
     223             :      * Returns CHIP_ERROR_INVALID_ARGUMENT if the event type is not acceptable.
     224             :      * Returns CHIP_ERROR_NO_MEMORY if resources are exhausted.
     225             :      */
     226             :     CHIP_ERROR PostBackgroundEvent(const ChipDeviceEvent * event);
     227             : 
     228             :     /**
     229             :      * Generally this function has the same semantics as RunEventLoop
     230             :      * except it applies to background processing.
     231             :      */
     232             :     void RunBackgroundEventLoop();
     233             : 
     234             :     /**
     235             :      * Generally this function has the same semantics as StartEventLoopTask
     236             :      * except it applies to background processing.
     237             :      */
     238             :     CHIP_ERROR StartBackgroundEventLoopTask();
     239             : 
     240             :     /**
     241             :      * Generally this function has the same semantics as StopEventLoopTask
     242             :      * except it applies to background processing.
     243             :      */
     244             :     CHIP_ERROR StopBackgroundEventLoopTask();
     245             : 
     246             : private:
     247             :     bool mInitialized                   = false;
     248             :     PlatformManagerDelegate * mDelegate = nullptr;
     249             : 
     250             :     // ===== Members for internal use by the following friends.
     251             : 
     252             :     friend class PlatformManagerImpl;
     253             :     friend class ConnectivityManagerImpl;
     254             :     friend class ConfigurationManagerImpl;
     255             :     friend class DeviceControlServer;
     256             :     friend class Dnssd::DiscoveryImplPlatform;
     257             :     friend class FailSafeContext;
     258             :     friend class TraitManager;
     259             :     friend class ThreadStackManagerImpl;
     260             :     friend class Internal::BLEManagerImpl;
     261             :     template <class>
     262             :     friend class Internal::GenericPlatformManagerImpl;
     263             :     template <class>
     264             :     friend class Internal::GenericPlatformManagerImpl_FreeRTOS;
     265             :     template <class>
     266             :     friend class Internal::GenericPlatformManagerImpl_POSIX;
     267             :     template <class>
     268             :     friend class Internal::GenericPlatformManagerImpl_Zephyr;
     269             :     template <class>
     270             :     friend class Internal::GenericConnectivityManagerImpl_Thread;
     271             :     template <class>
     272             :     friend class Internal::GenericThreadStackManagerImpl_OpenThread;
     273             :     template <class>
     274             :     friend class Internal::GenericThreadStackManagerImpl_OpenThread_LwIP;
     275             :     template <class>
     276             :     friend class Internal::GenericConfigurationManagerImpl;
     277             :     friend class System::PlatformEventing;
     278             : 
     279             :     void DispatchEvent(const ChipDeviceEvent * event);
     280             :     CHIP_ERROR StartChipTimer(System::Clock::Timeout duration);
     281             : 
     282             : protected:
     283             :     // Construction/destruction limited to subclasses.
     284             :     PlatformManager()  = default;
     285             :     ~PlatformManager() = default;
     286             : 
     287             :     // No copy, move or assignment.
     288             :     PlatformManager(const PlatformManager &)             = delete;
     289             :     PlatformManager(const PlatformManager &&)            = delete;
     290             :     PlatformManager & operator=(const PlatformManager &) = delete;
     291             : };
     292             : 
     293             : /**
     294             :  * Returns the public interface of the PlatformManager singleton object.
     295             :  *
     296             :  * chip applications should use this to access features of the PlatformManager object
     297             :  * that are common to all platforms.
     298             :  */
     299             : extern PlatformManager & PlatformMgr();
     300             : 
     301             : /**
     302             :  * Returns the platform-specific implementation of the PlatformManager singleton object.
     303             :  *
     304             :  * chip applications can use this to gain access to features of the PlatformManager
     305             :  * that are specific to the selected platform.
     306             :  */
     307             : extern PlatformManagerImpl & PlatformMgrImpl();
     308             : 
     309             : /**
     310             :  * @brief
     311             :  * RAII locking for PlatformManager to simplify management of
     312             :  * LockChipStack()/UnlockChipStack calls.
     313             :  */
     314             : class StackLock
     315             : {
     316             : public:
     317             :     StackLock() { PlatformMgr().LockChipStack(); }
     318             : 
     319             :     ~StackLock() { PlatformMgr().UnlockChipStack(); }
     320             : };
     321             : 
     322             : /**
     323             :  * @brief
     324             :  * RAII unlocking for PlatformManager to simplify management of
     325             :  * LockChipStack()/UnlockChipStack calls.
     326             :  */
     327             : class StackUnlock
     328             : {
     329             : public:
     330             :     StackUnlock() { PlatformMgr().UnlockChipStack(); }
     331             :     ~StackUnlock() { PlatformMgr().LockChipStack(); }
     332             : };
     333             : 
     334             : } // namespace DeviceLayer
     335             : } // namespace chip
     336             : 
     337             : /* Include a header file containing the implementation of the ConfigurationManager
     338             :  * object for the selected platform.
     339             :  */
     340             : #ifdef EXTERNAL_PLATFORMMANAGERIMPL_HEADER
     341             : #include EXTERNAL_PLATFORMMANAGERIMPL_HEADER
     342             : #elif defined(CHIP_DEVICE_LAYER_TARGET)
     343             : #define PLATFORMMANAGERIMPL_HEADER <platform/CHIP_DEVICE_LAYER_TARGET/PlatformManagerImpl.h>
     344             : #include PLATFORMMANAGERIMPL_HEADER
     345             : #endif // defined(CHIP_DEVICE_LAYER_TARGET)
     346             : 
     347             : namespace chip {
     348             : namespace DeviceLayer {
     349             : 
     350             : #if CHIP_STACK_LOCK_TRACKING_ENABLED
     351             : inline bool PlatformManager::IsChipStackLockedByCurrentThread() const
     352             : {
     353             :     return static_cast<const ImplClass *>(this)->_IsChipStackLockedByCurrentThread();
     354             : }
     355             : #endif
     356             : 
     357           0 : inline CHIP_ERROR PlatformManager::InitChipStack()
     358             : {
     359             :     // NOTE: this is NOT thread safe and cannot be as the chip stack lock is prepared by
     360             :     // InitChipStack itself on many platforms.
     361             :     //
     362             :     // In the future, this could be moved into specific platform code (where it can
     363             :     // be made thread safe). In general however, init twice
     364             :     // is likely a logic error and we may want to avoid that path anyway. Likely to
     365             :     // be done once code stabilizes a bit more.
     366           0 :     if (mInitialized)
     367             :     {
     368           0 :         return CHIP_NO_ERROR;
     369             :     }
     370             : 
     371           0 :     CHIP_ERROR err = static_cast<ImplClass *>(this)->_InitChipStack();
     372           0 :     mInitialized   = (err == CHIP_NO_ERROR);
     373           0 :     return err;
     374             : }
     375             : 
     376          16 : inline CHIP_ERROR PlatformManager::AddEventHandler(EventHandlerFunct handler, intptr_t arg)
     377             : {
     378          16 :     return static_cast<ImplClass *>(this)->_AddEventHandler(handler, arg);
     379             : }
     380             : 
     381           8 : inline void PlatformManager::RemoveEventHandler(EventHandlerFunct handler, intptr_t arg)
     382             : {
     383           8 :     static_cast<ImplClass *>(this)->_RemoveEventHandler(handler, arg);
     384           8 : }
     385             : 
     386           1 : inline void PlatformManager::HandleServerStarted()
     387             : {
     388           1 :     static_cast<ImplClass *>(this)->_HandleServerStarted();
     389           1 : }
     390             : 
     391           0 : inline void PlatformManager::HandleServerShuttingDown()
     392             : {
     393           0 :     static_cast<ImplClass *>(this)->_HandleServerShuttingDown();
     394           0 : }
     395             : 
     396           0 : inline CHIP_ERROR PlatformManager::ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg)
     397             : {
     398           0 :     return static_cast<ImplClass *>(this)->_ScheduleWork(workFunct, arg);
     399             : }
     400             : 
     401             : inline void PlatformManager::RunEventLoop()
     402             : {
     403             :     static_cast<ImplClass *>(this)->_RunEventLoop();
     404             : }
     405             : 
     406             : /**
     407             :  * @brief
     408             :  *  Starts the stack on its own task with an associated event queue
     409             :  *  to dispatch and handle events posted to that task.
     410             :  *
     411             :  *  This is thread-safe.
     412             :  *  This is *NOT SAFE* to call from within the CHIP event loop since it can grab the stack lock.
     413             :  */
     414           0 : inline CHIP_ERROR PlatformManager::StartEventLoopTask()
     415             : {
     416           0 :     return static_cast<ImplClass *>(this)->_StartEventLoopTask();
     417             : }
     418             : 
     419             : /**
     420             :  * @brief
     421             :  *  This will trigger the event loop to exit and block till it has exited the loop.
     422             :  *  This prevents the processing of any further events in the queue.
     423             :  *
     424             :  *  Additionally, this stops the CHIP task if the following criteria are met:
     425             :  *      1. One was created earlier through a call to StartEventLoopTask
     426             :  *      2. This call isn't being made from that task.
     427             :  *
     428             :  *  This is safe to call from any task.
     429             :  *  This is safe to call from within the CHIP event loop.
     430             :  *
     431             :  */
     432             : inline CHIP_ERROR PlatformManager::StopEventLoopTask()
     433             : {
     434             :     return static_cast<ImplClass *>(this)->_StopEventLoopTask();
     435             : }
     436             : 
     437             : /**
     438             :  * @brief
     439             :  *   Shuts down and cleans up the main objects in the CHIP stack.
     440             :  *   This DOES NOT stop the chip thread or event queue from running.
     441             :  *
     442             :  */
     443           0 : inline void PlatformManager::Shutdown()
     444             : {
     445           0 :     static_cast<ImplClass *>(this)->_Shutdown();
     446           0 :     mInitialized = false;
     447           0 : }
     448             : 
     449             : inline void PlatformManager::LockChipStack()
     450             : {
     451             :     static_cast<ImplClass *>(this)->_LockChipStack();
     452             : }
     453             : 
     454             : inline bool PlatformManager::TryLockChipStack()
     455             : {
     456             :     return static_cast<ImplClass *>(this)->_TryLockChipStack();
     457             : }
     458             : 
     459             : inline void PlatformManager::UnlockChipStack()
     460             : {
     461             :     static_cast<ImplClass *>(this)->_UnlockChipStack();
     462             : }
     463             : 
     464           1 : inline CHIP_ERROR PlatformManager::PostEvent(const ChipDeviceEvent * event)
     465             : {
     466           1 :     return static_cast<ImplClass *>(this)->_PostEvent(event);
     467             : }
     468             : 
     469           1 : inline void PlatformManager::PostEventOrDie(const ChipDeviceEvent * event)
     470             : {
     471           1 :     CHIP_ERROR status = static_cast<ImplClass *>(this)->_PostEvent(event);
     472           1 :     VerifyOrDieWithMsg(status == CHIP_NO_ERROR, DeviceLayer, "Failed to post event %d: %" CHIP_ERROR_FORMAT,
     473             :                        static_cast<int>(event->Type), status.Format());
     474           1 : }
     475             : 
     476           7 : inline CHIP_ERROR PlatformManager::ScheduleBackgroundWork(AsyncWorkFunct workFunct, intptr_t arg)
     477             : {
     478           7 :     return static_cast<ImplClass *>(this)->_ScheduleBackgroundWork(workFunct, arg);
     479             : }
     480             : 
     481             : inline CHIP_ERROR PlatformManager::PostBackgroundEvent(const ChipDeviceEvent * event)
     482             : {
     483             :     return static_cast<ImplClass *>(this)->_PostBackgroundEvent(event);
     484             : }
     485             : 
     486             : inline void PlatformManager::RunBackgroundEventLoop()
     487             : {
     488             :     static_cast<ImplClass *>(this)->_RunBackgroundEventLoop();
     489             : }
     490             : 
     491             : inline CHIP_ERROR PlatformManager::StartBackgroundEventLoopTask()
     492             : {
     493             :     return static_cast<ImplClass *>(this)->_StartBackgroundEventLoopTask();
     494             : }
     495             : 
     496             : inline CHIP_ERROR PlatformManager::StopBackgroundEventLoopTask()
     497             : {
     498             :     return static_cast<ImplClass *>(this)->_StopBackgroundEventLoopTask();
     499             : }
     500             : 
     501             : inline void PlatformManager::DispatchEvent(const ChipDeviceEvent * event)
     502             : {
     503             :     static_cast<ImplClass *>(this)->_DispatchEvent(event);
     504             : }
     505             : 
     506             : inline CHIP_ERROR PlatformManager::StartChipTimer(System::Clock::Timeout duration)
     507             : {
     508             :     return static_cast<ImplClass *>(this)->_StartChipTimer(duration);
     509             : }
     510             : 
     511             : } // namespace DeviceLayer
     512             : } // namespace chip

Generated by: LCOV version 1.14