Skip to content

Commit a188407

Browse files
Remove handling of the unitTestInject* bits in base MTRDevice.
These injections need to be handled by subclasses, because the subclasses do very different report processing and have different mechanisms for getting reports. Once these implementations are removed, the following become unreachable and can be removed: * _handleEventReport * _handleReportBegin * _handleAttributeReport * _handleReportEnd Once those are removed, the following become unreachable or unused and can be removed: * _receivingReport (always false) * _receivingPrimingReport (always false, because _receivingReport is always false) * _changeState * _callDelegateDeviceCachePrimed * unreportedEvents
1 parent 9520bef commit a188407

File tree

1 file changed

+3
-222
lines changed

1 file changed

+3
-222
lines changed

src/darwin/Framework/CHIP/MTRDevice.mm

+3-222
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,6 @@ @interface MTRDevice ()
260260
@property (nonatomic, readonly) os_unfair_lock timeSyncLock;
261261

262262
@property (nonatomic) chip::FabricIndex fabricIndex;
263-
@property (nonatomic) NSMutableArray<NSDictionary<NSString *, id> *> * unreportedEvents;
264-
@property (nonatomic) BOOL receivingReport;
265-
@property (nonatomic) BOOL receivingPrimingReport;
266263

267264
// TODO: instead of all the BOOL properties that are some facet of the state, move to internal state machine that has (at least):
268265
// Actively receiving report
@@ -371,6 +368,7 @@ - (instancetype)initForSubclassesWithNodeID:(NSNumber *)nodeID controller:(MTRDe
371368
_delegates = [NSMutableSet set];
372369
_deviceController = controller;
373370
_nodeID = nodeID;
371+
_state = MTRDeviceStateUnknown;
374372
}
375373

376374
return self;
@@ -820,41 +818,6 @@ - (void)_callFirstDelegateSynchronouslyWithBlock:(void (^)(id<MTRDeviceDelegate>
820818
}
821819
#endif
822820

823-
- (void)_callDelegateDeviceCachePrimed
824-
{
825-
os_unfair_lock_assert_owner(&self->_lock);
826-
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
827-
if ([delegate respondsToSelector:@selector(deviceCachePrimed:)]) {
828-
[delegate deviceCachePrimed:self];
829-
}
830-
}];
831-
}
832-
833-
// assume lock is held
834-
- (void)_changeState:(MTRDeviceState)state
835-
{
836-
os_unfair_lock_assert_owner(&self->_lock);
837-
MTRDeviceState lastState = _state;
838-
_state = state;
839-
if (lastState != state) {
840-
if (state != MTRDeviceStateReachable) {
841-
MTR_LOG("%@ reachability state change %lu => %lu, set estimated start time to nil", self, static_cast<unsigned long>(lastState),
842-
static_cast<unsigned long>(state));
843-
_estimatedStartTime = nil;
844-
_estimatedStartTimeFromGeneralDiagnosticsUpTime = nil;
845-
} else {
846-
MTR_LOG(
847-
"%@ reachability state change %lu => %lu", self, static_cast<unsigned long>(lastState), static_cast<unsigned long>(state));
848-
}
849-
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
850-
[delegate device:self stateChanged:state];
851-
}];
852-
} else {
853-
MTR_LOG(
854-
"%@ Not reporting reachability state change, since no change in state %lu => %lu", self, static_cast<unsigned long>(lastState), static_cast<unsigned long>(state));
855-
}
856-
}
857-
858821
#ifdef DEBUG
859822
- (MTRInternalDeviceState)_getInternalState
860823
{
@@ -906,20 +869,6 @@ - (BOOL)_deviceUsesThread
906869
return (networkCommissioningClusterFeatureMapValue & MTRNetworkCommissioningFeatureThreadNetworkInterface) != 0 ? YES : NO;
907870
}
908871

909-
- (void)_handleReportBegin
910-
{
911-
std::lock_guard lock(_lock);
912-
913-
_receivingReport = YES;
914-
if (_state != MTRDeviceStateReachable) {
915-
[self _changeState:MTRDeviceStateReachable];
916-
}
917-
918-
// If we currently don't have an established subscription, this must be a
919-
// priming report.
920-
_receivingPrimingReport = YES;
921-
}
922-
923872
- (NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> *)_clusterDataToPersistSnapshot
924873
{
925874
os_unfair_lock_assert_owner(&self->_lock);
@@ -1202,49 +1151,6 @@ - (void)setStorageBehaviorConfiguration:(MTRDeviceStorageBehaviorConfiguration *
12021151
[self _resetStorageBehaviorState];
12031152
}
12041153

1205-
- (void)_handleReportEnd
1206-
{
1207-
std::lock_guard lock(_lock);
1208-
_receivingReport = NO;
1209-
_receivingPrimingReport = NO;
1210-
_estimatedStartTimeFromGeneralDiagnosticsUpTime = nil;
1211-
1212-
[self _scheduleClusterDataPersistence];
1213-
1214-
// After the handling of the report, if we detected a device configuration change, notify the delegate
1215-
// of the same.
1216-
if (_deviceConfigurationChanged) {
1217-
[self _callDelegatesWithBlock:^(id<MTRDeviceDelegate> delegate) {
1218-
if ([delegate respondsToSelector:@selector(deviceConfigurationChanged:)]) {
1219-
[delegate deviceConfigurationChanged:self];
1220-
}
1221-
}];
1222-
_deviceConfigurationChanged = NO;
1223-
}
1224-
1225-
// Do this after the _deviceConfigurationChanged check, so that we don't
1226-
// call deviceConfigurationChanged: immediately after telling our delegate
1227-
// we are now primed.
1228-
//
1229-
// TODO: Maybe we shouldn't dispatch deviceConfigurationChanged: for the
1230-
// initial priming bits?
1231-
if (!_deviceCachePrimed) {
1232-
// This is the end of the priming sequence of data reports, so we have
1233-
// all the data for the device now.
1234-
_deviceCachePrimed = YES;
1235-
[self _callDelegateDeviceCachePrimed];
1236-
}
1237-
1238-
// For unit testing only
1239-
#ifdef DEBUG
1240-
[self _callDelegatesWithBlock:^(id testDelegate) {
1241-
if ([testDelegate respondsToSelector:@selector(unitTestReportEndForDevice:)]) {
1242-
[testDelegate unitTestReportEndForDevice:self];
1243-
}
1244-
}];
1245-
#endif
1246-
}
1247-
12481154
- (BOOL)_interestedPaths:(NSArray * _Nullable)interestedPaths includesAttributePath:(MTRAttributePath *)attributePath
12491155
{
12501156
for (id interestedPath in interestedPaths) {
@@ -1316,29 +1222,15 @@ - (void)_reportAttributes:(NSArray<NSDictionary<NSString *, id> *> *)attributes
13161222
}
13171223
}
13181224

1319-
- (void)_handleAttributeReport:(NSArray<NSDictionary<NSString *, id> *> *)attributeReport fromSubscription:(BOOL)isFromSubscription
1320-
{
1321-
std::lock_guard lock(_lock);
1322-
1323-
// _getAttributesToReportWithReportedValues will log attribute paths reported
1324-
[self _reportAttributes:[self _getAttributesToReportWithReportedValues:attributeReport fromSubscription:isFromSubscription]];
1325-
}
1326-
13271225
#ifdef DEBUG
13281226
- (void)unitTestInjectEventReport:(NSArray<NSDictionary<NSString *, id> *> *)eventReport
13291227
{
1330-
dispatch_async(self.queue, ^{
1331-
[self _handleEventReport:eventReport];
1332-
});
1228+
NSAssert(NO, @"Unit test injection of reports needs to be handled by subclasses");
13331229
}
13341230

13351231
- (void)unitTestInjectAttributeReport:(NSArray<NSDictionary<NSString *, id> *> *)attributeReport fromSubscription:(BOOL)isFromSubscription
13361232
{
1337-
dispatch_async(self.queue, ^{
1338-
[self _handleReportBegin];
1339-
[self _handleAttributeReport:attributeReport fromSubscription:isFromSubscription];
1340-
[self _handleReportEnd];
1341-
});
1233+
NSAssert(NO, @"Unit test injection of reports needs to be handled by subclasses");
13421234
}
13431235
#endif
13441236

@@ -1396,111 +1288,6 @@ - (BOOL)_interestedPaths:(NSArray * _Nullable)interestedPaths includesEventPath:
13961288
return filteredEvents;
13971289
}
13981290

1399-
- (void)_handleEventReport:(NSArray<NSDictionary<NSString *, id> *> *)eventReport
1400-
{
1401-
std::lock_guard lock(_lock);
1402-
1403-
NSDate * oldEstimatedStartTime = _estimatedStartTime;
1404-
// Combine with previous unreported events, if they exist
1405-
NSMutableArray * reportToReturn;
1406-
if (_unreportedEvents) {
1407-
reportToReturn = _unreportedEvents;
1408-
} else {
1409-
reportToReturn = [NSMutableArray array];
1410-
}
1411-
for (NSDictionary<NSString *, id> * eventDict in eventReport) {
1412-
// Whenever a StartUp event is received, reset the estimated start time
1413-
// New subscription case
1414-
// - Starts Unreachable
1415-
// - Start CASE and send subscription request
1416-
// - Receive priming report ReportBegin
1417-
// - Optionally receive UpTime attribute - update time and save start time estimate
1418-
// - Optionally receive StartUp event
1419-
// - Set estimated system time from event receipt time, or saved UpTime estimate if exists
1420-
// - ReportEnd handler clears the saved start time estimate based on UpTime
1421-
// Subscription dropped from client point of view case
1422-
// - Starts Unreachable
1423-
// - Resubscribe happens after some time, and then same as the above
1424-
// Server resuming subscription after reboot case
1425-
// - Starts Reachable
1426-
// - Receive priming report ReportBegin
1427-
// - Optionally receive UpTime attribute - update time and save value
1428-
// - Optionally receive StartUp event
1429-
// - Set estimated system time from event receipt time, or saved UpTime estimate if exists
1430-
// - ReportEnd handler clears the saved start time estimate based on UpTime
1431-
// Server resuming subscription after timeout case
1432-
// - Starts Reachable
1433-
// - Receive priming report ReportBegin
1434-
// - Optionally receive UpTime attribute - update time and save value
1435-
// - ReportEnd handler clears the saved start time estimate based on UpTime
1436-
MTREventPath * eventPath = eventDict[MTREventPathKey];
1437-
BOOL isStartUpEvent = (eventPath.cluster.unsignedLongValue == MTRClusterIDTypeBasicInformationID)
1438-
&& (eventPath.event.unsignedLongValue == MTREventIDTypeClusterBasicInformationEventStartUpID);
1439-
if (isStartUpEvent) {
1440-
if (_estimatedStartTimeFromGeneralDiagnosticsUpTime) {
1441-
// If UpTime was received, make use of it as mark of system start time
1442-
MTR_LOG("%@ StartUp event: set estimated start time forward to %@", self,
1443-
_estimatedStartTimeFromGeneralDiagnosticsUpTime);
1444-
_estimatedStartTime = _estimatedStartTimeFromGeneralDiagnosticsUpTime;
1445-
} else {
1446-
// If UpTime was not received, reset estimated start time in case of reboot
1447-
MTR_LOG("%@ StartUp event: set estimated start time to nil", self);
1448-
_estimatedStartTime = nil;
1449-
}
1450-
}
1451-
1452-
// If event time is of MTREventTimeTypeSystemUpTime type, then update estimated start time as needed
1453-
NSNumber * eventTimeTypeNumber = eventDict[MTREventTimeTypeKey];
1454-
if (!eventTimeTypeNumber) {
1455-
MTR_LOG_ERROR("%@ Event %@ missing event time type", self, eventDict);
1456-
continue;
1457-
}
1458-
MTREventTimeType eventTimeType = (MTREventTimeType) eventTimeTypeNumber.unsignedIntegerValue;
1459-
if (eventTimeType == MTREventTimeTypeSystemUpTime) {
1460-
NSNumber * eventTimeValueNumber = eventDict[MTREventSystemUpTimeKey];
1461-
if (!eventTimeValueNumber) {
1462-
MTR_LOG_ERROR("%@ Event %@ missing event time value", self, eventDict);
1463-
continue;
1464-
}
1465-
NSTimeInterval eventTimeValue = eventTimeValueNumber.doubleValue;
1466-
NSDate * potentialSystemStartTime = [NSDate dateWithTimeIntervalSinceNow:-eventTimeValue];
1467-
if (!_estimatedStartTime || ([potentialSystemStartTime compare:_estimatedStartTime] == NSOrderedAscending)) {
1468-
_estimatedStartTime = potentialSystemStartTime;
1469-
}
1470-
}
1471-
1472-
NSMutableDictionary * eventToReturn = eventDict.mutableCopy;
1473-
if (_receivingPrimingReport) {
1474-
eventToReturn[MTREventIsHistoricalKey] = @(YES);
1475-
} else {
1476-
eventToReturn[MTREventIsHistoricalKey] = @(NO);
1477-
}
1478-
1479-
[reportToReturn addObject:eventToReturn];
1480-
}
1481-
if (oldEstimatedStartTime != _estimatedStartTime) {
1482-
MTR_LOG("%@ updated estimated start time to %@", self, _estimatedStartTime);
1483-
}
1484-
1485-
__block BOOL delegatesCalled = NO;
1486-
[self _iterateDelegatesWithBlock:^(MTRDeviceDelegateInfo * delegateInfo) {
1487-
// _iterateDelegatesWithBlock calls this with an autorelease pool, and so temporary filtered event reports don't bloat memory
1488-
NSArray<NSDictionary<NSString *, id> *> * filteredEvents = [self _filteredEvents:reportToReturn forInterestedPaths:delegateInfo.interestedPathsForEvents];
1489-
if (filteredEvents.count) {
1490-
[delegateInfo callDelegateWithBlock:^(id<MTRDeviceDelegate> delegate) {
1491-
[delegate device:self receivedEventReport:filteredEvents];
1492-
}];
1493-
delegatesCalled = YES;
1494-
}
1495-
}];
1496-
if (delegatesCalled) {
1497-
_unreportedEvents = nil;
1498-
} else {
1499-
// save unreported events
1500-
_unreportedEvents = reportToReturn;
1501-
}
1502-
}
1503-
15041291
#ifdef DEBUG
15051292
- (void)unitTestClearClusterData
15061293
{
@@ -1639,7 +1426,6 @@ - (void)_setCachedAttributeValue:(MTRDeviceDataValueDictionary _Nullable)value f
16391426

16401427
if (value != nil
16411428
&& isFromSubscription
1642-
&& !_receivingPrimingReport
16431429
&& AttributeHasChangesOmittedQuality(path)) {
16441430
// Do not persist new values for Changes Omitted Quality (aka C Quality)
16451431
// attributes unless they're part of a Priming Report or from a read response.
@@ -2374,11 +2160,6 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
23742160
continue;
23752161
}
23762162

2377-
// Additional signal to help mark events as being received during priming report in the event the device rebooted and we get a subscription resumption priming report without noticing it became unreachable first
2378-
if (_receivingReport && AttributeHasChangesOmittedQuality(attributePath)) {
2379-
_receivingPrimingReport = YES;
2380-
}
2381-
23822163
// check if value is different than cache, and report if needed
23832164
BOOL shouldReportAttribute = NO;
23842165

0 commit comments

Comments
 (0)