Skip to content

Commit 78003be

Browse files
Update and Document ICDManager interface
1 parent 511c974 commit 78003be

File tree

9 files changed

+558
-71
lines changed

9 files changed

+558
-71
lines changed

examples/lit-icd-app/nrfconnect/main/AppTask.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
296296

297297
void AppTask::IcdUatEventHandler(const AppEvent &)
298298
{
299-
Server::GetInstance().GetICDManager().UpdateOperationState(ICDManager::OperationalState::ActiveMode);
299+
// Temporarily claim network activity, until we implement a "user trigger" reason for ICD wakeups.
300+
PlatformMgr().ScheduleWork([](intptr_t) { ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); });
300301
}
301302

302303
void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)

examples/platform/silabs/BaseApplication.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,7 @@ void BaseApplication::ButtonHandler(AppEvent * aEvent)
515515
SILABS_LOG("Network is already provisioned, Ble advertisement not enabled");
516516
#if CHIP_CONFIG_ENABLE_ICD_SERVER
517517
// Temporarily claim network activity, until we implement a "user trigger" reason for ICD wakeups.
518-
PlatformMgr().LockChipStack();
519-
ICDNotifier::GetInstance().NotifyNetworkActivityNotification();
520-
PlatformMgr().UnlockChipStack();
518+
PlatformMgr().ScheduleWork([](intptr_t) { ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); });
521519
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
522520
}
523521
}

src/app/icd/server/ICDManager.cpp

+15-8
Original file line numberDiff line numberDiff line change
@@ -378,12 +378,13 @@ void ICDManager::UpdateICDMode()
378378
if (ICDConfigurationData::GetInstance().GetICDMode() != tempMode)
379379
{
380380
ICDConfigurationData::GetInstance().SetICDMode(tempMode);
381-
postObserverEvent(ObserverEventType::ICDModeChange);
382381

383382
// Can't use attribute accessors/Attributes::OperatingMode::Set in unit tests
384383
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
385384
Attributes::OperatingMode::Set(kRootEndpointId, static_cast<OperatingModeEnum>(tempMode));
386385
#endif
386+
387+
postObserverEvent(ObserverEventType::ICDModeChange);
387388
}
388389

389390
// When in SIT mode, the slow poll interval SHOULDN'T be greater than the SIT mode polling threshold, per spec.
@@ -433,6 +434,8 @@ void ICDManager::UpdateOperationState(OperationalState state)
433434
{
434435
ChipLogError(AppServer, "Failed to set Slow Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format());
435436
}
437+
438+
postObserverEvent(ObserverEventType::EnterIdleMode);
436439
}
437440
else if (state == OperationalState::ActiveMode)
438441
{
@@ -447,17 +450,22 @@ void ICDManager::UpdateOperationState(OperationalState state)
447450

448451
if (activeModeDuration == kZero && !mKeepActiveFlags.HasAny())
449452
{
450-
// A Network Activity triggered the active mode and activeModeDuration is 0.
453+
// Network Activity triggered the active mode and activeModeDuration is 0.
451454
// Stay active for at least Active Mode Threshold.
452455
activeModeDuration = ICDConfigurationData::GetInstance().GetActiveModeThreshold();
453456
}
454457

455458
DeviceLayer::SystemLayer().StartTimer(activeModeDuration, OnActiveModeDone, this);
456459

457460
Milliseconds32 activeModeJitterInterval = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS);
461+
// TODO(#33074): Edge case when we transition to IdleMode with this conditio being true
462+
// (activeModeDuration == kZero && !mKeepActiveFlags.HasAny())
458463
activeModeJitterInterval =
459464
(activeModeDuration >= activeModeJitterInterval) ? activeModeDuration - activeModeJitterInterval : kZero;
460465

466+
// Reset this flag when we enter ActiveMode to avoid having a feedback loop that keeps us indefinitly in
467+
// ActiveMode.
468+
mTransitionToIdleCalled = false;
461469
DeviceLayer::SystemLayer().StartTimer(activeModeJitterInterval, OnTransitionToIdle, this);
462470

463471
CHIP_ERROR err =
@@ -504,10 +512,6 @@ void ICDManager::OnIdleModeDone(System::Layer * aLayer, void * appState)
504512
{
505513
ICDManager * pICDManager = reinterpret_cast<ICDManager *>(appState);
506514
pICDManager->UpdateOperationState(OperationalState::ActiveMode);
507-
508-
// We only reset this flag when idle mode is complete to avoid re-triggering the check when an event brings us back to active,
509-
// which could cause a loop.
510-
pICDManager->mTransitionToIdleCalled = false;
511515
}
512516

513517
void ICDManager::OnActiveModeDone(System::Layer * aLayer, void * appState)
@@ -532,10 +536,10 @@ void ICDManager::OnTransitionToIdle(System::Layer * aLayer, void * appState)
532536
}
533537

534538
/* ICDListener functions. */
539+
535540
void ICDManager::OnKeepActiveRequest(KeepActiveFlags request)
536541
{
537542
assertChipStackLockedByCurrentThread();
538-
539543
VerifyOrReturn(request < KeepActiveFlagsValues::kInvalidFlag);
540544

541545
if (request.Has(KeepActiveFlag::kExchangeContextOpen))
@@ -560,7 +564,6 @@ void ICDManager::OnKeepActiveRequest(KeepActiveFlags request)
560564
void ICDManager::OnActiveRequestWithdrawal(KeepActiveFlags request)
561565
{
562566
assertChipStackLockedByCurrentThread();
563-
564567
VerifyOrReturn(request < KeepActiveFlagsValues::kInvalidFlag);
565568

566569
if (request.Has(KeepActiveFlag::kExchangeContextOpen))
@@ -697,6 +700,10 @@ void ICDManager::postObserverEvent(ObserverEventType event)
697700
obs->mObserver->OnEnterActiveMode();
698701
return Loop::Continue;
699702
}
703+
case ObserverEventType::EnterIdleMode: {
704+
obs->mObserver->OnEnterIdleMode();
705+
return Loop::Continue;
706+
}
700707
case ObserverEventType::TransitionToIdle: {
701708
obs->mObserver->OnTransitionToIdle();
702709
return Loop::Continue;

src/app/icd/server/ICDManager.h

+107-37
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class TestICDManager;
5757
class ICDManager : public ICDListener, public TestEventTriggerHandler
5858
{
5959
public:
60-
// This structure is used for the creation an ObjectPool of ICDStateObserver pointers
60+
/**
61+
* @brief This structure is used for the creation an ObjectPool of ICDStateObserver pointers
62+
*/
6163
struct ObserverPointer
6264
{
6365
ObserverPointer(ICDStateObserver * obs) : mObserver(obs) {}
@@ -71,11 +73,14 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler
7173
ActiveMode,
7274
};
7375

74-
// This enum class represents to all ICDStateObserver callbacks available from the
75-
// mStateObserverPool for the ICDManager.
76+
/**
77+
* @brief This enum class represents to all ICDStateObserver callbacks available from the
78+
* mStateObserverPool for the ICDManager.
79+
*/
7680
enum class ObserverEventType : uint8_t
7781
{
7882
EnterActiveMode,
83+
EnterIdleMode,
7984
TransitionToIdle,
8085
ICDModeChange,
8186
};
@@ -85,22 +90,31 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler
8590
* This type can be used to implement specific verifiers that can be used in the CheckInMessagesWouldBeSent function.
8691
* The goal is to avoid having multiple functions that implement the iterator loop with only the check changing.
8792
*
88-
* @return true if at least one Check-In message would be sent
89-
* false No Check-In messages would be sent
93+
* @return true: if at least one Check-In message would be sent
94+
* false: No Check-In messages would be sent
9095
*/
91-
9296
using ShouldCheckInMsgsBeSentFunction = bool(FabricIndex aFabricIndex, NodeId subjectID);
9397

94-
ICDManager() {}
98+
ICDManager() = default;
99+
~ICDManager() = default;
100+
95101
void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore,
96-
Messaging::ExchangeManager * exchangeManager, SubscriptionsInfoProvider * manager);
102+
Messaging::ExchangeManager * exchangeManager, SubscriptionsInfoProvider * subInfoProvider);
97103
void Shutdown();
98-
void UpdateICDMode();
99-
void UpdateOperationState(OperationalState state);
100-
void SetKeepActiveModeRequirements(KeepActiveFlags flag, bool state);
101-
bool IsKeepActive() { return mKeepActiveFlags.HasAny(); }
104+
105+
/**
106+
* @brief SupportsFeature verifies if a given FeatureMap bit is enabled
107+
*
108+
* @param[in] feature FeatureMap bit to verify
109+
*
110+
* @return true: if the FeatureMap bit is enabled in the ICDM cluster attribute.
111+
* false: ff the FeatureMap bit is not enabled in the ICDM cluster attribute.
112+
* if we failed to read the FeatureMap attribute.
113+
*/
102114
bool SupportsFeature(Clusters::IcdManagement::Feature feature);
115+
103116
ICDConfigurationData::ICDMode GetICDMode() { return ICDConfigurationData::GetInstance().GetICDMode(); };
117+
104118
/**
105119
* @brief Adds the referenced observer in parameters to the mStateObserverPool
106120
* A maximum of CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE observers can be concurrently registered
@@ -111,36 +125,29 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler
111125

112126
/**
113127
* @brief Remove the referenced observer in parameters from the mStateObserverPool
128+
* If the observer is not present in the object pool, we do nothing
114129
*/
115130
void ReleaseObserver(ICDStateObserver * observer);
116131

117-
/**
118-
* @brief Associates the ObserverEventType parameters to the correct
119-
* ICDStateObservers function and calls it for all observers in the mStateObserverPool
120-
*/
121-
void postObserverEvent(ObserverEventType event);
122-
OperationalState GetOperationalState() { return mOperationalState; }
123-
124132
/**
125133
* @brief Ensures that the remaining Active Mode duration is at least the smaller of 30000 milliseconds and stayActiveDuration.
126134
*
127-
* @param stayActiveDuration The duration (in milliseconds) requested by the client to stay in Active Mode
135+
* @param[in] stayActiveDuration The duration (in milliseconds) requested by the client to stay in Active Mode
128136
* @return The duration (in milliseconds) the device will stay in Active Mode
129137
*/
130138
uint32_t StayActiveRequest(uint32_t stayActiveDuration);
131139

132140
/**
133141
* @brief TestEventTriggerHandler for the ICD feature set
134142
*
135-
* @param eventTrigger Event trigger to handle.
143+
* @param[in] eventTrigger Event trigger to handle.
144+
*
136145
* @return CHIP_ERROR CHIP_NO_ERROR - No erros during the processing
137146
* CHIP_ERROR_INVALID_ARGUMENT - eventTrigger isn't a valid value
138147
*/
139148
CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override;
140149

141150
#if CHIP_CONFIG_ENABLE_ICD_CIP
142-
void SendCheckInMsgs();
143-
144151
/**
145152
* @brief Trigger the ICDManager to send Check-In message if necessary
146153
*
@@ -160,47 +167,106 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler
160167

161168
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
162169
void SetTestFeatureMapValue(uint32_t featureMap) { mFeatureMap = featureMap; };
163-
#if !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION && CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
170+
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
164171
bool GetIsBootUpResumeSubscriptionExecuted() { return mIsBootUpResumeSubscriptionExecuted; };
165172
#endif // !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION && CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
166173
#endif
167174

168175
// Implementation of ICDListener functions.
169176
// Callers must origin from the chip task context or hold the ChipStack lock.
177+
170178
void OnNetworkActivity() override;
171179
void OnKeepActiveRequest(KeepActiveFlags request) override;
172180
void OnActiveRequestWithdrawal(KeepActiveFlags request) override;
173181
void OnICDManagementServerEvent(ICDManagementEvents event) override;
174182
void OnSubscriptionReport() override;
175183

176-
protected:
184+
private:
177185
friend class TestICDManager;
186+
/**
187+
* @brief UpdateICDMode checks in which ICDMode (SIT or LIT) the ICD can go to and updates the mode if necessary.
188+
* For a SIT ICD, the function does nothing.
189+
* For a LIT ICD, the function checks if the ICD has a registration in the ICDMonitoringTable to determine in which
190+
* ICDMode the ICD must be in.
191+
*/
192+
void UpdateICDMode();
193+
194+
/**
195+
* @brief UpdateOperationState updates the OperationState of the ICD to the requested one.
196+
* IdleMode -> IdleMode : No actions are necessary, do nothing.
197+
* IdleMode -> ActiveMode : Transition the device to ActiveMode, start the ActiveMode timer and triggers all necessary
198+
* operations. These operations could be : Send Check-In messages
199+
* Send subscription reports
200+
* Process user actions
201+
* ActiveMode -> ActiveMode : Increase remaining ActiveMode timer to one ActiveModeThreshold.
202+
* If ActiveModeThreshold is 0, do nothing.
203+
* ActiveMode -> IdleMode : Transition ICD to IdleMode and starts the IdleMode timer.
204+
*
205+
* @param state requested OperationalState for the ICD to transition to
206+
*/
207+
void UpdateOperationState(OperationalState state);
208+
209+
/**
210+
* @brief Set or Remove a keep ActiveMode requirement for the given flag
211+
* If state is true and the ICD is in IdleMode, transition the ICD to ActiveMode
212+
* If state is false and the ICD is in ActiveMode, verifies if we can transition the ICD to IdleMode.
213+
* If we can, transition the ICD to IdleMode.
214+
*
215+
* @param flag KeepActiveFlag to remove or add
216+
* @param state true: adding a flag requirement
217+
* false: removing a flag requirement
218+
*/
219+
void SetKeepActiveModeRequirements(KeepActiveFlags flag, bool state);
220+
221+
/**
222+
* @brief Associates the ObserverEventType parameters to the correct
223+
* ICDStateObservers function and calls it for all observers in the mStateObserverPool
224+
*/
225+
void postObserverEvent(ObserverEventType event);
178226

179227
/**
180-
* @brief Hepler function that extends the Active Mode duration as well as the Active Mode Jitter timer for the transition to
181-
* iddle mode.
228+
* @brief Hepler function that extends the ActiveMode timer as well as the Active Mode Jitter timer for the transition to
229+
* idle mode event.
182230
*/
183231
void ExtendActiveMode(System::Clock::Milliseconds16 extendDuration);
184232

233+
/**
234+
* @brief Timer callback function for when the IdleMode timer expires
235+
*
236+
* @param appState pointer to the ICDManager
237+
*/
185238
static void OnIdleModeDone(System::Layer * aLayer, void * appState);
239+
240+
/**
241+
* @brief Timer callback function for when the ActiveMode timer expires
242+
*
243+
* @param appState pointer to the ICDManager
244+
*/
186245
static void OnActiveModeDone(System::Layer * aLayer, void * appState);
187246

188247
/**
189-
* @brief Callback function called shortly before the device enters idle mode to allow checks to be made. This is currently only
190-
* called once to prevent entering in a loop if some events re-trigger this check (for instance if a check for subscription
191-
* before entering idle mode leads to emiting a report, we will re-enter UpdateOperationState and check again for subscription,
192-
* etc.)
248+
* @brief Timer Callback function called shortly before the device enters idle mode to allow checks to be made.
249+
* This is currently only called once to prevent entering in a loop if some events re-trigger this check (for instance if
250+
* a check for subscriptions before entering idle mode leads to emiting a report, we will re-enter UpdateOperationState
251+
* and check again for subscription, etc.)
252+
*
253+
* @param appState pointer to the ICDManager
193254
*/
194255
static void OnTransitionToIdle(System::Layer * aLayer, void * appState);
195256

196257
#if CHIP_CONFIG_ENABLE_ICD_CIP
197-
uint8_t mCheckInRequestCount = 0;
198-
#endif // CHIP_CONFIG_ENABLE_ICD_CIP
199-
200-
uint8_t mOpenExchangeContextCount = 0;
258+
/**
259+
* @brief Function triggers all necessary Check-In messages to be sent.
260+
*
261+
* @note For each ICDMonitoring entry, we check if should send a Check-In message with
262+
* ShouldCheckInMsgsBeSentAtActiveModeFunction. If we should, we allocate an ICDCheckInSender which tries to send a
263+
* Check-In message to the registered client.
264+
*/
265+
void SendCheckInMsgs();
201266

202-
private:
203-
#if CHIP_CONFIG_ENABLE_ICD_CIP
267+
/**
268+
* @brief See function implementation in .cpp for details on this function.
269+
*/
204270
bool ShouldCheckInMsgsBeSentAtActiveModeFunction(FabricIndex aFabricIndex, NodeId subjectID);
205271

206272
/**
@@ -221,11 +287,15 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler
221287
OperationalState mOperationalState = OperationalState::ActiveMode;
222288
bool mTransitionToIdleCalled = false;
223289
ObjectPool<ObserverPointer, CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE> mStateObserverPool;
290+
uint8_t mOpenExchangeContextCount = 0;
224291

225292
#if CHIP_CONFIG_ENABLE_ICD_CIP
293+
uint8_t mCheckInRequestCount = 0;
294+
226295
#if !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION && CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
227296
bool mIsBootUpResumeSubscriptionExecuted = false;
228297
#endif // !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION && CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
298+
229299
PersistentStorageDelegate * mStorage = nullptr;
230300
FabricTable * mFabricTable = nullptr;
231301
Messaging::ExchangeManager * mExchangeManager = nullptr;

0 commit comments

Comments
 (0)