Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ACL after content app is installed #34229

Merged
merged 18 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
chrisdecenzo marked this conversation as resolved.
Show resolved Hide resolved

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

CHIP_ERROR err =
Expand Down
23 changes: 23 additions & 0 deletions examples/tv-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ 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);

// 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);
}

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
Loading