LCOV - code coverage report
Current view: top level - app - FailSafeContext.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 23 60 38.3 %
Date: 2024-02-15 08:20:41 Functions: 3 9 33.3 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2022 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             : /**
      19             :  *    @file
      20             :  *          Provides the implementation of the FailSafeContext object.
      21             :  */
      22             : #include "FailSafeContext.h"
      23             : #include <app/icd/server/ICDServerConfig.h>
      24             : #if CHIP_CONFIG_ENABLE_ICD_SERVER
      25             : #include <app/icd/server/ICDNotifier.h> // nogncheck
      26             : #endif
      27             : #include <lib/support/SafeInt.h>
      28             : #include <platform/CHIPDeviceConfig.h>
      29             : #include <platform/ConnectivityManager.h>
      30             : #include <platform/internal/CHIPDeviceLayerInternal.h>
      31             : 
      32             : using namespace chip::DeviceLayer;
      33             : 
      34             : namespace chip {
      35             : namespace app {
      36             : 
      37           0 : void FailSafeContext::HandleArmFailSafeTimer(System::Layer * layer, void * aAppState)
      38             : {
      39           0 :     FailSafeContext * failSafeContext = reinterpret_cast<FailSafeContext *>(aAppState);
      40           0 :     failSafeContext->FailSafeTimerExpired();
      41           0 : }
      42             : 
      43           0 : void FailSafeContext::HandleMaxCumulativeFailSafeTimer(System::Layer * layer, void * aAppState)
      44             : {
      45           0 :     FailSafeContext * failSafeContext = reinterpret_cast<FailSafeContext *>(aAppState);
      46           0 :     failSafeContext->FailSafeTimerExpired();
      47           0 : }
      48             : 
      49           0 : void FailSafeContext::HandleDisarmFailSafe(intptr_t arg)
      50             : {
      51           0 :     FailSafeContext * failSafeContext = reinterpret_cast<FailSafeContext *>(arg);
      52           0 :     failSafeContext->DisarmFailSafe();
      53           0 : }
      54             : 
      55           4 : void FailSafeContext::SetFailSafeArmed(bool armed)
      56             : {
      57             : #if CHIP_CONFIG_ENABLE_ICD_SERVER
      58             :     if (IsFailSafeArmed() != armed)
      59             :     {
      60             :         ICDNotifier::GetInstance().BroadcastActiveRequest(ICDListener::KeepActiveFlag::kFailSafeArmed, armed);
      61             :     }
      62             : #endif
      63           4 :     mFailSafeArmed = armed;
      64           4 : }
      65             : 
      66           0 : void FailSafeContext::FailSafeTimerExpired()
      67             : {
      68           0 :     if (!IsFailSafeArmed())
      69             :     {
      70             :         // In case this was a pending timer event in event loop, and we had
      71             :         // done CommissioningComplete or manual disarm.
      72           0 :         return;
      73             :     }
      74             : 
      75           0 :     ChipLogProgress(FailSafe, "Fail-safe timer expired");
      76           0 :     ScheduleFailSafeCleanup(mFabricIndex, mAddNocCommandHasBeenInvoked, mUpdateNocCommandHasBeenInvoked);
      77             : }
      78             : 
      79           0 : void FailSafeContext::ScheduleFailSafeCleanup(FabricIndex fabricIndex, bool addNocCommandInvoked, bool updateNocCommandInvoked)
      80             : {
      81             :     // Not armed, but busy so cannot rearm (via General Commissioning cluster) until the flushing
      82             :     // via `HandleDisarmFailSafe` path is complete.
      83             :     // TODO: This is hacky and we need to remove all this event pushing business, to keep all fail-safe logic-only.
      84           0 :     mFailSafeBusy = true;
      85             : 
      86           0 :     SetFailSafeArmed(false);
      87             : 
      88             :     ChipDeviceEvent event;
      89           0 :     event.Type                                                = DeviceEventType::kFailSafeTimerExpired;
      90           0 :     event.FailSafeTimerExpired.fabricIndex                    = fabricIndex;
      91           0 :     event.FailSafeTimerExpired.addNocCommandHasBeenInvoked    = addNocCommandInvoked;
      92           0 :     event.FailSafeTimerExpired.updateNocCommandHasBeenInvoked = updateNocCommandInvoked;
      93           0 :     CHIP_ERROR status                                         = PlatformMgr().PostEvent(&event);
      94             : 
      95           0 :     if (status != CHIP_NO_ERROR)
      96             :     {
      97           0 :         ChipLogError(FailSafe, "Failed to post fail-safe timer expired: %" CHIP_ERROR_FORMAT, status.Format());
      98             :     }
      99             : 
     100           0 :     PlatformMgr().ScheduleWork(HandleDisarmFailSafe, reinterpret_cast<intptr_t>(this));
     101           0 : }
     102             : 
     103           2 : CHIP_ERROR FailSafeContext::ArmFailSafe(FabricIndex accessingFabricIndex, System::Clock::Seconds16 expiryLengthSeconds)
     104             : {
     105           2 :     VerifyOrReturnError(!IsFailSafeBusy(), CHIP_ERROR_INCORRECT_STATE);
     106             : 
     107           2 :     CHIP_ERROR err           = CHIP_NO_ERROR;
     108           2 :     bool cancelTimersIfError = false;
     109           2 :     if (!IsFailSafeArmed())
     110             :     {
     111           2 :         System::Clock::Timeout maxCumulativeTimeout = System::Clock::Seconds32(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC);
     112           2 :         SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(maxCumulativeTimeout, HandleMaxCumulativeFailSafeTimer, this));
     113           2 :         cancelTimersIfError = true;
     114             :     }
     115             : 
     116           2 :     SuccessOrExit(
     117             :         err = DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(expiryLengthSeconds), HandleArmFailSafeTimer, this));
     118             : 
     119           2 :     SetFailSafeArmed(true);
     120           2 :     mFabricIndex = accessingFabricIndex;
     121             : 
     122           2 : exit:
     123             : 
     124           2 :     if (err != CHIP_NO_ERROR && cancelTimersIfError)
     125             :     {
     126           0 :         DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
     127           0 :         DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
     128             :     }
     129           2 :     return err;
     130             : }
     131             : 
     132           2 : void FailSafeContext::DisarmFailSafe()
     133             : {
     134           2 :     DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
     135           2 :     DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
     136             : 
     137           2 :     ResetState();
     138             : 
     139           2 :     ChipLogProgress(FailSafe, "Fail-safe cleanly disarmed");
     140           2 : }
     141             : 
     142           0 : void FailSafeContext::ForceFailSafeTimerExpiry()
     143             : {
     144           0 :     if (!IsFailSafeArmed())
     145             :     {
     146           0 :         return;
     147             :     }
     148             : 
     149             :     // Cancel the timer since we force its action
     150           0 :     DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
     151           0 :     DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
     152             : 
     153           0 :     FailSafeTimerExpired();
     154             : }
     155             : 
     156             : } // namespace app
     157             : } // namespace chip

Generated by: LCOV version 1.14