Skip to content

Commit

Permalink
Update ACL after content app is installed (#34229)
Browse files Browse the repository at this point in the history
* Add code to update ACL after app is installed

* Restyled by whitespace

* Restyled by clang-format

* Update code per comments

* Restyled by whitespace

* Restyled by clang-format

* Minor code updates

* Restyled by clang-format

* Update description

* Update logic to support extern DeviceCommissioner & CommissionerDiscoveryController

* Restyled by clang-format

* Test the change to see if it will fix the tests

* Update AppTv.cpp

* Update code as it failed tests

* Restyled by whitespace

* Restyled by clang-format

---------

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
lazarkov and restyled-commits authored Jul 11, 2024
1 parent c70a769 commit e3cab4d
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 17 deletions.
2 changes: 1 addition & 1 deletion examples/common/m5stack-tft/repo
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<meta-data android:name="com.matter.tv.app.api.clusters" android:resource="@raw/static_matter_clusters" />
<meta-data android:name="com.matter.tv.app.api.vendor_name" android:value="CSA" />
<meta-data android:name="com.matter.tv.app.api.vendor_id" android:value="65521" />
<meta-data android:name="com.matter.tv.app.api.product_id" android:value="5678" />
<meta-data android:name="com.matter.tv.app.api.product_id" android:value="32769" />
<activity
android:name="com.example.contentapp.MainActivity"
android:exported="true">
Expand Down
87 changes: 87 additions & 0 deletions examples/tv-app/android/java/AppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,87 @@ ContentApp * ContentAppFactoryImpl::LoadContentApp(const CatalogVendorApp & vend
return nullptr;
}

class DevicePairedCommand : public Controller::DevicePairingDelegate
{
public:
struct CallbackContext
{
uint16_t vendorId;
uint16_t productId;
chip::NodeId nodeId;

CallbackContext(uint16_t vId, uint16_t pId, chip::NodeId nId) : vendorId(vId), productId(pId), nodeId(nId) {}
};
DevicePairedCommand(uint16_t vendorId, uint16_t productId, chip::NodeId nodeId) :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
mContext = std::make_shared<CallbackContext>(vendorId, productId, nodeId);
}

static void OnDeviceConnectedFn(void * context, chip::Messaging::ExchangeManager & exchangeMgr,
const chip::SessionHandle & sessionHandle)
{
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;

if (pairingCommand)
{
ChipLogProgress(DeviceLayer,
"OnDeviceConnectedFn - Updating ACL for node id: " ChipLogFormatX64
" and vendor id: %d and product id: %d",
ChipLogValueX64(cbContext->nodeId), cbContext->vendorId, cbContext->productId);

GetCommissionerDiscoveryController()->CommissioningSucceeded(cbContext->vendorId, cbContext->productId,
cbContext->nodeId, exchangeMgr, sessionHandle);
}
}

static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;

if (pairingCommand)
{
ChipLogProgress(DeviceLayer,
"OnDeviceConnectionFailureFn - Not updating ACL for node id: " ChipLogFormatX64
" and vendor id: %d and product id: %d",
ChipLogValueX64(cbContext->nodeId), cbContext->vendorId, cbContext->productId);
// TODO: Remove Node Id
}
}

chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
std::shared_ptr<CallbackContext> mContext;
};

void refreshConnectedClientsAcl(uint16_t vendorId, uint16_t productId, ContentAppImpl * app)
{

std::set<NodeId> nodeIds = ContentAppPlatform::GetInstance().GetNodeIdsForContentApp(vendorId, productId);

for (const auto & allowedVendor : app->GetApplicationBasicDelegate()->GetAllowedVendorList())
{
std::set<NodeId> tempNodeIds = ContentAppPlatform::GetInstance().GetNodeIdsForAllowVendorId(allowedVendor);

nodeIds.insert(tempNodeIds.begin(), tempNodeIds.end());
}

for (const auto & nodeId : nodeIds)
{

ChipLogProgress(DeviceLayer,
"Creating Pairing Command with node id: " ChipLogFormatX64 " and vendor id: %d and product id: %d",
ChipLogValueX64(nodeId), vendorId, productId);

std::shared_ptr<DevicePairedCommand> pairingCommand = std::make_shared<DevicePairedCommand>(vendorId, productId, nodeId);

GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback);
}
}

EndpointId ContentAppFactoryImpl::AddContentApp(const char * szVendorName, uint16_t vendorId, const char * szApplicationName,
uint16_t productId, const char * szApplicationVersion,
std::vector<SupportedCluster> supportedClusters, jobject manager)
Expand All @@ -369,6 +450,9 @@ EndpointId ContentAppFactoryImpl::AddContentApp(const char * szVendorName, uint1
app->GetEndpointId());
mContentApps.push_back(app);
mDataVersions.push_back(dataVersionBuf);

refreshConnectedClientsAcl(vendorId, productId, app);

return epId;
}

Expand All @@ -387,6 +471,9 @@ EndpointId ContentAppFactoryImpl::AddContentApp(const char * szVendorName, uint1
app->GetEndpointId());
mContentApps.push_back(app);
mDataVersions.push_back(dataVersionBuf);

refreshConnectedClientsAcl(vendorId, productId, app);

return epId;
}

Expand Down
2 changes: 2 additions & 0 deletions examples/tv-app/android/java/TVApp-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ class MyPostCommissioningListener : public PostCommissioningListener
// read current binding list
chip::Controller::ClusterBase cluster(exchangeMgr, sessionHandle, kTargetBindingClusterEndpointId);

ContentAppPlatform::GetInstance().StoreNodeIdForContentApp(vendorId, productId, nodeId);

cacheContext(vendorId, productId, nodeId, exchangeMgr, sessionHandle);

CHIP_ERROR err =
Expand Down
25 changes: 25 additions & 0 deletions examples/tv-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,31 @@ void ApplicationInit()
ChipLogDetail(DeviceLayer, "TV Linux App: Warning - Fixed Content App Endpoint Not Disabled");
// Can't disable this without breaking CI unit tests that act upon account login cluster (only available on ep3)
// emberAfEndpointEnableDisable(3, false);

#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
// Install Content Apps
ContentAppFactoryImpl * factory = GetContentAppFactoryImpl();

// Content App 1
constexpr uint16_t kApp1VendorId = 65521;
constexpr uint16_t kApp1ProductId = 32769;
factory->InstallContentApp(kApp1VendorId, kApp1ProductId);

// Content App 2
constexpr uint16_t kApp2VendorId = 1;
constexpr uint16_t kApp2ProductId = 11;
factory->InstallContentApp(kApp2VendorId, kApp2ProductId);

// Content App 3
constexpr uint16_t kApp3VendorId = 9050;
constexpr uint16_t kApp3ProductId = 22;
factory->InstallContentApp(kApp3VendorId, kApp3ProductId);

// Content App 4
constexpr uint16_t kApp4VendorId = 1111;
constexpr uint16_t kApp4ProductId = 22;
factory->InstallContentApp(kApp4VendorId, kApp4ProductId);
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
}

void ApplicationShutdown() {}
Expand Down
11 changes: 11 additions & 0 deletions examples/tv-app/tv-common/shell/AppTvShellCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ static CHIP_ERROR PrintAllCommands()
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
streamer_printf(sout, " print-app-access Print all ACLs for app platform fabric. Usage: app print-app-access\r\n");
streamer_printf(sout, " remove-app-access Remove all ACLs for app platform fabric. Usage: app remove-app-access\r\n");
streamer_printf(
sout,
" print-installed-apps Print all installed content apps with their endpoints. Usage: app print-installed-apps\r\n");

streamer_printf(sout,
" commission <udc-entry> Commission given udc-entry using given pincode from corresponding app. Usage: "
"app commission 0\r\n");
Expand Down Expand Up @@ -436,6 +440,13 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv)
Access::GetAccessControl().DeleteAllEntriesForFabric(GetDeviceCommissioner()->GetFabricIndex());
return CHIP_NO_ERROR;
}
else if (strcmp(argv[0], "print-installed-apps") == 0)
{
ContentAppFactoryImpl * factory = GetContentAppFactoryImpl();
factory->LogInstalledApps();

return CHIP_NO_ERROR;
}
else if (strcmp(argv[0], "commission") == 0)
{
if (argc < 2)
Expand Down
116 changes: 101 additions & 15 deletions examples/tv-app/tv-common/src/AppTv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ class MyPostCommissioningListener : public PostCommissioningListener
// read current binding list
chip::Controller::ClusterBase cluster(exchangeMgr, sessionHandle, kTargetBindingClusterEndpointId);

ContentAppPlatform::GetInstance().StoreNodeIdForContentApp(vendorId, productId, nodeId);

cacheContext(vendorId, productId, nodeId, exchangeMgr, sessionHandle);

CHIP_ERROR err =
Expand Down Expand Up @@ -565,6 +567,63 @@ void ContentAppFactoryImpl::AddAdminVendorId(uint16_t vendorId)
mAdminVendorIds.push_back(vendorId);
}

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
class DevicePairedCommand : public Controller::DevicePairingDelegate
{
public:
struct CallbackContext
{
uint16_t vendorId;
uint16_t productId;
chip::NodeId nodeId;

CallbackContext(uint16_t vId, uint16_t pId, chip::NodeId nId) : vendorId(vId), productId(pId), nodeId(nId) {}
};
DevicePairedCommand(uint16_t vendorId, uint16_t productId, chip::NodeId nodeId) :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
mContext = std::make_shared<CallbackContext>(vendorId, productId, nodeId);
}

static void OnDeviceConnectedFn(void * context, chip::Messaging::ExchangeManager & exchangeMgr,
const chip::SessionHandle & sessionHandle)
{
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;

if (pairingCommand)
{
ChipLogProgress(DeviceLayer,
"OnDeviceConnectedFn - Updating ACL for node id: " ChipLogFormatX64
" and vendor id: %d and product id: %d",
ChipLogValueX64(cbContext->nodeId), cbContext->vendorId, cbContext->productId);

GetCommissionerDiscoveryController()->CommissioningSucceeded(cbContext->vendorId, cbContext->productId,
cbContext->nodeId, exchangeMgr, sessionHandle);
}
}

static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;

if (pairingCommand)
{
ChipLogProgress(DeviceLayer,
"OnDeviceConnectionFailureFn - Not updating ACL for node id: " ChipLogFormatX64
" and vendor id: %d and product id: %d",
ChipLogValueX64(cbContext->nodeId), cbContext->vendorId, cbContext->productId);
// TODO: Remove Node Id
}
}

chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
std::shared_ptr<CallbackContext> mContext;
};
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE

void ContentAppFactoryImpl::InstallContentApp(uint16_t vendorId, uint16_t productId)
{
auto make_default_supported_clusters = []() {
Expand Down Expand Up @@ -605,6 +664,46 @@ void ContentAppFactoryImpl::InstallContentApp(uint16_t vendorId, uint16_t produc
make_default_supported_clusters());
mContentApps.emplace_back(std::move(ptr));
}

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
// Get the list of node ids
std::set<NodeId> nodeIds = ContentAppPlatform::GetInstance().GetNodeIdsForContentApp(vendorId, productId);

// update ACLs
for (auto & contentApp : mContentApps)
{
auto app = contentApp.get();

if (app->MatchesPidVid(productId, vendorId))
{
CatalogVendorApp vendorApp = app->GetApplicationBasicDelegate()->GetCatalogVendorApp();

GetContentAppFactoryImpl()->LoadContentApp(vendorApp);
}

// update the list of node ids with content apps allowed vendor list
for (const auto & allowedVendor : app->GetApplicationBasicDelegate()->GetAllowedVendorList())
{
std::set<NodeId> tempNodeIds = ContentAppPlatform::GetInstance().GetNodeIdsForAllowVendorId(allowedVendor);

nodeIds.insert(tempNodeIds.begin(), tempNodeIds.end());
}
}

// refresh ACLs
for (const auto & nodeId : nodeIds)
{

ChipLogProgress(DeviceLayer,
"Creating Pairing Command with node id: " ChipLogFormatX64 " and vendor id: %d and product id: %d",
ChipLogValueX64(nodeId), vendorId, productId);

std::shared_ptr<DevicePairedCommand> pairingCommand = std::make_shared<DevicePairedCommand>(vendorId, productId, nodeId);

GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback);
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
}

bool ContentAppFactoryImpl::UninstallContentApp(uint16_t vendorId, uint16_t productId)
Expand All @@ -625,8 +724,9 @@ bool ContentAppFactoryImpl::UninstallContentApp(uint16_t vendorId, uint16_t prod
ChipLogProgress(DeviceLayer, "Found an app vid=%d pid=%d. Uninstalling it.",
app->GetApplicationBasicDelegate()->HandleGetVendorId(),
app->GetApplicationBasicDelegate()->HandleGetProductId());
EndpointId removedEndpointID = ContentAppPlatform::GetInstance().RemoveContentApp(app);
ChipLogProgress(DeviceLayer, "Removed content app at endpoint id: %d", removedEndpointID);
mContentApps.erase(mContentApps.begin() + index);
// TODO: call ContentAppPlatform->RemoveContentApp(ids...)
return true;
}

Expand Down Expand Up @@ -701,22 +801,8 @@ std::list<ClusterId> ContentAppFactoryImpl::GetAllowedClusterListForStaticEndpoi
CHIP_ERROR AppTvInit()
{
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
// test data for apps
constexpr uint16_t kApp1VendorId = 1;
constexpr uint16_t kApp1ProductId = 11;
constexpr uint16_t kApp2VendorId = 65521;
constexpr uint16_t kApp2ProductId = 32769;
constexpr uint16_t kApp3VendorId = 9050;
constexpr uint16_t kApp3ProductId = 22;
constexpr uint16_t kApp4VendorId = 1111;
constexpr uint16_t kApp4ProductId = 22;

ContentAppPlatform::GetInstance().SetupAppPlatform();
ContentAppPlatform::GetInstance().SetContentAppFactory(&gFactory);
gFactory.InstallContentApp(kApp1VendorId, kApp1ProductId);
gFactory.InstallContentApp(kApp2VendorId, kApp2ProductId);
gFactory.InstallContentApp(kApp3VendorId, kApp3ProductId);
gFactory.InstallContentApp(kApp4VendorId, kApp4ProductId);
uint16_t value;
if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(value) != CHIP_NO_ERROR)
{
Expand Down
51 changes: 51 additions & 0 deletions src/app/app-platform/ContentAppPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,57 @@ ContentApp * ContentAppPlatform::GetContentApp(EndpointId id)
return nullptr;
}

// create a string key from vendorId and productId
std::string createKey(uint16_t vendorId, uint16_t productId)
{
return std::to_string(vendorId) + ":" + std::to_string(productId);
}

void ContentAppPlatform::StoreNodeIdForContentApp(uint16_t vendorId, uint16_t productId, NodeId nodeId)
{
std::string key = createKey(vendorId, productId);

ChipLogProgress(DeviceLayer, "Stored node id: " ChipLogFormatX64 " for key: %s", ChipLogValueX64(nodeId), key.c_str());

mConnectedContentAppNodeIds[key].insert(nodeId);
}

std::set<NodeId> ContentAppPlatform::GetNodeIdsForContentApp(uint16_t vendorId, uint16_t productId)
{
std::string key = createKey(vendorId, productId);

ChipLogProgress(DeviceLayer, "Retrieving node id for key: %s", key.c_str());

auto it = mConnectedContentAppNodeIds.find(key);
if (it != mConnectedContentAppNodeIds.end())
{
ChipLogProgress(DeviceLayer, "Found node id");
return it->second;
}

ChipLogProgress(DeviceLayer, "Didn't find node id");
// If key not found, return an empty set
return {};
}

std::set<NodeId> ContentAppPlatform::GetNodeIdsForAllowVendorId(uint16_t vendorId)
{
std::set<NodeId> result;
std::string vendorPrefix = std::to_string(vendorId) + ":";

for (const auto & pair : mConnectedContentAppNodeIds)
{
const std::string & key = pair.first;
if (key.find(vendorPrefix) == 0)
{ // Check if the key starts with the vendor prefix
const std::set<NodeId> & nodeIds = pair.second;
result.insert(nodeIds.begin(), nodeIds.end());
}
}

return result;
}

void ContentAppPlatform::SetCurrentApp(ContentApp * app)
{
if (!HasCurrentApp())
Expand Down
Loading

0 comments on commit e3cab4d

Please sign in to comment.