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

Add basic support for App Install Flow #33445

Merged
merged 26 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6fff237
Add logic for the basic app installation flow
lazarkov May 13, 2024
5839b4a
Add more logic
lazarkov May 14, 2024
3e9f59b
Merge branch 'project-chip:master' into feature/basic-app-install-flow
lazarkov May 14, 2024
e1f2e44
Update basic logic
lazarkov May 14, 2024
8a19733
Update codebase
lazarkov May 14, 2024
33b5912
Update code
lazarkov May 14, 2024
5407248
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 14, 2024
0613f7b
Update code
lazarkov May 14, 2024
2d0864b
Add missing content apps
lazarkov May 14, 2024
ca5ffb4
Update TODO comment
lazarkov May 14, 2024
45a5202
Update code per comments
lazarkov May 16, 2024
3b23b5b
Update Logic per comments
lazarkov May 17, 2024
fb174cc
Update code to make android work
lazarkov May 17, 2024
2ca78f9
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 20, 2024
5b2fc5c
Update per comments
lazarkov May 21, 2024
070261e
Restyled by whitespace
restyled-commits May 21, 2024
75be581
Restyled by clang-format
restyled-commits May 21, 2024
af2d200
Restyled by prettier-markdown
restyled-commits May 21, 2024
18750a0
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 21, 2024
ab88dc4
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 21, 2024
3ae484e
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 21, 2024
159cd5f
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 21, 2024
376cc35
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 21, 2024
5c4bff8
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 22, 2024
6a6dc09
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 22, 2024
f1e0f75
Merge branch 'master' into feature/basic-app-install-flow
lazarkov May 22, 2024
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
55 changes: 55 additions & 0 deletions examples/tv-app/android/.idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 3 additions & 7 deletions examples/tv-app/tv-common/include/AppTv.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,10 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory

void AddAdminVendorId(uint16_t vendorId);

protected:
ContentAppImpl mContentApps[APP_LIBRARY_SIZE] = {
ContentAppImpl("Vendor1", 1, "exampleid", 11, "Version1", "34567890"),
ContentAppImpl("Vendor2", 65521, "exampleString", 32768, "Version2", "20202021"),
ContentAppImpl("Vendor3", 9050, "App3", 22, "Version3", "20202021"),
ContentAppImpl("TestSuiteVendor", 1111, "applicationId", 22, "v2", "20202021")
};
void AddContentApp(uint16_t vendorId, uint16_t productId);

protected:
std::vector<std::unique_ptr<ContentAppImpl>> mContentApps;
std::vector<uint16_t> mAdminVendorIds{};
};

Expand Down
2 changes: 2 additions & 0 deletions examples/tv-app/tv-common/shell/AppTvShellCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv)
{
pid = (uint16_t) strtol(argv[2], &eptr, 10);
}
ContentAppFactoryImpl * factory = GetContentAppFactoryImpl();
factory->AddContentApp(vid, pid);
ContentAppPlatform::GetInstance().LoadContentAppByClient(vid, pid);

ChipLogProgress(DeviceLayer, "added app");
Expand Down
57 changes: 49 additions & 8 deletions examples/tv-app/tv-common/src/AppTv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ using namespace chip::AppPlatform;
using namespace chip::app::Clusters;
using namespace chip::Protocols::UserDirectedCommissioning;

ContentAppFactoryImpl gFactory;

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
class MyUserPrompter : public UserPrompter
{
Expand Down Expand Up @@ -98,6 +100,10 @@ class MyUserPrompter : public UserPrompter

// tv should override this with a dialog prompt
inline void PromptCommissioningFailed(const char * commissioneeName, CHIP_ERROR error) override { return; }

// tv should override this with a dialog prompt
inline void PromptForAppInstallOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override
{ return; }
};

MyUserPrompter gMyUserPrompter;
Expand Down Expand Up @@ -146,6 +152,18 @@ class MyPasscodeService : public PasscodeService
};
MyPasscodeService gMyPasscodeService;

class MyAppInstallationService : public AppInstallationService
{
// TODO: rename the method
// intentionally ambigiously named, need to find a better method name
bool HasContentApp(uint16_t vendorId, uint16_t productId) override
{
return ContentAppPlatform::GetInstance().LoadContentAppByClient(vendorId, productId) != nullptr;
}
};

MyAppInstallationService gMyAppInstallationService;

class MyPostCommissioningListener : public PostCommissioningListener
{
void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
Expand Down Expand Up @@ -272,7 +290,6 @@ MyPostCommissioningListener gMyPostCommissioningListener;
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE

#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ContentAppFactoryImpl gFactory;

ContentAppFactoryImpl * GetContentAppFactoryImpl()
{
Expand Down Expand Up @@ -527,19 +544,23 @@ ContentApp * ContentAppFactoryImpl::LoadContentApp(const CatalogVendorApp & vend
{
ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl: LoadContentAppByAppId catalogVendorId=%d applicationId=%s ",
vendorApp.catalogVendorId, vendorApp.applicationId);
int index = 0;

for (auto & contentApp : mContentApps) {

for (size_t i = 0; i < ArraySize(mContentApps); ++i)
{
auto & app = mContentApps[i];

ChipLogProgress(DeviceLayer, " Looking next=%s ", app.GetApplicationBasicDelegate()->GetCatalogVendorApp()->applicationId);
if (app.GetApplicationBasicDelegate()->GetCatalogVendorApp()->Matches(vendorApp))
auto app = contentApp.get();

ChipLogProgress(DeviceLayer, " Looking next=%s ", app->GetApplicationBasicDelegate()->GetCatalogVendorApp()->applicationId);
if (app->GetApplicationBasicDelegate()->GetCatalogVendorApp()->Matches(vendorApp))
{
ContentAppPlatform::GetInstance().AddContentApp(&app, &contentAppEndpoint, Span<DataVersion>(gDataVersions[i]),
ContentAppPlatform::GetInstance().AddContentApp(app, &contentAppEndpoint, Span<DataVersion>(gDataVersions[index]),
Span<const EmberAfDeviceType>(gContentAppDeviceType));
return &app;
return app;
}
index++;
}

ChipLogProgress(DeviceLayer, "LoadContentAppByAppId NOT FOUND catalogVendorId=%d applicationId=%s ", vendorApp.catalogVendorId,
vendorApp.applicationId);

Expand All @@ -551,6 +572,21 @@ void ContentAppFactoryImpl::AddAdminVendorId(uint16_t vendorId)
mAdminVendorIds.push_back(vendorId);
}

void ContentAppFactoryImpl::AddContentApp(uint16_t vendorId, uint16_t productId)
{
if (vendorId == 1 && productId == 11) {
mContentApps.emplace_back(std::make_unique<ContentAppImpl>("Vendor1", vendorId, "exampleid", productId, "Version1", "34567890"));
} else if (vendorId == 65521 && productId == 32768) {
mContentApps.emplace_back(std::make_unique<ContentAppImpl>("Vendor2", vendorId, "exampleString", productId, "Version2", "20202021"));
} else if (vendorId == 9050 && productId == 22) {
mContentApps.emplace_back(std::make_unique<ContentAppImpl>("Vendor3", vendorId, "App3", productId, "Version3", "20202021"));
} else if (vendorId == 1111 && productId == 22) {
mContentApps.emplace_back(std::make_unique<ContentAppImpl>("TestSuiteVendor", vendorId, "applicationId", productId, "v2", "20202021"));
} else {
mContentApps.emplace_back(std::make_unique<ContentAppImpl>("NewAppVendor", vendorId, "newAppApplicationId", productId, "v2", "20202021"));
}
}

Access::Privilege ContentAppFactoryImpl::GetVendorPrivilege(uint16_t vendorId)
{
for (size_t i = 0; i < mAdminVendorIds.size(); ++i)
Expand Down Expand Up @@ -607,6 +643,10 @@ CHIP_ERROR AppTvInit()
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ContentAppPlatform::GetInstance().SetupAppPlatform();
ContentAppPlatform::GetInstance().SetContentAppFactory(&gFactory);
gFactory.AddContentApp((uint16_t)1, (uint16_t)11);
// gFactory.AddContentApp((uint16_t)65521, (uint16_t)32768);
gFactory.AddContentApp((uint16_t)9050, (uint16_t)22);
gFactory.AddContentApp((uint16_t)1111, (uint16_t)22);
uint16_t value;
if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(value) != CHIP_NO_ERROR)
{
Expand All @@ -623,6 +663,7 @@ CHIP_ERROR AppTvInit()
if (cdc != nullptr)
{
cdc->SetPasscodeService(&gMyPasscodeService);
cdc->SetAppInstallationService(&gMyAppInstallationService);
cdc->SetUserPrompter(&gMyUserPrompter);
cdc->SetPostCommissioningListener(&gMyPostCommissioningListener);
}
Expand Down
24 changes: 24 additions & 0 deletions src/controller/CommissionerDiscoveryController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,28 @@ void CommissionerDiscoveryController::InternalOk()
ChipLogError(AppServer, "UX InternalOk: could not find instance=%s", mCurrentInstance);
return;
}

bool isContentAppInstalled = mAppInstallationService->HasContentApp(client->GetVendorId(), client->GetProductId());

if (!isContentAppInstalled) {
ChipLogDetail(AppServer, "UX InternalOk: app not installed.");

// TODO: send CDC message that user is prompted to install the app

// dialog
ChipLogDetail(Controller,
"------PROMPT USER: %s is requesting to install app on this TV. [" ChipLogFormatMEI "," ChipLogFormatMEI "]",
client->GetDeviceName(), ChipLogValueMEI(client->GetVendorId()), ChipLogValueMEI(client->GetProductId()));

if (mUserPrompter != nullptr)
{
mUserPrompter->PromptForAppInstallOKPermission(client->GetVendorId(), client->GetProductId(), client->GetDeviceName());
}
ChipLogDetail(Controller, "------Via Shell Enter: app add <pid> <vid>");
// TODO: force user to send again "cast request <id>" command?
return;
}

if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kPromptingUser)
{
ChipLogError(AppServer, "UX InternalOk: invalid state for ok");
Expand All @@ -244,6 +266,7 @@ void CommissionerDiscoveryController::InternalOk()
CharSpan rotatingIdSpan(rotatingIdBuffer, 2 * rotatingIdLength);

uint8_t targetAppCount = client->GetNumTargetAppInfos();

if (targetAppCount > 0)
{
ChipLogDetail(AppServer, "UX InternalOk: checking for each target app specified");
Expand Down Expand Up @@ -583,6 +606,7 @@ void CommissionerDiscoveryController::Cancel()
}
client->SetUDCClientProcessingState(UDCClientProcessingState::kUserDeclined);
mPendingConsent = false;
ResetState();
}

void CommissionerDiscoveryController::CommissioningSucceeded(uint16_t vendorId, uint16_t productId, NodeId nodeId,
Expand Down
43 changes: 43 additions & 0 deletions src/controller/CommissionerDiscoveryController.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ class DLL_EXPORT UserPrompter
*/
virtual void PromptCommissioningFailed(const char * commissioneeName, CHIP_ERROR error) = 0;

/**
* @brief
* Called to prompt the user for consent to allow the app commissioneeName/vendorId/productId to be installed.
* For example "[commissioneeName] is requesting permission to install app to this TV, approve?"
*
* If user responds with OK then implementor should call CommissionerRespondOk();
* If user responds with Cancel then implementor should call CommissionerRespondCancel();
*
* @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee.
* @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee.
* @param[in] commissioneeName The commissioneeName in the DNS-SD advertisement of the requesting commissionee.
*
*/
virtual void PromptForAppInstallOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) = 0;


virtual ~UserPrompter() = default;
};

Expand Down Expand Up @@ -204,6 +220,27 @@ class DLL_EXPORT PasscodeService
virtual ~PasscodeService() = default;
};

class DLL_EXPORT AppInstallationService
{
public:
/**
* @brief
* Called to get the setup passcode from the content app corresponding to the given vendorId/productId.
*
* This will be called by the main chip thread so any blocking work should be moved to a separate thread.
*
* After attempting to obtain the passcode, implementor should call HandleContentAppPasscodeResponse();
*
* @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee.
* @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee.
* @param[in] rotatingId The rotatingId in the DNS-SD advertisement of the requesting commissionee.
*
*/
virtual bool HasContentApp(uint16_t vendorId, uint16_t productId) = 0;

virtual ~AppInstallationService() = default;
};

class DLL_EXPORT PostCommissioningListener
{
public:
Expand Down Expand Up @@ -392,6 +429,11 @@ class CommissionerDiscoveryController : public chip::Protocols::UserDirectedComm
inline void SetPasscodeService(PasscodeService * passcodeService) { mPasscodeService = passcodeService; }
inline PasscodeService * GetPasscodeService() { return mPasscodeService; }

/**
* Assign an AppInstallationService
*/
inline void SetAppInstallationService(AppInstallationService * appInstallationService) { mAppInstallationService = appInstallationService; }

/**
* Assign a Commissioner Callback to perform commissioning once user consent has been given
*/
Expand Down Expand Up @@ -430,6 +472,7 @@ class CommissionerDiscoveryController : public chip::Protocols::UserDirectedComm
UserDirectedCommissioningServer * mUdcServer = nullptr;
UserPrompter * mUserPrompter = nullptr;
PasscodeService * mPasscodeService = nullptr;
AppInstallationService * mAppInstallationService = nullptr;
CommissionerCallback * mCommissionerCallback = nullptr;
PostCommissioningListener * mPostCommissioningListener = nullptr;
};
Expand Down
Loading