diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java index 6b5856870eba58..e30a75a00d98b2 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java @@ -67,7 +67,9 @@ public void setEndpointId(int endpoint) { } public Set getSupportedClusters() { - return Collections.unmodifiableSet(supportedClusters); + return supportedClusters != null + ? Collections.unmodifiableSet(supportedClusters) + : Collections.EMPTY_SET; } public String getVersion() { diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/AppPlatformService.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/AppPlatformService.java index 32a5a9c2e2d865..df360375068e70 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/AppPlatformService.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/AppPlatformService.java @@ -34,6 +34,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -198,6 +199,7 @@ private Collection mapSupportedClusters( Collection supportedClusters) { return supportedClusters .stream() + .filter(Objects::nonNull) .map(AppPlatformService::mapSupportedCluster) .collect(Collectors.toList()); } diff --git a/examples/tv-app/android/java/AppPlatform-JNI.cpp b/examples/tv-app/android/java/AppPlatform-JNI.cpp index 2daebbdd890b6a..52905cf0ba130b 100644 --- a/examples/tv-app/android/java/AppPlatform-JNI.cpp +++ b/examples/tv-app/android/java/AppPlatform-JNI.cpp @@ -128,7 +128,7 @@ std::vector convert_to_cpp(JNIEnv * env, jobject s // Find Java classes. WARNING: Reflection jclass collectionClass = env->FindClass("java/util/Collection"); jclass iteratorClass = env->FindClass("java/util/Iterator"); - jclass clusterClass = env->FindClass("com/matter/tv/server/tvapp/SupportedCluster"); + jclass clusterClass = env->FindClass("com/matter/tv/server/tvapp/ContentAppSupportedCluster"); if (collectionClass == nullptr || iteratorClass == nullptr || clusterClass == nullptr) { return {}; diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp index 4eb0abe25645da..6d586d99c1c67f 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp @@ -227,15 +227,6 @@ bool JNIMyUserPrompter::DisplaysPasscodeAndQRCode() return false; } -/** - * 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?" - */ -void JNIMyUserPrompter::PromptForAppInstallOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) -{ - ChipLogError(Zcl, "JNIMyUserPrompter::PromptForAppInstallOKPermission Needs Implementation"); -} - /** * Called to display the given setup passcode to the user, * for commissioning the given commissioneeName with the given vendorId and productId, diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.h b/examples/tv-app/android/java/MyUserPrompter-JNI.h index 3d2e7f14afb75e..408346326a6fd6 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.h +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.h @@ -29,7 +29,6 @@ class JNIMyUserPrompter : public UserPrompter void PromptForCommissionOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; void PromptForCommissionPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, uint16_t pairingHint, const char * pairingInstruction) override; - void PromptForAppInstallOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; void HidePromptsOnCancel(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; bool DisplaysPasscodeAndQRCode() override; void PromptWithCommissionerPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, uint32_t passcode, diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp index f154b0759c2b1a..04b5f4199edcaa 100644 --- a/examples/tv-app/android/java/TVApp-JNI.cpp +++ b/examples/tv-app/android/java/TVApp-JNI.cpp @@ -240,6 +240,16 @@ class MyPincodeService : public PasscodeService }; MyPincodeService gMyPincodeService; +class SampleTvAppInstallationService : public AppInstallationService +{ + bool LookupTargetContentApp(uint16_t vendorId, uint16_t productId) override + { + return ContentAppPlatform::GetInstance().LoadContentAppByClient(vendorId, productId) != nullptr; + } +}; + +SampleTvAppInstallationService gSampleTvAppInstallationService; + class MyPostCommissioningListener : public PostCommissioningListener { void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr, @@ -372,6 +382,7 @@ void TvAppJNI::InitializeCommissioner(JNIMyUserPrompter * userPrompter) if (cdc != nullptr && userPrompter != nullptr) { cdc->SetPasscodeService(&gMyPincodeService); + cdc->SetAppInstallationService(&gSampleTvAppInstallationService); cdc->SetUserPrompter(userPrompter); cdc->SetPostCommissioningListener(&gMyPostCommissioningListener); } diff --git a/examples/tv-app/tv-common/include/AppTv.h b/examples/tv-app/tv-common/include/AppTv.h index 8ddd793c611f70..026f125339aba6 100644 --- a/examples/tv-app/tv-common/include/AppTv.h +++ b/examples/tv-app/tv-common/include/AppTv.h @@ -149,6 +149,10 @@ 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); + // Print mContentApps and endpoints + void LogInstalledApps(); + // TODO: method to retrieve list of mContentApps + // https://github.com/project-chip/connectedhomeip/issues/34020 protected: std::vector> mContentApps; diff --git a/examples/tv-app/tv-common/src/AppTv.cpp b/examples/tv-app/tv-common/src/AppTv.cpp index bcdeac1a52b39f..03422c3fa462e7 100644 --- a/examples/tv-app/tv-common/src/AppTv.cpp +++ b/examples/tv-app/tv-common/src/AppTv.cpp @@ -98,12 +98,6 @@ 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; @@ -583,28 +577,33 @@ void ContentAppFactoryImpl::InstallContentApp(uint16_t vendorId, uint16_t produc ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl: InstallContentApp vendorId=%d productId=%d ", vendorId, productId); if (vendorId == 1 && productId == 11) { - mContentApps.emplace_back(std::make_unique("Vendor1", vendorId, "exampleid", productId, "Version1", - "34567890", make_default_supported_clusters())); + auto ptr = std::make_unique("Vendor1", vendorId, "exampleid", productId, "Version1", "34567890", + make_default_supported_clusters()); + mContentApps.emplace_back(std::move(ptr)); } - else if (vendorId == 65521 && productId == 32768) + else if (vendorId == 65521 && productId == 32769) { - mContentApps.emplace_back(std::make_unique("Vendor2", vendorId, "exampleString", productId, "Version2", - "20202021", make_default_supported_clusters())); + auto ptr = std::make_unique("Vendor2", vendorId, "exampleString", productId, "Version2", "20202021", + make_default_supported_clusters()); + mContentApps.emplace_back(std::move(ptr)); } else if (vendorId == 9050 && productId == 22) { - mContentApps.emplace_back(std::make_unique("Vendor3", vendorId, "App3", productId, "Version3", "20202021", - make_default_supported_clusters())); + auto ptr = std::make_unique("Vendor3", vendorId, "App3", productId, "Version3", "20202021", + make_default_supported_clusters()); + mContentApps.emplace_back(std::move(ptr)); } else if (vendorId == 1111 && productId == 22) { - mContentApps.emplace_back(std::make_unique("TestSuiteVendor", vendorId, "applicationId", productId, "v2", - "20202021", make_default_supported_clusters())); + auto ptr = std::make_unique("TestSuiteVendor", vendorId, "applicationId", productId, "v2", "20202021", + make_default_supported_clusters()); + mContentApps.emplace_back(std::move(ptr)); } else { - mContentApps.emplace_back(std::make_unique("NewAppVendor", vendorId, "newAppApplicationId", productId, "v2", - "20202021", make_default_supported_clusters())); + auto ptr = std::make_unique("NewAppVendor", vendorId, "newAppApplicationId", productId, "v2", "20202021", + make_default_supported_clusters()); + mContentApps.emplace_back(std::move(ptr)); } } @@ -627,6 +626,7 @@ bool ContentAppFactoryImpl::UninstallContentApp(uint16_t vendorId, uint16_t prod app->GetApplicationBasicDelegate()->HandleGetVendorId(), app->GetApplicationBasicDelegate()->HandleGetProductId()); mContentApps.erase(mContentApps.begin() + index); + // TODO: call ContentAppPlatform->RemoveContentApp(ids...) return true; } @@ -635,6 +635,18 @@ bool ContentAppFactoryImpl::UninstallContentApp(uint16_t vendorId, uint16_t prod return false; } +void ContentAppFactoryImpl::LogInstalledApps() +{ + for (auto & contentApp : mContentApps) + { + auto app = contentApp.get(); + + ChipLogProgress(DeviceLayer, "Content app vid=%d pid=%d is on ep=%d", + app->GetApplicationBasicDelegate()->HandleGetVendorId(), + app->GetApplicationBasicDelegate()->HandleGetProductId(), app->GetEndpointId()); + } +} + Access::Privilege ContentAppFactoryImpl::GetVendorPrivilege(uint16_t vendorId) { for (size_t i = 0; i < mAdminVendorIds.size(); ++i) @@ -689,12 +701,22 @@ std::list 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((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(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) { diff --git a/src/controller/CommissionerDiscoveryController.cpp b/src/controller/CommissionerDiscoveryController.cpp index d1a5747491ad50..7f13a4323d2f5c 100644 --- a/src/controller/CommissionerDiscoveryController.cpp +++ b/src/controller/CommissionerDiscoveryController.cpp @@ -229,22 +229,6 @@ void CommissionerDiscoveryController::InternalOk() if (!mAppInstallationService->LookupTargetContentApp(client->GetVendorId(), client->GetProductId())) { 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()); - - if (mUserPrompter != nullptr) - { - mUserPrompter->PromptForAppInstallOKPermission(client->GetVendorId(), client->GetProductId(), client->GetDeviceName()); - } - ChipLogDetail(Controller, "------Via Shell Enter: app install "); - return; } if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kPromptingUser) diff --git a/src/controller/CommissionerDiscoveryController.h b/src/controller/CommissionerDiscoveryController.h index b2211641fd0ede..5f7572b29def17 100644 --- a/src/controller/CommissionerDiscoveryController.h +++ b/src/controller/CommissionerDiscoveryController.h @@ -150,21 +150,6 @@ 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; }; @@ -227,8 +212,6 @@ class DLL_EXPORT AppInstallationService * Called to check if the given target app is available to the commissione with th given * vendorId/productId * - * This will be called by the main chip thread so any blocking work should be moved to a separate thread. - * * @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. *