Skip to content

Commit

Permalink
Make AttributeAccessInterface and CommandHandlerInterface registries …
Browse files Browse the repository at this point in the history
…consistent as objects with singletons (project-chip#34462)

* Switch CHI registry to an object

* Switch CHI registry to an object

* Prepare the AAI registry to use an object

* Replace unregister

* Replace the register

* Update the getter

* Restyle

* Fix unregister

* Fix typo

* Fix namespacing for instance

* Do not make IME auto-clear command handlers

* Make spellcheck happy

* Remove chip::app prefix throughout

* Fix compile error

* One more compile fix

* One more compile fix

* make tv-app compile

* Update examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp

Co-authored-by: Boris Zbarsky <[email protected]>

* Update examples/tv-app/android/java/AppImpl.cpp

Co-authored-by: Boris Zbarsky <[email protected]>

* Update register/unregister names

* Fix endpoint id usage that was awkward in aai

* Restyle

* Code simplification and some namespace removal

* Fix comment

* re-order of methods

* One more move to preserve previous order

* Restyle

* Add back the odd clear

* Add missing invalidation of AAI cache

* Fix compile

* one more compile fix

* more compile fixes

---------

Co-authored-by: Andrei Litvin <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>
  • Loading branch information
3 people authored and austina-csa committed Aug 12, 2024
1 parent 95abd8d commit a7416a6
Show file tree
Hide file tree
Showing 98 changed files with 305 additions and 258 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ ending in the cluster initialization code.
EmberAfInitializeAttributes - ember attribute storage - for all attributes
marked as “RAM” in the zap, sets defaults in the storage
Matter<Cluster>PluginServerCallback - .h is a generated file, .cpp impl is done
in the server cluster code. Use this to setup the cluster and do attribute
overrides registerAttributeAccessOverride - use this if you want to handle
attribute reads and writes externally
in the server cluster code. Use this to setup the cluster and setup overrides in
chip::app::AttributeAccessInterfaceRegistry::Instance().Register - use this if
you want to handle attribute reads and writes externally

Blue sections can be overridden.

Expand Down
24 changes: 20 additions & 4 deletions docs/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,26 @@ independent of the InteractionModelEngine class.
The following replacements exist:

- `chip::app::InteractionModelEngine::RegisterCommandHandler` replaced by
`chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler`
`chip::app::CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler`
- `chip::app::InteractionModelEngine::UnregisterCommandHandler` replaced by
`chip::app::CommandHandlerInterfaceRegistry::UnregisterCommandHandler`
`chip::app::CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler`
- `chip::app::InteractionModelEngine::FindCommandHandler` replaced by
`chip::app::CommandHandlerInterfaceRegistry::GetCommandHandler`
`chip::app::CommandHandlerInterfaceRegistry::Instance().GetCommandHandler`
- `chip::app::InteractionModelEngine::UnregisterCommandHandlers` replaced by
`chip::app::CommandHandlerInterfaceRegistry::UnregisterAllCommandHandlersForEndpoint`
`chip::app::CommandHandlerInterfaceRegistry::Instance().UnregisterAllCommandHandlersForEndpoint`

### AttributeAccessInterface registration and removal

A new object exists for the attribute access interface registry, accessible as
`chip::app::AttributeHandlerInterfaceRegistry::Instance()`

Replacements for methods are:

- `registerAttributeAccessOverride` replaced by
`chip::app::AttributeAccessInterfaceRegistry::Instance().Register`
- `unregisterAttributeAccessOverride` replaced by
`chip::app::AttributeAccessInterfaceRegistry::Instance().Unregister`
- `unregisterAllAttributeAccessOverridesForEndpoint` replaced by
`chip::app::AttributeAccessInterfaceRegistry::Instance().UnregisterAllForEndpoint`
- `chip::app::GetAttributeAccessOverride` replaced by
`chip::app::AttributeAccessInterfaceRegistry::Instance().Get`
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr

void MatterActionsPluginServerInitCallback()
{
registerAttributeAccessOverride(&gAttrAccess);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,6 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint)
{
VerifyOrDie(mFanControlManager == nullptr);
mFanControlManager = new FanControlManager(endpoint);
registerAttributeAccessOverride(mFanControlManager);
AttributeAccessInterfaceRegistry::Instance().Register(mFanControlManager);
FanControl::SetDefaultDelegate(endpoint, mFanControlManager);
}
2 changes: 1 addition & 1 deletion examples/bridge-app/asr/src/bridged-actions-stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr

void MatterActionsPluginServerInitCallback(void)
{
registerAttributeAccessOverride(&gAttrAccess);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
}
2 changes: 1 addition & 1 deletion examples/bridge-app/esp32/main/DeviceCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr

void MatterActionsPluginServerInitCallback(void)
{
registerAttributeAccessOverride(&gAttrAccess);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
}
2 changes: 1 addition & 1 deletion examples/bridge-app/linux/bridged-actions-stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr

void MatterActionsPluginServerInitCallback()
{
registerAttributeAccessOverride(&gAttrAccess);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
}
2 changes: 1 addition & 1 deletion examples/bridge-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ void ApplicationInit()
}
}

registerAttributeAccessOverride(&gPowerAttrAccess);
AttributeAccessInterfaceRegistry::Instance().Register(&gPowerAttrAccess);
}

void ApplicationShutdown() {}
Expand Down
2 changes: 1 addition & 1 deletion examples/bridge-app/telink/src/DeviceCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr

void MatterActionsPluginServerInitCallback(void)
{
registerAttributeAccessOverride(&gAttrAccess);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
}
2 changes: 1 addition & 1 deletion examples/chef/common/chef-fan-control-manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint)
{
VerifyOrDie(!mFanControlManager);
mFanControlManager = std::make_unique<ChefFanControlManager>(endpoint);
registerAttributeAccessOverride(mFanControlManager.get());
AttributeAccessInterfaceRegistry::Instance().Register(mFanControlManager.get());
FanControl::SetDefaultDelegate(endpoint, mFanControlManager.get());
}
5 changes: 2 additions & 3 deletions examples/fabric-bridge-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "RpcServer.h"
#endif

#include <string>
#include <sys/ioctl.h>
#include <thread>

Expand Down Expand Up @@ -186,8 +185,8 @@ void ApplicationInit()
ChipLogDetail(NotSpecified, "Fabric-Bridge: ApplicationInit()");

MatterEcosystemInformationPluginServerInitCallback();
CommandHandlerInterfaceRegistry::RegisterCommandHandler(&gAdministratorCommissioningCommandHandler);
registerAttributeAccessOverride(&gBridgedDeviceBasicInformationAttributes);
CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gAdministratorCommissioningCommandHandler);
AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes);

#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
InitRpcServer(kFabricBridgeServerPort);
Expand Down
2 changes: 1 addition & 1 deletion examples/log-source-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ int main(int argc, char * argv[])
// Initialize device attestation config
SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());

CommandHandlerInterfaceRegistry::RegisterCommandHandler(&GetLogProvider());
CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&GetLogProvider());

chip::DeviceLayer::PlatformMgr().RunEventLoop();

Expand Down
2 changes: 1 addition & 1 deletion examples/placeholder/linux/src/bridged-actions-stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr

void MatterActionsPluginServerInitCallback(void)
{
registerAttributeAccessOverride(&gAttrAccess);
chip::app::AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
}
2 changes: 1 addition & 1 deletion examples/tv-app/android/java/AppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ CHIP_ERROR InitVideoPlayerPlatform(jobject contentAppEndpointManager)
{
ContentAppCommandDelegate * delegate =
new ContentAppCommandDelegate(contentAppEndpointManager, contentAppClusters[i].clusterId);
chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler(delegate);
app::CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(delegate);
ChipLogProgress(AppServer, "Registered command handler delegate for cluster %d", contentAppClusters[i].clusterId);
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/AttributeAccessInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
* endpoint or for all endpoints.
*
* Instances of AttributeAccessInterface that are registered via
* registerAttributeAccessOverride will be consulted before taking the normal
* attribute access codepath and can use that codepath as a fallback if desired.
* AttributeAccessInterfaceRegistry::Instance().Register will be consulted before taking the
* normal attribute access codepath and can use that codepath as a fallback if desired.
*/
namespace chip {
namespace app {
Expand Down
56 changes: 31 additions & 25 deletions src/app/AttributeAccessInterfaceRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "app/AttributeAccessInterface.h"
#include <app/AttributeAccessInterfaceRegistry.h>

#include <app/AttributeAccessInterfaceCache.h>

using namespace chip::app;

namespace {

AttributeAccessInterface * gAttributeAccessOverrides = nullptr;
AttributeAccessInterfaceCache gAttributeAccessInterfaceCache;
using chip::app::AttributeAccessInterface;

// shouldUnregister returns true if the given AttributeAccessInterface should be
// unregistered.
template <typename F>
void UnregisterMatchingAttributeAccessInterfaces(F shouldUnregister)
void UnregisterMatchingAttributeAccessInterfaces(F shouldUnregister, AttributeAccessInterface *& list_head)
{
AttributeAccessInterface * prev = nullptr;
AttributeAccessInterface * cur = gAttributeAccessOverrides;
AttributeAccessInterface * cur = list_head;
while (cur)
{
AttributeAccessInterface * next = cur->GetNext();
Expand All @@ -43,7 +41,7 @@ void UnregisterMatchingAttributeAccessInterfaces(F shouldUnregister)
}
else
{
gAttributeAccessOverrides = next;
list_head = next;
}

cur->SetNext(nullptr);
Expand All @@ -60,43 +58,51 @@ void UnregisterMatchingAttributeAccessInterfaces(F shouldUnregister)

} // namespace

void unregisterAttributeAccessOverride(AttributeAccessInterface * attrOverride)
namespace chip {
namespace app {

AttributeAccessInterfaceRegistry & AttributeAccessInterfaceRegistry::Instance()
{
static AttributeAccessInterfaceRegistry instance;
return instance;
}

void AttributeAccessInterfaceRegistry::Unregister(AttributeAccessInterface * attrOverride)
{
gAttributeAccessInterfaceCache.Invalidate();
UnregisterMatchingAttributeAccessInterfaces([attrOverride](AttributeAccessInterface * entry) { return entry == attrOverride; });
mAttributeAccessInterfaceCache.Invalidate();
UnregisterMatchingAttributeAccessInterfaces([attrOverride](AttributeAccessInterface * entry) { return entry == attrOverride; },
mAttributeAccessOverrides);
}

void unregisterAllAttributeAccessOverridesForEndpoint(EmberAfDefinedEndpoint * definedEndpoint)
void AttributeAccessInterfaceRegistry::UnregisterAllForEndpoint(EndpointId endpointId)
{
mAttributeAccessInterfaceCache.Invalidate();
UnregisterMatchingAttributeAccessInterfaces(
[endpoint = definedEndpoint->endpoint](AttributeAccessInterface * entry) { return entry->MatchesEndpoint(endpoint); });
[endpointId](AttributeAccessInterface * entry) { return entry->MatchesEndpoint(endpointId); }, mAttributeAccessOverrides);
}

bool registerAttributeAccessOverride(AttributeAccessInterface * attrOverride)
bool AttributeAccessInterfaceRegistry::Register(AttributeAccessInterface * attrOverride)
{
gAttributeAccessInterfaceCache.Invalidate();
for (auto * cur = gAttributeAccessOverrides; cur; cur = cur->GetNext())
mAttributeAccessInterfaceCache.Invalidate();
for (auto * cur = mAttributeAccessOverrides; cur; cur = cur->GetNext())
{
if (cur->Matches(*attrOverride))
{
ChipLogError(InteractionModel, "Duplicate attribute override registration failed");
return false;
}
}
attrOverride->SetNext(gAttributeAccessOverrides);
gAttributeAccessOverrides = attrOverride;
attrOverride->SetNext(mAttributeAccessOverrides);
mAttributeAccessOverrides = attrOverride;
return true;
}

namespace chip {
namespace app {

app::AttributeAccessInterface * GetAttributeAccessOverride(EndpointId endpointId, ClusterId clusterId)
AttributeAccessInterface * AttributeAccessInterfaceRegistry::Get(EndpointId endpointId, ClusterId clusterId)
{
using CacheResult = AttributeAccessInterfaceCache::CacheResult;

AttributeAccessInterface * cached = nullptr;
CacheResult result = gAttributeAccessInterfaceCache.Get(endpointId, clusterId, &cached);
CacheResult result = mAttributeAccessInterfaceCache.Get(endpointId, clusterId, &cached);
switch (result)
{
case CacheResult::kDefinitelyUnused:
Expand All @@ -106,17 +112,17 @@ app::AttributeAccessInterface * GetAttributeAccessOverride(EndpointId endpointId
case CacheResult::kCacheMiss:
default:
// Did not cache yet, search set of AAI registered, and cache if found.
for (app::AttributeAccessInterface * cur = gAttributeAccessOverrides; cur; cur = cur->GetNext())
for (app::AttributeAccessInterface * cur = mAttributeAccessOverrides; cur; cur = cur->GetNext())
{
if (cur->Matches(endpointId, clusterId))
{
gAttributeAccessInterfaceCache.MarkUsed(endpointId, clusterId, cur);
mAttributeAccessInterfaceCache.MarkUsed(endpointId, clusterId, cur);
return cur;
}
}

// Did not find AAI registered: mark as definitely not using.
gAttributeAccessInterfaceCache.MarkUnused(endpointId, clusterId);
mAttributeAccessInterfaceCache.MarkUnused(endpointId, clusterId);
}

return nullptr;
Expand Down
66 changes: 38 additions & 28 deletions src/app/AttributeAccessInterfaceRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,49 @@
#pragma once

#include <app/AttributeAccessInterface.h>
#include <app/util/af-types.h>
#include <app/AttributeAccessInterfaceCache.h>

/**
* Register an attribute access override. It will remain registered until the
* endpoint it's registered for is disabled (or until shutdown if it's
* registered for all endpoints) or until it is explicitly unregistered.
* Registration will fail if there is an already-registered override for the
* same set of attributes.
*
* @return false if there is an existing override that the new one would
* conflict with. In this case the override is not registered.
* @return true if registration was successful.
*/
bool registerAttributeAccessOverride(chip::app::AttributeAccessInterface * attrOverride);
namespace chip {
namespace app {

/**
* Unregister an attribute access override (for example if the object
* implementing AttributeAccessInterface is being destroyed).
*/
void unregisterAttributeAccessOverride(chip::app::AttributeAccessInterface * attrOverride);
class AttributeAccessInterfaceRegistry
{
public:
/**
* Register an attribute access override. It will remain registered until the
* endpoint it's registered for is disabled (or until shutdown if it's
* registered for all endpoints) or until it is explicitly unregistered.
* Registration will fail if there is an already-registered override for the
* same set of attributes.
*
* @return false if there is an existing override that the new one would
* conflict with. In this case the override is not registered.
* @return true if registration was successful.
*/
bool Register(AttributeAccessInterface * attrOverride);

/**
* Unregister all attribute access interfaces that match this given endpoint.
*/
void unregisterAllAttributeAccessOverridesForEndpoint(EmberAfDefinedEndpoint * definedEndpoint);
/**
* Unregister an attribute access override (for example if the object
* implementing AttributeAccessInterface is being destroyed).
*/
void Unregister(AttributeAccessInterface * attrOverride);

namespace chip {
namespace app {
/**
* Unregister all attribute access interfaces that match this given endpoint.
*/
void UnregisterAllForEndpoint(EndpointId endpointId);

/**
* Get the registered attribute access override. nullptr when attribute access override is not found.
*/
AttributeAccessInterface * GetAttributeAccessOverride(EndpointId aEndpointId, ClusterId aClusterId);
/**
* Get the registered attribute access override. nullptr when attribute access override is not found.
*/
AttributeAccessInterface * Get(EndpointId aEndpointId, ClusterId aClusterId);

static AttributeAccessInterfaceRegistry & Instance();

private:
AttributeAccessInterface * mAttributeAccessOverrides = nullptr;
AttributeAccessInterfaceCache mAttributeAccessInterfaceCache;
};

} // namespace app
} // namespace chip
Loading

0 comments on commit a7416a6

Please sign in to comment.