diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp index f154b0759c2b1a..928c85bd92a41e 100644 --- a/examples/tv-app/android/java/TVApp-JNI.cpp +++ b/examples/tv-app/android/java/TVApp-JNI.cpp @@ -240,6 +240,23 @@ class MyPincodeService : public PasscodeService }; MyPincodeService gMyPincodeService; +class MyAppInstallationService : public AppInstallationService +{ + bool LookupTargetContentApp(uint16_t vendorId, uint16_t productId) override + { + return ContentAppPlatform::GetInstance().LoadContentAppByClient(vendorId, productId) != nullptr; + } + + // TODO: Dummy code for Android OS, needs to be updated with package manager + // retrieving correct app's installation status + CommissionerDeclaration::CdError GetAppInstallationErrorCode(uint16_t vendorId, uint16_t productId) override + { + return CommissionerDeclaration::CdError::kAppInstallConsentPending; + } +}; + +MyAppInstallationService gMyAppInstallationService; + class MyPostCommissioningListener : public PostCommissioningListener { void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr, @@ -373,6 +390,7 @@ void TvAppJNI::InitializeCommissioner(JNIMyUserPrompter * userPrompter) { cdc->SetPasscodeService(&gMyPincodeService); cdc->SetUserPrompter(userPrompter); + cdc->SetAppInstallationService(&gMyAppInstallationService); cdc->SetPostCommissioningListener(&gMyPostCommissioningListener); } diff --git a/examples/tv-app/tv-common/include/AppTv.h b/examples/tv-app/tv-common/include/AppTv.h index 34f5bd8dc4c958..3cc65f14f53ea7 100644 --- a/examples/tv-app/tv-common/include/AppTv.h +++ b/examples/tv-app/tv-common/include/AppTv.h @@ -147,10 +147,17 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory void InstallContentApp(uint16_t vendorId, uint16_t productId); // Remove the app from the list of mContentApps bool UninstallContentApp(uint16_t vendorId, uint16_t productId); + // Set App's Installation Error Status + void SetAppInstallationErrorStatus(uint16_t vendorId, uint16_t productId, + Protocols::UserDirectedCommissioning::CommissionerDeclaration::CdError errorStatus); + // Get App's Installation Status + Protocols::UserDirectedCommissioning::CommissionerDeclaration::CdError GetAppInstallationStatus(uint16_t vendorId, + uint16_t productId); protected: std::vector> mContentApps; std::vector mAdminVendorIds{}; + std::map mAppInstallationStatus{}; }; } // namespace AppPlatform diff --git a/examples/tv-app/tv-common/shell/AppTvShellCommands.cpp b/examples/tv-app/tv-common/shell/AppTvShellCommands.cpp index b39e84ad40f89a..e2e4cca6a59500 100644 --- a/examples/tv-app/tv-common/shell/AppTvShellCommands.cpp +++ b/examples/tv-app/tv-common/shell/AppTvShellCommands.cpp @@ -205,6 +205,18 @@ static CHIP_ERROR PrintAllCommands() streamer_printf(sout, " add-admin-vendor Add vendor ID to list which will receive admin privileges. Usage: app " "add-admin-vendor 65521\r\n"); + streamer_printf(sout, + " app install Install app with given vendor ID and product ID. Usage: app install " + "65521 32768\r\n"); + streamer_printf( + sout, + " app uninstall Uinstall app at given vendor ID and product ID. Usage: app uninstall " + "65521 32768\r\n"); + streamer_printf(sout, + " app setinstallerrorstatus Set app's installation error status for a given vendor " + "ID and product ID. " + "Usage: app setinstallerrorstatus 65521 32768 13. Installation error status can be found at: " + "UserDirectedCommissioning.h\r\n"); #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #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"); @@ -292,6 +304,27 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) return CHIP_NO_ERROR; } + else if (strcmp(argv[0], "setinstallerrorstatus") == 0) + { + if (argc < 3) + { + return PrintAllCommands(); + } + char * eptr; + + uint16_t vid = (uint16_t) strtol(argv[1], &eptr, 10); + uint16_t pid = (uint16_t) strtol(argv[2], &eptr, 10); + uint16_t appInstallationErrorStatus = (uint16_t) strtol(argv[3], &eptr, 10); + + ContentAppFactoryImpl * factory = GetContentAppFactoryImpl(); + factory->SetAppInstallationErrorStatus( + vid, pid, + static_cast(appInstallationErrorStatus)); + + ChipLogProgress(DeviceLayer, "set app installation status"); + + return CHIP_NO_ERROR; + } else if (strcmp(argv[0], "add") == 0) { if (argc < 2) diff --git a/examples/tv-app/tv-common/src/AppTv.cpp b/examples/tv-app/tv-common/src/AppTv.cpp index 9987b4cdd67d6e..5d65da34caceaf 100644 --- a/examples/tv-app/tv-common/src/AppTv.cpp +++ b/examples/tv-app/tv-common/src/AppTv.cpp @@ -158,6 +158,12 @@ class MyAppInstallationService : public AppInstallationService { return ContentAppPlatform::GetInstance().LoadContentAppByClient(vendorId, productId) != nullptr; } + + CommissionerDeclaration::CdError GetAppInstallationErrorCode(uint16_t vendorId, uint16_t productId) override + { + ContentAppFactoryImpl * factory = GetContentAppFactoryImpl(); + return factory->GetAppInstallationStatus(vendorId, productId); + } }; MyAppInstallationService gMyAppInstallationService; @@ -627,6 +633,41 @@ bool ContentAppFactoryImpl::UninstallContentApp(uint16_t vendorId, uint16_t prod return false; } +std::string createSearchIndex(uint16_t vendorId, uint16_t productId) +{ + // Format the IDs into a string + std::string formattedString = std::to_string(vendorId) + ":" + std::to_string(productId); + return formattedString; +} + +void ContentAppFactoryImpl::SetAppInstallationErrorStatus(uint16_t vendorId, uint16_t productId, + CommissionerDeclaration::CdError errorStatus) +{ + std::string searchIndex = createSearchIndex(vendorId, productId); + std::map::iterator it; + it = mAppInstallationStatus.find(searchIndex); + if (it != mAppInstallationStatus.end()) + { + mAppInstallationStatus[searchIndex] = errorStatus; + return; + } + + mAppInstallationStatus.insert({ searchIndex, errorStatus }); +} + +CommissionerDeclaration::CdError ContentAppFactoryImpl::GetAppInstallationStatus(uint16_t vendorId, uint16_t productId) +{ + std::string searchIndex = createSearchIndex(vendorId, productId); + std::map::iterator it; + it = mAppInstallationStatus.find(searchIndex); + if (it != mAppInstallationStatus.end()) + { + return mAppInstallationStatus[searchIndex]; + } + + return CommissionerDeclaration::CdError::kAppInstallConsentPending; +} + Access::Privilege ContentAppFactoryImpl::GetVendorPrivilege(uint16_t vendorId) { for (size_t i = 0; i < mAdminVendorIds.size(); ++i) @@ -681,12 +722,22 @@ std::list ContentAppFactoryImpl::GetAllowedClusterListForStaticEndpoi CHIP_ERROR AppTvInit() { #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED + // test data for apps + const uint16_t APP1_VENDOR_ID = 1; + const uint16_t APP1_PRODUCT_ID = 11; + const uint16_t APP2_VENDOR_ID = 65521; + const uint16_t APP2_PRODUCT_ID = 32769; + const uint16_t APP3_VENDOR_ID = 9050; + const uint16_t APP3_PRODUCT_ID = 22; + const uint16_t APP4_VENDOR_ID = 1111; + const uint16_t APP4_PRODUCT_ID = 22; + ContentAppPlatform::GetInstance().SetupAppPlatform(); ContentAppPlatform::GetInstance().SetContentAppFactory(&gFactory); - gFactory.InstallContentApp((uint16_t) 1, (uint16_t) 11); - gFactory.InstallContentApp((uint16_t) 65521, (uint16_t) 32768); - gFactory.InstallContentApp((uint16_t) 9050, (uint16_t) 22); - gFactory.InstallContentApp((uint16_t) 1111, (uint16_t) 22); + gFactory.InstallContentApp(APP1_VENDOR_ID, APP1_PRODUCT_ID); + gFactory.InstallContentApp(APP2_VENDOR_ID, APP2_PRODUCT_ID); + gFactory.InstallContentApp(APP3_VENDOR_ID, APP3_PRODUCT_ID); + gFactory.InstallContentApp(APP4_VENDOR_ID, APP4_PRODUCT_ID); uint16_t value; if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(value) != CHIP_NO_ERROR) { diff --git a/src/controller/CommissionerDiscoveryController.cpp b/src/controller/CommissionerDiscoveryController.cpp index d1a5747491ad50..bee0bc39da433c 100644 --- a/src/controller/CommissionerDiscoveryController.cpp +++ b/src/controller/CommissionerDiscoveryController.cpp @@ -230,11 +230,6 @@ void CommissionerDiscoveryController::InternalOk() { ChipLogDetail(AppServer, "UX InternalOk: app not installed."); - // notify client that app will be installed - CommissionerDeclaration cd; - cd.SetErrorCode(CommissionerDeclaration::CdError::kAppInstallConsentPending); - mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); - // dialog ChipLogDetail(Controller, "------PROMPT USER: %s is requesting to install app on this TV. vendorId=%d, productId=%d", client->GetDeviceName(), client->GetVendorId(), client->GetProductId()); @@ -244,6 +239,14 @@ void CommissionerDiscoveryController::InternalOk() mUserPrompter->PromptForAppInstallOKPermission(client->GetVendorId(), client->GetProductId(), client->GetDeviceName()); } ChipLogDetail(Controller, "------Via Shell Enter: app install "); + + CommissionerDeclaration::CdError appInstallStatus = + mAppInstallationService->GetAppInstallationErrorCode(client->GetVendorId(), client->GetProductId()); + + // notify client the current app's installation status + CommissionerDeclaration cd; + cd.SetErrorCode(appInstallStatus); + mUdcServer->SendCDCMessage(cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); return; } diff --git a/src/controller/CommissionerDiscoveryController.h b/src/controller/CommissionerDiscoveryController.h index b2211641fd0ede..7a5d6031ca5e29 100644 --- a/src/controller/CommissionerDiscoveryController.h +++ b/src/controller/CommissionerDiscoveryController.h @@ -235,6 +235,21 @@ class DLL_EXPORT AppInstallationService */ virtual bool LookupTargetContentApp(uint16_t vendorId, uint16_t productId) = 0; + /** + * @brief + * Called to get app's installation error code. + * + * CdError status is designed for CommissionerDeclaration and should be set by using SetErrorCode() and + * sent back to the client as a CDC Message. It is expected that app during installation can return following errors: + * kNoError, kAppInstallConsentPending, kAppInstalling, kAppInstallFailed, kAppInstalledRetryNeeded + * + * @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. + * + */ + virtual chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration::CdError + GetAppInstallationErrorCode(uint16_t vendorId, uint16_t productId) = 0; + virtual ~AppInstallationService() = default; };