From 190acdafefdc6831de003a35a17761ebab850091 Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Fri, 23 Aug 2024 09:35:49 +0000 Subject: [PATCH 1/9] RDK-52203: Convert XCast plugin as OutOfProcess Reason for change: Convert XCast plugin as OutOfProcess, Later it will be linked with GDial as library Test Procedure: XCast should be converted as OutOfProcess thunder plugin Risks: HIGH Priority: P0 Signed-off-by: yuvaramachandran_gurusamy --- XCast/CMakeLists.txt | 10 +- XCast/RtNotifier.h | 2 +- XCast/RtXcastConnector.cpp | 364 ++++----------- XCast/RtXcastConnector.h | 42 +- XCast/XCast.conf.in | 16 + XCast/XCast.config | 5 + XCast/XCast.cpp | 804 +++++++++++++++------------------- XCast/XCast.h | 251 ++++++----- XCast/XCastImplementation.cpp | 288 ++++++++++++ XCast/XCastImplementation.h | 132 ++++++ 10 files changed, 1043 insertions(+), 871 deletions(-) create mode 100644 XCast/XCastImplementation.cpp create mode 100644 XCast/XCastImplementation.h diff --git a/XCast/CMakeLists.txt b/XCast/CMakeLists.txt index 0290690041..d21e06e9f1 100644 --- a/XCast/CMakeLists.txt +++ b/XCast/CMakeLists.txt @@ -20,16 +20,22 @@ set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) set(PLUGIN_XCAST_AUTOSTART "false" CACHE STRING "Automatically start XCast plugin") set(PLUGIN_XCAST_STARTUPORDER "" CACHE STRING "To configure startup order of XCast plugin") +set(PLUGIN_XCAST_MODE "Local" CACHE STRING "Controls if the plugin should run in its own process, in process or remote") find_package(${NAMESPACE}Plugins REQUIRED) add_library(${MODULE_NAME} SHARED XCast.cpp + XCastImplementation.cpp Module.cpp RtXcastConnector.cpp) find_package(RFC) find_package(IARMBus) +find_package(GLIB REQUIRED) + +find_library(XDIAL_LIBRARIES NAMES gdial-server) + set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) @@ -39,10 +45,10 @@ target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NA add_definitions (-DRT_PLATFORM_LINUX) target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) target_include_directories(${MODULE_NAME} PRIVATE ${RFC_INCLUDE_DIRS} ../helpers) -target_include_directories(${MODULE_NAME} PRIVATE $ENV{PKG_CONFIG_SYSROOT_DIR}/usr/include/pxcore) +target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS}) if(NOT RDK_SERVICES_L1_TEST) - target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins rtRemote rtCore ${RFC_LIBRARIES} ${IARMBUS_LIBRARIES}) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${RFC_LIBRARIES} ${IARMBUS_LIBRARIES} ${XDIAL_LIBRARIES}) else(RDK_SERVICES_L1_TEST) target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${RFC_LIBRARIES} ${IARMBUS_LIBRARIES}) endif() diff --git a/XCast/RtNotifier.h b/XCast/RtNotifier.h index 5e10830c8c..94189a4416 100644 --- a/XCast/RtNotifier.h +++ b/XCast/RtNotifier.h @@ -27,7 +27,7 @@ class RtNotifier { public: - virtual void onRtServiceDisconnected(void)=0; + //virtual void onRtServiceDisconnected(void)=0; virtual void onXcastApplicationLaunchRequest(string appName, string parameter)=0; virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, string strPayLoad, string strQuery, string strAddDataUrl)=0; diff --git a/XCast/RtXcastConnector.cpp b/XCast/RtXcastConnector.cpp index 2bdbd6261b..cc0c09c777 100644 --- a/XCast/RtXcastConnector.cpp +++ b/XCast/RtXcastConnector.cpp @@ -31,222 +31,81 @@ using namespace WPEFramework; #define EVENT_LOOP_ITERATION_IN_100MS 100000 -static rtObjectRef xdialCastObj = NULL; +static gdialService* gdialCastObj = NULL; RtXcastConnector * RtXcastConnector::_instance = nullptr; -void RtXcastConnector::remoteDisconnectCallback( void* context) { - RtNotifier * observer = static_cast (context); - LOGINFO ( "remoteDisconnectCallback: Remote disconnected... "); - observer->onRtServiceDisconnected(); -} - -void RtXcastConnector::processRtMessages(){ - LOGINFO("Entering Event Loop"); - while(true) - { - rtError err = rtRemoteProcessSingleItem(); - if (err != RT_OK && err != RT_ERROR_QUEUE_EMPTY) { - LOGERR("Failed to gete item from Rt queue"); - } - { - //Queue needs to be deactivated ? - lock_guard lock(m_threadlock); - if (!m_runEventThread ) break; - } - /* - Ideally this should be part of wpe process main message loop, - will reconsider once we decide on connectivity with dial server - */ - usleep(EVENT_LOOP_ITERATION_IN_100MS); - } - LOGINFO("Exiting Event Loop"); -} -void RtXcastConnector::threadRun(RtXcastConnector *rtCtx){ - RtXcastConnector * observer = static_cast (rtCtx); - observer->processRtMessages(); -} //XDIALCAST EVENT CALLBACK /** * Callback function for application launch request from an app */ -rtError RtXcastConnector::onApplicationLaunchRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context) +void RtXcastConnector::onApplicationLaunchRequestWithLaunchParam(string appName,string strPayLoad, string strQuery, string strAddDataUrl) { - if (numArgs == 1) + if ( nullptr != m_observer ) { - RtNotifier * observer = static_cast (context); - rtObjectRef appObject = args[0].toObject(); - rtString appName = appObject.get("applicationName"); - rtString rtparamIsUrl = appObject.get("isUrl"); - if (0 == strcmp(rtparamIsUrl.cString(), "false")) { - - rtString rtPayload = appObject.get("payload"); - rtString rtQuery = appObject.get("query"); - rtString rtAddDataUrl = appObject.get("addDataUrl"); - observer->onXcastApplicationLaunchRequestWithLaunchParam( - appName.cString(), - rtPayload.cString(), - rtQuery.cString(), - rtAddDataUrl.cString()); - } - else { - if (!strcmp(appName.cString(),"Netflix")) - appName = "NetflixApp"; - rtString rtparams = appObject.get("parameters"); - observer->onXcastApplicationLaunchRequest(appName.cString() , rtparams.cString()); - } + m_observer->onXcastApplicationLaunchRequestWithLaunchParam(appName,strPayLoad,strQuery,strAddDataUrl); } - else - LOGERR(" *** Error: received unknown event"); - if (result) - *result = rtValue(true); - return RT_OK; } -/** - * Callback function for application stop request from an app - */ -rtError RtXcastConnector::onApplicationStopRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context) + +void RtXcastConnector::onApplicationLaunchRequest(string appName, string parameter) { - if (numArgs == 1) + if ( nullptr != m_observer ) { - RtNotifier * observer = static_cast (context); - rtObjectRef appObject = args[0].toObject(); - rtString appName = appObject.get("applicationName"); - if (!strcmp(appName.cString(),"Netflix")) + if (!strcmp(appName.c_str(),"Netflix")) + { appName = "NetflixApp"; - rtString appID = appObject.get("applicationId"); - observer->onXcastApplicationStopRequest(appName.cString(),appID.cString()); + } + m_observer->onXcastApplicationLaunchRequest(appName,parameter); } - else - LOGERR(" *** Error: received unknown event" ); - if (result) - *result = rtValue(true); - return RT_OK; } -/** - * Callback function for application hide request from an app - */ -rtError RtXcastConnector::onApplicationHideRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context) + +void RtXcastConnector::onApplicationStopRequest(string appName, string appID) { - if (numArgs == 1) + if ( nullptr != m_observer ) { - RtNotifier * observer = static_cast (context); - rtObjectRef appObject = args[0].toObject(); - rtString appName = appObject.get("applicationName"); - if (!strcmp(appName.cString(),"Netflix")) + if (!strcmp(appName.c_str(),"Netflix")) + { appName = "NetflixApp"; - rtString appID = appObject.get("applicationId"); - observer->onXcastApplicationHideRequest(appName.cString(), appID.cString()); + } + m_observer->onXcastApplicationStopRequest(appName,appID); } - else - LOGERR(" *** Error: received unknown event"); - - if (result) - *result = rtValue(true); - - return RT_OK; - } -/** - * Callback function for application state request from an app - */ -rtError RtXcastConnector::onApplicationStateRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context) + +void RtXcastConnector::onApplicationHideRequest(string appName, string appID) { - if (numArgs == 1) + if ( nullptr != m_observer ) { - RtNotifier * observer = static_cast (context); - rtObjectRef appObject = args[0].toObject(); - rtString appName = appObject.get("applicationName"); - if (!strcmp(appName.cString(),"Netflix")) + if (!strcmp(appName.c_str(),"Netflix")) + { appName = "NetflixApp"; - - rtString appID = appObject.get("applicationId"); - observer->onXcastApplicationStateRequest(appName.cString(),appID.cString()); + } + m_observer->onXcastApplicationHideRequest(appName,appID); } - else - LOGERR(" *** Error: received unknown event"); - - if (result) - *result = rtValue(true); - - return RT_OK; } -/** - * Callback function for application resume request from an app - */ -rtError RtXcastConnector::onApplicationResumeRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context) + +void RtXcastConnector::onApplicationResumeRequest(string appName, string appID) { - if (numArgs == 1) + if ( nullptr != m_observer ) { - RtNotifier * observer = static_cast (context); - rtObjectRef appObject = args[0].toObject(); - rtString appName = appObject.get("applicationName"); - if (!strcmp(appName.cString(),"Netflix")) + if (!strcmp(appName.c_str(),"Netflix")) + { appName = "NetflixApp"; - - rtString appID = appObject.get("applicationId"); - observer->onXcastApplicationResumeRequest(appName.cString(),appID.cString()); - - } - else - LOGERR(" *** Error: received unknown event"); - - if (result) - *result = rtValue(true); - - return RT_OK; -} -/** - * Callback function when remote service exits - */ -rtError RtXcastConnector::onRtServiceByeCallback(int numArgs, const rtValue* args, rtValue* result, void* context) -{ - if (numArgs == 1) - { - rtObjectRef appObject = args[0].toObject(); - rtString serviceName = appObject.get("serviceName"); - LOGINFO("Received RtService Bye Event! Service: %s", serviceName.cString()); + } + m_observer->onXcastApplicationResumeRequest(appName,appID); } - else - LOGERR(" *** Error: received unknown event"); - - if (result) - *result = rtValue(true); - - return RT_OK; - } -//Timer Functions -//Timer Fired when rt remote connectivity is broken. -int RtXcastConnector::connectToRemoteService() +void RtXcastConnector::onApplicationStateRequest(string appName, string appID) { - rtError err = RT_ERROR; - - const char * serviceName = "com.comcast.xdialcast"; - - LOGINFO("connectToRemoteService entry " ); - err = rtRemoteLocateObject(rtEnvironmentGetGlobal(), serviceName, xdialCastObj, 0, &RtXcastConnector::remoteDisconnectCallback, m_observer); - if(err == RT_OK && xdialCastObj != NULL) + if ( nullptr != m_observer ) { - rtError e = xdialCastObj.send("on", "onApplicationLaunchRequest" , new rtFunctionCallback(RtXcastConnector::onApplicationLaunchRequestCallback, m_observer)); - LOGINFO("Registered onApplicationLaunchRequest ; response %d" ,e ); - e = xdialCastObj.send("on", "onApplicationStopRequest" , new rtFunctionCallback(RtXcastConnector::onApplicationStopRequestCallback, m_observer)); - LOGINFO("Registered onApplicationStopRequest %d", e ); - e = xdialCastObj.send("on", "onApplicationHideRequest" , new rtFunctionCallback( RtXcastConnector::onApplicationHideRequestCallback, m_observer)); - LOGINFO("Registered onApplicationHideRequest %d", e ); - e = xdialCastObj.send("on", "onApplicationResumeRequest" , new rtFunctionCallback( RtXcastConnector::onApplicationResumeRequestCallback, m_observer)); - LOGINFO("Registered onApplicationResumeRequest %d", e ); - e = xdialCastObj.send("on", "onApplicationStateRequest" , new rtFunctionCallback( RtXcastConnector::onApplicationStateRequestCallback, m_observer)); - LOGINFO("Registed onApplicationStateRequest %d", e ); - e = xdialCastObj.send("on", "bye" , new rtFunctionCallback(RtXcastConnector::onRtServiceByeCallback, m_observer)); - LOGINFO("Registed rtService bye event %d", e ); + if (!strcmp(appName.c_str(),"Netflix")) + { + appName = "NetflixApp"; + } + m_observer->onXcastApplicationStateRequest(appName,appID); } - else - LOGINFO("response of rtRemoteLocateObject %d ", err); - return (err == RT_OK) ? 0 : 1; } - RtXcastConnector::~RtXcastConnector() { _instance = nullptr; @@ -255,30 +114,16 @@ RtXcastConnector::~RtXcastConnector() bool RtXcastConnector::initialize() { - rtError err; - rtRemoteEnvironment* env = rtEnvironmentGetGlobal(); - err = rtRemoteInit(env); - if(err != RT_OK){ - LOGINFO("Xcastservice: rtRemoteInit failed : Reason %s", rtStrError(err)); - } - else { - lock_guard lock(m_threadlock); - m_runEventThread = true; - m_eventMtrThread = std::thread(threadRun, this); - } - return (err == RT_OK) ? true:false; + // @@@ TODO for GDial command line arguments @@@ + std::vector gdial_args; + gdialCastObj = gdialService::getInstance(this,gdial_args); + return (nullptr != gdialCastObj) ? true:false; } void RtXcastConnector::shutdown() { LOGINFO("Shutting down rtRemote connectivity"); - { - lock_guard lock(m_threadlock); - m_runEventThread = false; - } - if (m_eventMtrThread.joinable()) - m_eventMtrThread.join(); - - rtRemoteShutdown(rtEnvironmentGetGlobal()); + gdialService::destroyInstance(); + gdialCastObj = nullptr; if(RtXcastConnector::_instance != nullptr) { delete RtXcastConnector::_instance; @@ -290,108 +135,84 @@ int RtXcastConnector::applicationStateChanged( string app, string state, string { int status = 0; LOGINFO("XcastService::ApplicationStateChanged ARGS = %s : %s : %s : %s ", app.c_str(), id.c_str() , state.c_str() , error.c_str()); - if(xdialCastObj != NULL) + if(gdialCastObj != NULL) { - rtObjectRef e = new rtMapObject; - e.set("applicationName", app.c_str()); - e.set("applicationId", id.c_str()); - e.set("state",state.c_str()); - e.set("error",error.c_str()); - xdialCastObj.send("onApplicationStateChanged", e); + gdialCastObj->ApplicationStateChanged( app, state, id, error); status = 1; } else - LOGINFO(" xdialCastObj is NULL "); + LOGINFO(" gdialCastObj is NULL "); return status; }//app && state not empty + void RtXcastConnector::enableCastService(string friendlyname,bool enableService) { LOGINFO("XcastService::enableCastService ARGS = %s : %d ", friendlyname.c_str(), enableService); - if(xdialCastObj != NULL) + if(gdialCastObj != NULL) { - rtObjectRef e = new rtMapObject; - e.set("activation",(enableService ? "true": "false")); - e.set("friendlyname",friendlyname.c_str()); - int ret = xdialCastObj.send("onActivationChanged", e); - LOGINFO("XcastService send onActivationChanged:%d",ret); + std::string activation = enableService ? "true": "false"; + gdialCastObj->ActivationChanged( activation, friendlyname); + LOGINFO("XcastService send onActivationChanged"); } else - LOGINFO(" xdialCastObj is NULL "); - + LOGINFO(" gdialCastObj is NULL "); } void RtXcastConnector::updateFriendlyName(string friendlyname) { LOGINFO("XcastService::updateFriendlyName ARGS = %s ", friendlyname.c_str()); - if(xdialCastObj != NULL) + if(gdialCastObj != NULL) { - rtObjectRef rtObj = new rtMapObject; - rtObj.set("friendlyname",friendlyname.c_str()); - int ret = xdialCastObj.send("onFriendlyNameChanged", rtObj); - LOGINFO("XcastService send onFriendlyNameChanged ret:%d",ret); + gdialCastObj->FriendlyNameChanged( friendlyname); + LOGINFO("XcastService send onFriendlyNameChanged"); } else - LOGINFO(" xdialCastObj is NULL "); + LOGINFO(" gdialCastObj is NULL "); } string RtXcastConnector::getProtocolVersion(void) { LOGINFO("XcastService::getProtocolVersion "); - rtString strVersion ; - int ret = 0; - if(xdialCastObj != NULL && (xdialCastObj.sendReturns("getProtocolVersion", strVersion) == RT_OK)) + std::string strVersion; + if(gdialCastObj != NULL) { - LOGINFO("XcastService getProtocolVersion ret:%d version:%s ",ret,strVersion.cString()); + strVersion = gdialCastObj->getProtocolVersion(); + LOGINFO("XcastService getProtocolVersion version:%s ",strVersion.c_str()); } else { - LOGINFO(" XcastService getProtocolVersion xdialCastObj is NULL sendReturns ret :%d not RT_OK so returns 2.1",ret); - strVersion = "2.1"; + LOGINFO(" XcastService getProtocolVersion gdialCastObj is NULL so returns 2.1"); + strVersion = "2.1"; } - return strVersion.cString(); + return strVersion; } void RtXcastConnector::registerApplications(std::vector& appConfigList) { - LOGINFO("XcastService::registerApplications"); + LOGINFO("XcastService::RegisterAppEntryList"); - rtArrayObject *appReqList = new rtArrayObject; - for (DynamicAppConfig* pDynamicAppConfig : appConfigList) { - //populate the rtParam here - rtObjectRef appReq = new rtMapObject; - - rtArrayObject *appNameList = new rtArrayObject; - appNameList->pushBack (pDynamicAppConfig->appName); - appReq.set ("Names", rtValue(appNameList)); - - if ('\0' != pDynamicAppConfig->prefixes[0]) { - rtArrayObject *appPrefixes = new rtArrayObject; - appPrefixes->pushBack (pDynamicAppConfig->prefixes); - appReq.set ("prefixes", rtValue(appPrefixes)); - } - - if ('\0' != pDynamicAppConfig->cors[0]) { - rtArrayObject *appCors = new rtArrayObject; - appCors->pushBack (pDynamicAppConfig->cors); - appReq.set ("cors", rtValue(appCors)); - } + RegisterAppEntryList *appReqList = new RegisterAppEntryList; - rtObjectRef appProp = new rtMapObject; - appProp.set("allowStop",pDynamicAppConfig->allowStop); - appReq.set ("properties", rtValue(appProp)); + for (DynamicAppConfig* pDynamicAppConfig : appConfigList) + { + RegisterAppEntry* appReq = new RegisterAppEntry; + + appReq->Names = pDynamicAppConfig->appName; + appReq->prefixes = pDynamicAppConfig->prefixes; + appReq->cors = pDynamicAppConfig->cors; + appReq->allowStop = pDynamicAppConfig->allowStop; - appReqList->pushBack(rtValue(appReq)); + appReqList->pushBack(appReq); } - if(xdialCastObj != NULL) + if(gdialCastObj != NULL) { - int ret = xdialCastObj.send("onRegisterApplications", appReqList); - LOGINFO("XcastService send onRegisterApplications ret:%d",ret); + gdialCastObj->RegisterApplications(appReqList); + LOGINFO("XcastService send onRegisterAppEntryList"); } else { - LOGINFO(" xdialCastObj is NULL "); - delete appReqList; + LOGINFO(" gdialCastObj is NULL "); } } @@ -404,29 +225,6 @@ RtXcastConnector * RtXcastConnector::getInstance() return RtXcastConnector::_instance; } -bool RtXcastConnector::IsDynamicAppListEnabled() -{ - bool ret = false; -#ifdef RFC_ENABLED - RFC_ParamData_t param; - WDMP_STATUS wdmpStatus = getRFCParameter(const_cast("Xcast"), "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.DynamicAppList", ¶m); - if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) - { - if( param.type == WDMP_BOOLEAN ) - { - if(strncasecmp(param.value,"true",4) == 0 ) - ret = true; - } - } - - LOGINFO(" IsDynamicAppListEnabled enabled ? %d , call value %d ", ret, wdmpStatus); -#else - ret = true; -#endif //RFC_ENABLED - - return ret; -} - bool RtXcastConnector::IsAppEnabled(char* strAppName) { bool ret = false; @@ -449,4 +247,4 @@ bool RtXcastConnector::IsAppEnabled(char* strAppName) #endif //RFC_ENABLED return ret; -} +} \ No newline at end of file diff --git a/XCast/RtXcastConnector.h b/XCast/RtXcastConnector.h index 76942934db..954cc5bb78 100644 --- a/XCast/RtXcastConnector.h +++ b/XCast/RtXcastConnector.h @@ -22,21 +22,21 @@ #include #include -#include -#include -#include #include "RtNotifier.h" #include "XCastCommon.h" +#include +#include using namespace std; /** * This is the connector class for interacting with xdial client using rtRemote. */ -class RtXcastConnector { +class RtXcastConnector : public GDialNotifier +{ protected: - RtXcastConnector():m_runEventThread(true) ,m_IsDefaultDynamicAppListEnabled(false){ - } + //RtXcastConnector():m_runEventThread(true){} + RtXcastConnector(){} public: virtual ~RtXcastConnector(); /** @@ -72,11 +72,18 @@ class RtXcastConnector { *Request the single instance of this class */ static RtXcastConnector * getInstance(); + + virtual void onApplicationLaunchRequest(string appName, string parameter) override; + virtual void onApplicationLaunchRequestWithLaunchParam (string appName,string strPayLoad, string strQuery, string strAddDataUrl) override; + virtual void onApplicationStopRequest(string appName, string appID) override; + virtual void onApplicationHideRequest(string appName, string appID) override; + virtual void onApplicationResumeRequest(string appName, string appID) override; + virtual void onApplicationStateRequest(string appName, string appID) override; + /** *Call back function for rtConnection */ - int connectToRemoteService(); - bool IsDynamicAppListEnabled(); + //int connectToRemoteService(); void setService(RtNotifier * service){ m_observer = service; @@ -86,27 +93,18 @@ class RtXcastConnector { //RT Connector class RtNotifier * m_observer; //Event Monitoring thread - thread m_eventMtrThread; + //thread m_eventMtrThread; // Atomic lock - mutex m_threadlock; + //mutex m_threadlock; // Boolean event thread exit condition - bool m_runEventThread; - bool m_IsDefaultDynamicAppListEnabled; + //bool m_runEventThread; // Member function to handle RT messages. - void processRtMessages(); + //void processRtMessages(); bool IsAppEnabled(char* strAppName); // Class level contracts // Singleton instance static RtXcastConnector * _instance; // Thread main function - static void threadRun(RtXcastConnector *rtCtx); - - static rtError onApplicationLaunchRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context); - static rtError onApplicationHideRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context); - static rtError onApplicationResumeRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context); - static rtError onApplicationStateRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context); - static rtError onApplicationStopRequestCallback(int numArgs, const rtValue* args, rtValue* result, void* context); - static rtError onRtServiceByeCallback(int numArgs, const rtValue* args, rtValue* result, void* context); - static void remoteDisconnectCallback(void * context); + //static void threadRun(RtXcastConnector *rtCtx); }; diff --git a/XCast/XCast.conf.in b/XCast/XCast.conf.in index 7d2fbeefc9..060338aad8 100644 --- a/XCast/XCast.conf.in +++ b/XCast/XCast.conf.in @@ -2,3 +2,19 @@ precondition = ["Platform"] callsign = "org.rdk.Xcast" autostart = "@PLUGIN_XCAST_AUTOSTART@" startuporder = "@PLUGIN_XCAST_STARTUPORDER@" + +configuration = JSON() + +configuration.add("endpoint", "@PLUGIN_TEXTTOSPEECH_ENDPOINT@") +configuration.add("secureendpoint", "@PLUGIN_TEXTTOSPEECH_SECURE_ENDPOINT@") +configuration.add("endpoint_type", "@PLUGIN_TEXTTOSPEECH_ENDPOINT_TYPE@") +configuration.add("localendpoint", "@PLUGIN_TEXTTOSPEECH_LOCAL_ENDPOINT@") +configuration.add("speechrate", "@PLUGIN_TEXTTOSPEECH_SPEECHRATE@") +configuration.add("satplugincallsign", "@PLUGIN_TEXTTOSPEECH_SATPLUGINCALLSIGN@") +configuration.add("language", "@PLUGIN_TEXTTOSPEECH_LANGUAGE@") +configuration.add("volume", "@PLUGIN_TEXTTOSPEECH_VOLUME@") +configuration.add("rate", "@PLUGIN_TEXTTOSPEECH_RATE@") + +rootobject = JSON() +rootobject.add("mode", "@PLUGIN_TEXTTOSPEECH_MODE@") +configuration.add("root", rootobject) \ No newline at end of file diff --git a/XCast/XCast.config b/XCast/XCast.config index e7f409fd15..20d85ef465 100644 --- a/XCast/XCast.config +++ b/XCast/XCast.config @@ -5,3 +5,8 @@ set (callsign "org.rdk.Xcast") if(PLUGIN_XCAST_STARTUPORDER) set (startuporder ${PLUGIN_XCAST_STARTUPORDER}) endif() + +map() + kv(mode ${PLUGIN_XCAST_MODE}) +end() +ans(rootobject) \ No newline at end of file diff --git a/XCast/XCast.cpp b/XCast/XCast.cpp index 2fe743699d..087f59d293 100644 --- a/XCast/XCast.cpp +++ b/XCast/XCast.cpp @@ -26,9 +26,7 @@ #endif //RFC_ENABLED #include #include -#include "RtXcastConnector.h" -#include "UtilsSynchroIarm.hpp" - +//#include "RtXcastConnector.h" using namespace std; // Events @@ -70,7 +68,7 @@ using namespace std; #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 0 -#define API_VERSION_NUMBER_PATCH 20 +#define API_VERSION_NUMBER_PATCH 17 namespace WPEFramework { @@ -90,11 +88,12 @@ namespace { namespace Plugin { +/** + *Register XCast module as wpeframework plugin + **/ SERVICE_REGISTRATION(XCast, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); -static RtXcastConnector * _rtConnector = RtXcastConnector::getInstance(); -static int locateCastObjectRetryCount = 0; -bool XCast::isCastEnabled = false; +//static int locateCastObjectRetryCount = 0; #ifdef XCAST_ENABLED_BY_DEFAULT bool XCast::m_xcastEnable = true; #else @@ -106,32 +105,14 @@ bool XCast::m_standbyBehavior = true; #else bool XCast::m_standbyBehavior = false; #endif -bool XCast::m_enableStatus = false; IARM_Bus_PWRMgr_PowerState_t XCast::m_powerState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; -bool powerModeChangeActive = false; XCast::XCast() : PluginHost::JSONRPC() -, m_apiVersionNumber(1), m_isDynamicRegistrationsRequired(false) + , _notification(this) + , m_apiVersionNumber(API_VERSION_NUMBER_MAJOR) { - XCast::checkRFCServiceStatus(); - if(XCast::isCastEnabled) - { - LOGINFO("XcastService::Register methods and create onLocateCastTimer "); - Utils::Synchro::RegisterLockedApi(METHOD_GET_API_VERSION_NUMBER, &XCast::getApiVersionNumber, this); - Utils::Synchro::RegisterLockedApi(METHOD_ON_APPLICATION_STATE_CHANGED , &XCast::applicationStateChanged, this); - Utils::Synchro::RegisterLockedApi(METHOD_SET_ENABLED, &XCast::setEnabled, this); - Utils::Synchro::RegisterLockedApi(METHOD_GET_ENABLED, &XCast::getEnabled, this); - Utils::Synchro::RegisterLockedApi(METHOD_GET_STANDBY_BEHAVIOR, &XCast::getStandbyBehavior, this); - Utils::Synchro::RegisterLockedApi(METHOD_SET_STANDBY_BEHAVIOR, &XCast::setStandbyBehavior, this); - Utils::Synchro::RegisterLockedApi(METHOD_GET_FRIENDLYNAME, &XCast::getFriendlyName, this); - Utils::Synchro::RegisterLockedApi(METHOD_SET_FRIENDLYNAME, &XCast::setFriendlyName, this); - Utils::Synchro::RegisterLockedApi(METHOD_REG_APPLICATIONS, &XCast::registerApplications, this); - Utils::Synchro::RegisterLockedApi(METHOD_UNREG_APPLICATIONS, &XCast::unregisterApplications, this); - Utils::Synchro::RegisterLockedApi(METHOD_GET_PROTOCOLVERSION, &XCast::getProtocolVersion, this); - - m_locateCastTimer.connect( bind( &XCast::onLocateCastTimer, this )); - } + } XCast::~XCast() @@ -142,75 +123,116 @@ XCast::~XCast() delete m_SystemPluginObj; m_SystemPluginObj = nullptr; } - m_CurrentService = NULL; + _service = nullptr; } + +void XCast::RegisterAll() +{ + LOGINFO("XcastService::Register methods and create onLocateCastTimer "); + Register(METHOD_GET_API_VERSION_NUMBER, &XCast::getApiVersionNumber, this); + Register(METHOD_ON_APPLICATION_STATE_CHANGED , &XCast::applicationStateChanged, this); + Register(METHOD_SET_ENABLED, &XCast::setEnabled, this); + Register(METHOD_GET_ENABLED, &XCast::getEnabled, this); + Register(METHOD_GET_STANDBY_BEHAVIOR, &XCast::getStandbyBehavior, this); + Register(METHOD_SET_STANDBY_BEHAVIOR, &XCast::setStandbyBehavior, this); + Register(METHOD_GET_FRIENDLYNAME, &XCast::getFriendlyName, this); + Register(METHOD_SET_FRIENDLYNAME, &XCast::setFriendlyName, this); + Register(METHOD_REG_APPLICATIONS, &XCast::registerApplications, this); + Register(METHOD_UNREG_APPLICATIONS, &XCast::unregisterApplications, this); + Register(METHOD_GET_PROTOCOLVERSION, &XCast::getProtocolVersion, this); + + //m_locateCastTimer.connect( bind( &XCast::onLocateCastTimer, this )); +} + void XCast::InitializeIARM() { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( Utils::Synchro::RegisterLockedIarmEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_MODECHANGED, powerModeChange) ); - IARM_Bus_PWRMgr_GetPowerState_Param_t param; - res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_GetPowerState, + if (Utils::IARM::init()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_MODECHANGED, powerModeChange) ); + IARM_Bus_PWRMgr_GetPowerState_Param_t param; + res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_GetPowerState, (void *)¶m, sizeof(param)); - if (res == IARM_RESULT_SUCCESS) - { - m_powerState = param.curState; - } - LOGINFO("XcastService::m_powerState:%d ",m_powerState); - } + if (res == IARM_RESULT_SUCCESS) + { + m_powerState = param.curState; + } + LOGINFO("XcastService::m_powerState:%d ",m_powerState); + } } + void XCast::DeinitializeIARM() { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( Utils::Synchro::RemoveLockedEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_MODECHANGED, powerModeChange) ); - } - Unregister(METHOD_GET_API_VERSION_NUMBER); - Unregister(METHOD_ON_APPLICATION_STATE_CHANGED); - Unregister(METHOD_SET_ENABLED); - Unregister(METHOD_GET_ENABLED); - Unregister(METHOD_GET_STANDBY_BEHAVIOR); - Unregister(METHOD_SET_STANDBY_BEHAVIOR); - Unregister(METHOD_GET_FRIENDLYNAME); - Unregister(METHOD_SET_FRIENDLYNAME); + if (Utils::IARM::isConnected()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_MODECHANGED, powerModeChange) ); + } + Unregister(METHOD_GET_API_VERSION_NUMBER); + Unregister(METHOD_ON_APPLICATION_STATE_CHANGED); + Unregister(METHOD_SET_ENABLED); + Unregister(METHOD_GET_ENABLED); + Unregister(METHOD_GET_STANDBY_BEHAVIOR); + Unregister(METHOD_SET_STANDBY_BEHAVIOR); + Unregister(METHOD_GET_FRIENDLYNAME); + Unregister(METHOD_SET_FRIENDLYNAME); } void XCast::powerModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len) { - if (strcmp(owner, IARM_BUS_PWRMGR_NAME) == 0) { - if (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED ) { - IARM_Bus_PWRMgr_EventData_t *param = (IARM_Bus_PWRMgr_EventData_t *)data; - LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", - param->data.state.curState, param->data.state.newState); + if (strcmp(owner, IARM_BUS_PWRMGR_NAME) == 0) { + if (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED ) { + IARM_Bus_PWRMgr_EventData_t *param = (IARM_Bus_PWRMgr_EventData_t *)data; + LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", + param->data.state.curState, param->data.state.newState); m_powerState = param->data.state.newState; LOGWARN("creating worker thread for threadPowerModeChangeEvent m_powerState :%d",m_powerState); std::thread powerModeChangeThread = std::thread(threadPowerModeChangeEvent); powerModeChangeThread.detach(); - } + } } } const string XCast::Initialize(PluginHost::IShell *service) { - LOGINFO("XCast:: Initialize plugin called \n"); - InitializeIARM(); - _rtConnector = RtXcastConnector::getInstance(); - _rtConnector->setService(this); - if (XCast::isCastEnabled) - { - //TODO add rt intialization. - if( _rtConnector->initialize()) - { - //We give few seconds delay before the timer is fired. - m_locateCastTimer.start(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); + ASSERT(_service == nullptr); + + _connectionId = 0; + _service = service; + _skipURL = static_cast(_service->WebPrefix().length()); + + _service->Register(&_notification); + + _xcast = _service->Root(_connectionId, 5000, _T("XCastImplementation")); + + std::string message; + if(_xcast != nullptr) { + #ifndef UNIT_TESTING + ASSERT(_connectionId != 0); + #endif + + PluginHost::IStateControl* stateControl(_xcast->QueryInterface()); + + if (stateControl == nullptr) { + _xcast->Release(); + _xcast = nullptr; + } else { + if (stateControl->Configure(_service) != Core::ERROR_NONE) { + _xcast->Release(); + _xcast = nullptr; + } + stateControl->Release(); } - m_CurrentService = service; + } + + if(_xcast != nullptr) { + _xcast->Register(&_notification); + RegisterAll(); + InitializeIARM(); + getSystemPlugin(); // subscribe for event - m_SystemPluginObj->Subscribe(1000, "onFriendlyNameChanged" - , &XCast::onFriendlyNameUpdateHandler, this); + m_SystemPluginObj->Subscribe(1000, "onFriendlyNameChanged", &XCast::onFriendlyNameUpdateHandler, this); if (Core::ERROR_NONE == updateSystemFriendlyName()) { LOGINFO("XCast::Initialize m_friendlyName: %s\n ",m_friendlyName.c_str()); @@ -218,49 +240,68 @@ const string XCast::Initialize(PluginHost::IShell *service) } else { - LOGINFO(" Cast service is disabled. Not initializing"); + message = _T("XCast could not be instantiated."); + _service->Unregister(&_notification); + _service = nullptr; } - // On success return empty, to indicate there is no error text. - return (string()); + + return message; } -void XCast::Deinitialize(PluginHost::IShell* /* service */) +void XCast::Deinitialize(PluginHost::IShell* service) { - LOGINFO("XCast::Deinitialize called \n "); - int count = 0; - while(powerModeChangeActive && count < 20){ - sleep(100); - count++; - } - if ( m_locateCastTimer.isActive()) - { - m_locateCastTimer.stop(); - } - if( XCast::isCastEnabled){ - _rtConnector->enableCastService(m_friendlyName,false); - _rtConnector->shutdown(); + ASSERT(_service == service); + ASSERT(_xcast != nullptr); + + if(_xcast) + _xcast->Unregister(&_notification); + + if(_service) + _service->Unregister(&_notification); + + if(_xcast) { + if(_xcast->Release() != Core::ERROR_DESTRUCTION_SUCCEEDED) { + ASSERT(_connectionId != 0); + LOGINFO("XCast Plugin is not properly destructed. %d", _connectionId); + + if(_service) { + RPC::IRemoteConnection* connection(_service->RemoteConnection(_connectionId)); + + // The process can disappear in the meantime... + if (connection != nullptr) { + // But if it did not dissapear in the meantime, forcefully terminate it. Shoot to kill :-) + connection->Terminate(); + connection->Release(); + } + } + } } - DeinitializeIARM(); + + _xcast = nullptr; + _service = nullptr; } -string XCast::Information() const +void XCast::Deactivated(RPC::IRemoteConnection* connection) { - // No additional info to report. - return (string()); + if (connection->Id() == _connectionId) { + ASSERT(_service != nullptr); + LOGINFO("XCast::Deactivated - %p", this); + Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); + } } - uint32_t XCast::getApiVersionNumber(const JsonObject& parameters, JsonObject& response) { LOGINFOMETHOD(); response["version"] = m_apiVersionNumber; returnResponse(true); } + uint32_t XCast::applicationStateChanged(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::ApplicationStateChanged () "); - string app,id,state,error; + bool returnStatus = false; getStringParameter("applicationName",app); getStringParameter("state", state); @@ -272,39 +313,55 @@ uint32_t XCast::applicationStateChanged(const JsonObject& parameters, JsonObject { getStringParameter("error", error); } - if(!app.empty() && !state.empty()) + if (!app.empty() && !state.empty() && (nullptr != _xcast)) { if (app == "NetflixApp") app = "Netflix"; LOGINFO("XcastService::ApplicationStateChanged ARGS = %s : %s : %s : %s ", app.c_str(), id.c_str() , state.c_str() , error.c_str()); - _rtConnector->applicationStateChanged(app, state, id, error); - returnResponse(true); - }//app && state not empty - else{ - returnResponse(false); + auto result = _xcast->applicationStateChanged(app,state,id,error); + if (Core::ERROR_NONE == result) + { + returnStatus = true; + } } + returnResponse(returnStatus); } uint32_t XCast::setEnabled(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::setEnabled "); - bool enabled = false; + bool enabled = false, + returnStatus = false; if (parameters.HasLabel("enabled")) { - getBoolParameter("enabled", enabled); + getBoolParameter("enabled", enabled); } else { - returnResponse(false); + returnResponse(false); } m_xcastEnable= enabled; - if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) - _rtConnector->enableCastService(m_friendlyName,true); + if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)))) + { + enabled = true; + } else - _rtConnector->enableCastService(m_friendlyName,false); - returnResponse(true); + { + enabled = false; + } + + if ( nullptr != _xcast ) + { + auto result = _xcast->enableCastService(m_friendlyName,enabled); + if (Core::ERROR_NONE == result) + { + returnStatus = true; + } + } + returnResponse(returnStatus); } + uint32_t XCast::getEnabled(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::getEnabled "); @@ -312,7 +369,6 @@ uint32_t XCast::getEnabled(const JsonObject& parameters, JsonObject& response) returnResponse(true); } - uint32_t XCast::setStandbyBehavior(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::setStandbyBehavior \n "); @@ -326,12 +382,13 @@ uint32_t XCast::setStandbyBehavior(const JsonObject& parameters, JsonObject& res } else { - returnResponse(false); + returnResponse(false); } m_standbyBehavior = enabled; LOGINFO("XcastService::setStandbyBehavior m_standbyBehavior : %d", m_standbyBehavior); returnResponse(true); } + uint32_t XCast::getStandbyBehavior(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::getStandbyBehavior m_standbyBehavior :%d",m_standbyBehavior); @@ -347,37 +404,38 @@ uint32_t XCast::setFriendlyName(const JsonObject& parameters, JsonObject& respon { LOGINFO("XcastService::setFriendlyName \n "); std::string paramStr; + bool enabledStatus = false, + returnStatus = false; + if (parameters.HasLabel("friendlyname")) { - getStringParameter("friendlyname",paramStr); - if(_rtConnector) - { + getStringParameter("friendlyname",paramStr); + if(nullptr != _xcast) + { m_friendlyName = paramStr; LOGINFO("XcastService::setFriendlyName :%s",m_friendlyName.c_str()); - if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { - _rtConnector->enableCastService(m_friendlyName,true); + if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)))) + { + enabledStatus = true; } - else { - _rtConnector->enableCastService(m_friendlyName,false); + else + { + enabledStatus = false; } - } - else - returnResponse(false); - } - else - { - returnResponse(false); + _xcast->enableCastService(m_friendlyName,enabledStatus); + returnStatus = true; + } } - returnResponse(true); + returnResponse(returnStatus); } + uint32_t XCast::getFriendlyName(const JsonObject& parameters, JsonObject& response) { - LOGINFO("XcastService::getFriendlyNamem_friendlyName :%s ",m_friendlyName.c_str()); + LOGINFO("XcastService::getFriendlyName :%s ",m_friendlyName.c_str()); response["friendlyname"] = m_friendlyName; returnResponse(true); } - void XCast::getSystemPlugin() { LOGINFO("Entering..!!!"); @@ -385,7 +443,7 @@ void XCast::getSystemPlugin() { string token; // TODO: use interfaces and remove token - auto security = m_CurrentService->QueryInterfaceByCallsign("SecurityAgent"); + auto security = _service->QueryInterfaceByCallsign("SecurityAgent"); if (nullptr != security) { string payload = "http://localhost"; @@ -393,30 +451,30 @@ void XCast::getSystemPlugin() reinterpret_cast(payload.c_str()), token) == Core::ERROR_NONE) { - LOGINFO("got security token\n"); + LOGINFO("got security token\n"); } else { - LOGERR("failed to get security token\n"); + LOGERR("failed to get security token\n"); } security->Release(); - } - else - { - LOGERR("No security agent\n"); - } - - string query = "token=" + token; - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(SERVER_DETAILS))); - m_SystemPluginObj = new WPEFramework::JSONRPC::LinkType(_T(SYSTEM_CALLSIGN_VER), (_T(SYSTEM_CALLSIGN_VER)), false, query); - if (nullptr == m_SystemPluginObj) - { - LOGERR("JSONRPC: %s: initialization failed", SYSTEM_CALLSIGN_VER); - } - else - { - LOGINFO("JSONRPC: %s: initialization ok", SYSTEM_CALLSIGN_VER); - } + } + else + { + LOGERR("No security agent\n"); + } + + string query = "token=" + token; + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(SERVER_DETAILS))); + m_SystemPluginObj = new WPEFramework::JSONRPC::LinkType(_T(SYSTEM_CALLSIGN_VER), (_T(SYSTEM_CALLSIGN_VER)), false, query); + if (nullptr == m_SystemPluginObj) + { + LOGERR("JSONRPC: %s: initialization failed", SYSTEM_CALLSIGN_VER); + } + else + { + LOGINFO("JSONRPC: %s: initialization ok", SYSTEM_CALLSIGN_VER); + } } LOGINFO("Exiting..!!!"); } @@ -438,12 +496,12 @@ int XCast::updateSystemFriendlyName() { if (Result["success"].Boolean()) { - m_friendlyName = Result["friendlyName"].String(); + m_friendlyName = Result["friendlyName"].String(); } else { - ret = Core::ERROR_GENERAL; - LOGERR("getSystemFriendlyName call failed"); + ret = Core::ERROR_GENERAL; + LOGERR("getSystemFriendlyName call failed"); } } else @@ -455,12 +513,23 @@ int XCast::updateSystemFriendlyName() uint32_t XCast::getProtocolVersion(const JsonObject& parameters, JsonObject& response) { + string protocolVersion; + bool returnStatus = false; LOGINFO("XcastService::getProtocolVersion"); - response["version"] = _rtConnector->getProtocolVersion(); - returnResponse(true); + if (nullptr != _xcast) + { + auto result = _xcast->getProtocolVersion(protocolVersion); + if (result == Core::ERROR_NONE) + { + returnStatus = true; + response["version"] = protocolVersion.c_str(); + } + } + returnResponse(returnStatus); } -bool XCast::getEntryFromAppLaunchParamList (const char* appName, DynamicAppConfig& retAppConfig){ +bool XCast::getEntryFromAppLaunchParamList (const char* appName, DynamicAppConfig& retAppConfig) +{ bool isEntryFound = false; {lock_guard lck(m_appConfigMutex); for (DynamicAppConfig* regAppLaunchParam : m_appConfigCache) { @@ -468,13 +537,12 @@ bool XCast::getEntryFromAppLaunchParamList (const char* appName, DynamicAppConfi isEntryFound = true; strncpy (retAppConfig.appName, regAppLaunchParam->appName, sizeof(retAppConfig.appName)); retAppConfig.appName[sizeof(retAppConfig.appName) - 1] = '\0'; - + strncpy (retAppConfig.query, regAppLaunchParam->query, sizeof(retAppConfig.query)); retAppConfig.query[sizeof(retAppConfig.query) - 1] = '\0'; - + strncpy (retAppConfig.payload, regAppLaunchParam->payload, sizeof(retAppConfig.payload)); retAppConfig.payload[sizeof(retAppConfig.payload) - 1] = '\0'; - break; } } @@ -488,12 +556,12 @@ void XCast::dumpDynamicAppConfigCache(string strListName, std::vectorappName, - pDynamicAppConfig->prefixes, - pDynamicAppConfig->cors, - pDynamicAppConfig->allowStop, - pDynamicAppConfig->query, - pDynamicAppConfig->payload); + pDynamicAppConfig->appName, + pDynamicAppConfig->prefixes, + pDynamicAppConfig->cors, + pDynamicAppConfig->allowStop, + pDynamicAppConfig->query, + pDynamicAppConfig->payload); } LOGINFO ("================================================================="); } @@ -727,100 +795,85 @@ void XCast::updateDynamicAppCache(JsonArray applications) uint32_t XCast::registerApplications(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::registerApplications \n "); - bool hasAppReq = parameters.HasLabel("applications"); - if (hasAppReq) { - LOGINFO ("\nInput string is:%s\n", parameters["applications"].String().c_str()); - - if(_rtConnector) - { - LOGINFO("%s:%d _rtConnector Not NULL", __FUNCTION__, __LINE__); - if(_rtConnector->IsDynamicAppListEnabled()) { - /*Disable cast service before registering Applications*/ - _rtConnector->enableCastService(m_friendlyName,false); - - m_isDynamicRegistrationsRequired = true; - //Register dynamic application list to app cache map - updateDynamicAppCache(parameters["applications"].Array()); - std::vector appConfigList; - {lock_guard lck(m_appConfigMutex); - appConfigList = m_appConfigCache; - } - dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); - //Pass the dynamic cache to xdial process - _rtConnector->registerApplications (m_appConfigCache); - - /*Reenabling cast service after registering Applications*/ - if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { - LOGINFO("Enable CastService m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); - _rtConnector->enableCastService(m_friendlyName,true); - } - else { - LOGINFO("CastService not enabled m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); - } - returnResponse(true); - } - else { - returnResponse(false); - } - } - else - returnResponse(false); - } - else { - returnResponse(false); + bool hasAppReq = parameters.HasLabel("applications"), + returnStatus = false; + if (hasAppReq) + { + LOGINFO ("\nInput string is:%s\n", parameters["applications"].String().c_str()); + + if(nullptr != _xcast) + { + LOGINFO("%s:%d _xcast Not NULL", __FUNCTION__, __LINE__); + /*Disable cast service before registering Applications*/ + _xcast->enableCastService(m_friendlyName,false); + + m_isDynamicRegistrationsRequired = true; + //Register dynamic application list to app cache map + updateDynamicAppCache(parameters["applications"].Array()); + std::vector appConfigList; + {lock_guard lck(m_appConfigMutex); + appConfigList = m_appConfigCache; + } + dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); + //Pass the dynamic cache to xdial process + registerApplicationsInternal(m_appConfigCache); + + /*Reenabling cast service after registering Applications*/ + if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { + LOGINFO("Enable CastService m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); + _xcast->enableCastService(m_friendlyName,true); + } + else { + LOGINFO("CastService not enabled m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); + } + returnStatus = true; + } } + returnResponse(returnStatus); } uint32_t XCast::unregisterApplications(const JsonObject& parameters, JsonObject& response) { LOGINFO("XcastService::unregisterApplications \n "); - bool hasAppReq = parameters.HasLabel("applications"); - if (hasAppReq) { - LOGINFO ("\nInput string is:%s\n", parameters["applications"].String().c_str()); - - if(_rtConnector) - { - LOGINFO("%s:%d _rtConnector Not NULL", __FUNCTION__, __LINE__); - if(_rtConnector->IsDynamicAppListEnabled()) { - /*Disable cast service before registering Applications*/ - _rtConnector->enableCastService(m_friendlyName,false); - m_isDynamicRegistrationsRequired = true; - //Remove app names from cache map - bool ret = deleteFromDynamicAppCache (parameters["applications"].Array()); - std::vector appConfigList; - {lock_guard lck(m_appConfigMutex); - appConfigList = m_appConfigCache; - } - dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); - //Pass the dynamic cache to xdial process - _rtConnector->registerApplications (appConfigList); - - /*Reenabling cast service after registering Applications*/ - if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { - LOGINFO("Enable CastService m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); - _rtConnector->enableCastService(m_friendlyName,true); - } - else { - LOGINFO("CastService not enabled m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); - } - returnResponse(ret); - } - else { - returnResponse(false); - } - } - else - returnResponse(false); - } - else { - returnResponse(false); + bool hasAppReq = parameters.HasLabel("applications"), + returnStatus = false; + if (hasAppReq) + { + LOGINFO ("\nInput string is:%s\n", parameters["applications"].String().c_str()); + if(_xcast) + { + LOGINFO("%s:%d _xcast Not NULL", __FUNCTION__, __LINE__); + /*Disable cast service before registering Applications*/ + _xcast->enableCastService(m_friendlyName,false); + m_isDynamicRegistrationsRequired = true; + //Remove app names from cache map + returnStatus = deleteFromDynamicAppCache (parameters["applications"].Array()); + std::vector appConfigList; + {lock_guard lck(m_appConfigMutex); + appConfigList = m_appConfigCache; + } + dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); + //Pass the dynamic cache to xdial process + registerApplicationsInternal (appConfigList); + + /*Reenabling cast service after registering Applications*/ + if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { + LOGINFO("Enable CastService m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); + _xcast->enableCastService(m_friendlyName,true); + } + else { + LOGINFO("CastService not enabled m_xcastEnable: %d m_standbyBehavior: %d m_powerState:%d", m_xcastEnable, m_standbyBehavior, m_powerState); + } + } } + returnResponse(returnStatus); } +#if 0 //Timer Functions void XCast::onLocateCastTimer() { - int status = _rtConnector->connectToRemoteService(); + int status = _xcast->connectToRemoteService(); if(status != 0) { if(locateCastObjectRetryCount < 4) @@ -852,39 +905,67 @@ void XCast::onLocateCastTimer() locateCastObjectRetryCount = 0; m_locateCastTimer.stop(); - if (NULL != _rtConnector) { - if (_rtConnector->IsDynamicAppListEnabled() && m_isDynamicRegistrationsRequired) { - - std::vector appConfigList; - {lock_guard lck(m_appConfigMutex); - appConfigList = m_appConfigCache; - } - dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); - LOGINFO("XCast::onLocateCastTimer : calling registerApplications"); - _rtConnector->registerApplications (appConfigList); - } - else { - LOGINFO("XCast::onLocateCastTimer : DynamicAppList not enabled"); + if (NULL != _xcast) + { + std::vector appConfigList; + {lock_guard lck(m_appConfigMutex); + appConfigList = m_appConfigCache; } + dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); + LOGINFO("XCast::onLocateCastTimer : calling registerApplications"); + registerApplicationsInternal(appConfigList); } else { - LOGINFO("XCast::onLocateCastTimer :_rtConnector: %p", _rtConnector); + LOGINFO("XCast::onLocateCastTimer :_xcast: %p", _xcast); } + + bool enabledStatus = false; if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { - _rtConnector->enableCastService(m_friendlyName,true); + enabledStatus = true; } - else { - _rtConnector->enableCastService(m_friendlyName,false); - } - + _xcast->enableCastService(m_friendlyName,enabledStatus); LOGINFO("XCast::onLocateCastTimer : Timer still active ? %d ",m_locateCastTimer.isActive()); } +#endif + +uint32_t XCast::registerApplicationsInternal(std::vector appConfigEntries) +{ + std::list appInfoList; + Exchange::IXCast::IApplicationInfoIterator* appInfoLists{}; + uint32_t rc = Core::ERROR_UNAVAILABLE; + + for (auto appConfig : appConfigEntries) + { + Exchange::IXCast::ApplicationInfo appinfo; + appinfo.appName = appConfig->appName; + appinfo.prefixes = appConfig->prefixes; + appinfo.cors = appConfig->cors; + appinfo.query = appConfig->query; + appinfo.payload = appConfig->payload; + appinfo.allowStop = appConfig->allowStop; + appInfoList.emplace_back(appinfo); + } + appInfoLists = (Core::Service>::Create(appInfoList)); + + if (nullptr != _xcast) + { + rc = _xcast->registerApplications(appInfoLists); + } + + if (appInfoLists) + { + appInfoLists->Release(); + } + return rc; +} -void XCast::onRtServiceDisconnected() +#if 0 +void XCast::onRtServiceDisconnected() { LOGINFO("RT communication failure. Reconnecting.. "); m_locateCastTimer.start(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); } +#endif void XCast::getUrlFromAppLaunchParams (const char *app_name, const char *payload, const char *query_string, const char *additional_data_url, char *url) { LOGINFO("getUrlFromAppLaunchParams : Application launch request: appName: %s query: [%s], payload: [%s], additionalDataUrl [%s]\n", @@ -972,194 +1053,5 @@ void XCast::getUrlFromAppLaunchParams (const char *app_name, const char *payload LOGINFO(" url is [%s]\r\n", url); } } - -void XCast::onXcastApplicationLaunchRequestWithLaunchParam (string appName, - string strPayLoad, string strQuery, string strAddDataUrl) -{ - //TODO - LOGINFO ("XcastService::onXcastApplicationLaunchRequestWithLaunchParam "); - if(strAddDataUrl.size() > DIAL_MAX_ADDITIONALURL){ - LOGWARN ("%s - current additional data size (%d) exceeds maximum allowed size (%d) ", __PRETTY_FUNCTION__, (int)strAddDataUrl.size(), DIAL_MAX_ADDITIONALURL); - return; - } - if(strPayLoad.size() > DIAL_MAX_PAYLOAD) { - LOGWARN ("%s - current payload size (%d) exceeds maximum allowed size (%d) ", __PRETTY_FUNCTION__, (int)strPayLoad.size(), DIAL_MAX_PAYLOAD); - return; - } - JsonObject params; - JsonObject urlParam; - char url[DIAL_MAX_PAYLOAD+DIAL_MAX_ADDITIONALURL+100] = {0,}; - - if(_rtConnector) { - DynamicAppConfig appConfig{}; - getEntryFromAppLaunchParamList (appName.c_str(), appConfig); - - /*Replacing with App requested payload and query*/ - if (('\0' != appConfig.query[0]) && ('\0' != appConfig.payload[0])) { - getUrlFromAppLaunchParams (appName.c_str(), - appConfig.payload, - appConfig.query, - strAddDataUrl.c_str(), url); - } - else if(('\0' != appConfig.payload[0])){ - getUrlFromAppLaunchParams (appName.c_str(), - appConfig.payload, - strQuery.c_str(), - strAddDataUrl.c_str(), url); - } - else if(('\0' != appConfig.query[0])) { - getUrlFromAppLaunchParams (appName.c_str(), - strPayLoad.c_str(), - appConfig.query, - strAddDataUrl.c_str(), url); - } - else { - getUrlFromAppLaunchParams (appName.c_str(), - strPayLoad.c_str(), - strQuery.c_str(), - strAddDataUrl.c_str(), url); - } - - - string strUrl = std::string (url); - if (appName == "Netflix") { - appName.assign("NetflixApp"); - urlParam["pluginUrl"]=strUrl; - } - else { - urlParam["url"]=strUrl; - } - - params["applicationName"]= appName; - params["parameters"]= urlParam; - - sendNotify(EVT_ON_LAUNCH_REQUEST, params); - } -} - -void XCast::onXcastApplicationLaunchRequest(string appName, string parameter) -{ - //TODO - LOGINFO ("XcastService::onXcastApplicationLaunchRequest "); - JsonObject params; - JsonObject urlParam; - if (appName == "NetflixApp") - urlParam["pluginUrl"]=parameter; - else - urlParam["url"]=parameter; - - params["applicationName"]= appName; - params["parameters"]= urlParam; - - sendNotify(EVT_ON_LAUNCH_REQUEST, params); -} -void XCast::onXcastApplicationStopRequest(string appName, string appID) -{ - //TODO - LOGINFO("XcastService::onXcastApplicationStopRequest "); - - JsonObject params; - params["applicationName"] = appName; - params["applicationId"]= appID; - - sendNotify(EVT_ON_STOP_REQUEST, params); -} -void XCast::onXcastApplicationHideRequest(string appName, string appID) -{ - LOGINFO("XcastService::onXcastApplicationHideRequest : "); - if (appName.compare("Netflix") == 0 ) - appName = "NetflixApp"; - - - JsonObject params; - params["applicationName"] = appName; - params["applicationId"]= appID; - - sendNotify(EVT_ON_HIDE_REQUEST, params); -} -void XCast::onXcastApplicationStateRequest(string appName, string appID) -{ - LOGINFO("XcastService::onXcastApplicationStateRequest: "); - if (appName.compare("Netflix") == 0 ) - appName = "NetflixApp"; - - JsonObject params; - params["applicationName"] = appName; - params["applicationId"]= appID; - - sendNotify(EVT_ON_STATE_REQUEST , params); - -} -void XCast::onXcastApplicationResumeRequest(string appName, string appID) -{ - LOGINFO("XcastService::onXcastApplicationResumeRequest "); - if (appName.compare("Netflix") == 0 ) - appName = "NetflixApp"; - - JsonObject params; - params["applicationName"] = appName; - params["applicationId"]= appID; - sendNotify(EVT_ON_RESUME_REQUEST, params); -} - -bool XCast::checkRFCServiceStatus() -{ -#ifdef RFC_ENABLED - RFC_ParamData_t param; - WDMP_STATUS wdmpStatus = getRFCParameter(const_cast("Xcast"), "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.Enable", ¶m); - if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) - { - if( param.type == WDMP_BOOLEAN ) - { - if(strncasecmp(param.value,"true",4) == 0 ) - XCast::isCastEnabled = true; - } - } - - LOGINFO(" Is cast enabled ? %d , call value %d ", isCastEnabled, wdmpStatus); -#else - XCast::isCastEnabled = true;; -#endif //RFC_ENABLED - - return XCast::isCastEnabled; -} - -void XCast::onFriendlyNameUpdateHandler(const JsonObject& parameters) { - string message; - string value; - parameters.ToString(message); - LOGINFO("[Friendly Name Event], %s : %s", __FUNCTION__,message.c_str()); - - if (parameters.HasLabel("friendlyName")) { - value = parameters["friendlyName"].String(); - if(_rtConnector) - { - m_friendlyName = value; - LOGINFO("onFriendlyNameUpdateHandler :%s",m_friendlyName.c_str()); - if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { - _rtConnector->enableCastService(m_friendlyName,true); - } - else { - _rtConnector->enableCastService(m_friendlyName,false); - } - } - } -} - -void XCast::threadPowerModeChangeEvent(void) -{ - powerModeChangeActive = true; - LOGINFO(" threadPowerModeChangeEvent m_standbyBehavior:%d , m_powerState:%d ",m_standbyBehavior,m_powerState); - if(m_standbyBehavior == false) - { - if(m_xcastEnable && ( m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) - _rtConnector->enableCastService(m_friendlyName,true); - else - _rtConnector->enableCastService(m_friendlyName,false); - } - powerModeChangeActive = false; -} - - } // namespace Plugin -} // namespace WPEFramework +} // namespace WPEFramework \ No newline at end of file diff --git a/XCast/XCast.h b/XCast/XCast.h index 92bc943477..854a6221f8 100644 --- a/XCast/XCast.h +++ b/XCast/XCast.h @@ -1,6 +1,6 @@ -/** - * If not stated otherwise in this file or this component's LICENSE - * file the following copyright and licenses apply: +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: * * Copyright 2020 RDK Management * @@ -15,121 +15,158 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - **/ + */ -#pragma once +/** + * @file XCast.h + * @brief Thunder Plugin based Implementation for TTS service API's (RDK-27957). + */ -#include -#include +/** + @mainpage XCast + + XCast XCast Thunder Service provides APIs for the arbitrators + * (ex: Native application such as Cobalt) to use TTS resource. + */ + +#pragma once -#include "tptimer.h" #include "Module.h" +#include +#include "tracing/Logging.h" +#include "tptimer.h" #include "RtNotifier.h" #include "libIBus.h" #include "libIBusDaemon.h" #include "pwrMgr.h" #include "XCastCommon.h" - -using namespace std; +#include +#include +#include "UtilsLogging.h" namespace WPEFramework { - namespace Plugin { -// This is a server for a JSONRPC communication channel. -// For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. -// By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. -// This realization of this interface implements, by default, the following methods on this plugin -// - exists -// - register -// - unregister -// Any other methood to be handled by this plugin can be added can be added by using the -// templated methods Register on the PluginHost::JSONRPC class. -// As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, -// this class exposes a public method called, Notify(), using this methods, all subscribed clients -// will receive a JSONRPC message as a notification, in case this method is called. -class XCast : public PluginHost::IPlugin, public PluginHost::JSONRPC, public RtNotifier { -private: - - // We do not allow this plugin to be copied !! - XCast(const XCast&) = delete; - XCast& operator=(const XCast&) = delete; - - //Begin methods - uint32_t getApiVersionNumber(const JsonObject& parameters, JsonObject& response); - uint32_t applicationStateChanged(const JsonObject& parameters, JsonObject& response); - uint32_t setEnabled(const JsonObject& parameters, JsonObject& response); - uint32_t getEnabled(const JsonObject& parameters, JsonObject& response); - uint32_t setStandbyBehavior(const JsonObject& parameters, JsonObject& response); - uint32_t getStandbyBehavior(const JsonObject& parameters, JsonObject& response); - uint32_t setFriendlyName(const JsonObject& parameters, JsonObject& response); - uint32_t getFriendlyName(const JsonObject& parameters, JsonObject& response); - uint32_t registerApplications(const JsonObject& parameters, JsonObject& response); - uint32_t unregisterApplications(const JsonObject& parameters, JsonObject& response); - uint32_t getProtocolVersion(const JsonObject& parameters, JsonObject& response); - //End methods - - //Begin events - - //End events -public: - XCast(); - virtual ~XCast(); - //Build QueryInterface implementation, specifying all possible interfaces to be returned. - BEGIN_INTERFACE_MAP(XCast) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - //IPlugin methods - virtual const string Initialize(PluginHost::IShell* service) override; - virtual void Deinitialize(PluginHost::IShell* service) override; - virtual string Information() const override; - - virtual void onRtServiceDisconnected(void) override; - virtual void onXcastApplicationLaunchRequest(string appName, string parameter) override; - virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, - string strPayLoad, string strQuery, string strAddDataUrl) override; - virtual void onXcastApplicationStopRequest(string appName, string appID) override; - virtual void onXcastApplicationHideRequest(string appName, string appID) override; - virtual void onXcastApplicationResumeRequest(string appName, string appID) override; - virtual void onXcastApplicationStateRequest(string appName, string appID) override; -private: - /** - * Whether Cast service is enabled by RFC - */ - static bool isCastEnabled; - static bool m_xcastEnable; - static IARM_Bus_PWRMgr_PowerState_t m_powerState; - uint32_t m_apiVersionNumber; - bool m_isDynamicRegistrationsRequired; - mutex m_appConfigMutex; - WPEFramework::JSONRPC::LinkType * m_SystemPluginObj = NULL; - PluginHost::IShell *m_CurrentService; - std::vector m_appConfigCache; - static string m_friendlyName; - static bool m_standbyBehavior; - static bool m_enableStatus; - //Timer related variables and functions - TpTimer m_locateCastTimer; - void InitializeIARM(); - void DeinitializeIARM(); - //Internal methods - void onLocateCastTimer(); - void getUrlFromAppLaunchParams (const char *app_name, const char *payload, const char *query_string, const char *additional_data_url, char *url); - bool getEntryFromAppLaunchParamList (const char* appName, DynamicAppConfig& retAppConfig); - void dumpDynamicAppConfigCache(string strListName, std::vector appConfigList); - bool deleteFromDynamicAppCache(JsonArray applications); - bool deleteFromDynamicAppCache(vector& appsToDelete); - void updateDynamicAppCache(JsonArray applications); - void getSystemPlugin(); - int updateSystemFriendlyName(); - void onFriendlyNameUpdateHandler(const JsonObject& parameters); - - /** - * Check whether the xdial service is allowed in this device. - */ - static bool checkRFCServiceStatus(); - static void powerModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - static void threadPowerModeChangeEvent(void); -}; + class XCast: public PluginHost::IPlugin, public PluginHost::JSONRPC { + public: + class Notification : public RPC::IRemoteConnection::INotification, + public Exchange::IXCast::INotification { + private: + Notification() = delete; + Notification(const Notification&) = delete; + Notification& operator=(const Notification&) = delete; + + public: + explicit Notification(XCast* parent) + : _parent(*parent) { + ASSERT(parent != nullptr); + } + + virtual ~Notification() { + } + + public: + virtual void onApplicationLaunchRequestWithLaunchParam(const string& appName, const string& strPayLoad, const string& strQuery, const string& strAddDataUrl) override; + virtual void onApplicationLaunchRequest(const string& appName, const string& parameter) override; + virtual void onApplicationStopRequest(const string& appName, const string& appID) override; + virtual void onApplicationHideRequest(const string& appName, const string& appID) override; + virtual void onApplicationStateRequest(const string& appName, const string& appID) override; + virtual void onApplicationResumeRequest(const string& appName, const string& appID) override; + virtual void Activated(RPC::IRemoteConnection* /* connection */) final + { + LOGINFO("XCast::Notification::Activated - %p", this); + } + + virtual void Deactivated(RPC::IRemoteConnection* connection) final + { + LOGINFO("XCast::Notification::Deactivated - %p", this); + _parent.Deactivated(connection); + } + + BEGIN_INTERFACE_MAP(Notification) + INTERFACE_ENTRY(Exchange::IXCast::INotification) + INTERFACE_ENTRY(RPC::IRemoteConnection::INotification) + END_INTERFACE_MAP + + private: + XCast& _parent; + }; + + BEGIN_INTERFACE_MAP(XCast) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + INTERFACE_AGGREGATE(Exchange::IXCast, _xcast) + END_INTERFACE_MAP + + public: + XCast(); + virtual ~XCast(); + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + virtual string Information() const override { return {}; } + + private: + // We do not allow this plugin to be copied !! + XCast(const XCast&) = delete; + XCast& operator=(const XCast&) = delete; + + void RegisterAll(); + + void Deactivated(RPC::IRemoteConnection* connection); + //Begin methods + uint32_t getApiVersionNumber(const JsonObject& parameters, JsonObject& response); + uint32_t applicationStateChanged(const JsonObject& parameters, JsonObject& response); + uint32_t setEnabled(const JsonObject& parameters, JsonObject& response); + uint32_t getEnabled(const JsonObject& parameters, JsonObject& response); + uint32_t setStandbyBehavior(const JsonObject& parameters, JsonObject& response); + uint32_t getStandbyBehavior(const JsonObject& parameters, JsonObject& response); + uint32_t setFriendlyName(const JsonObject& parameters, JsonObject& response); + uint32_t getFriendlyName(const JsonObject& parameters, JsonObject& response); + uint32_t registerApplications(const JsonObject& parameters, JsonObject& response); + uint32_t unregisterApplications(const JsonObject& parameters, JsonObject& response); + uint32_t getProtocolVersion(const JsonObject& parameters, JsonObject& response); + uint32_t registerApplicationsInternal(std::vector appConfigEntries); + //End methods + /** + * Whether Cast service is enabled by RFC + */ + static bool m_xcastEnable; + static IARM_Bus_PWRMgr_PowerState_t m_powerState; + bool m_isDynamicRegistrationsRequired; + mutex m_appConfigMutex; + WPEFramework::JSONRPC::LinkType * m_SystemPluginObj = NULL; + std::vector m_appConfigCache; + static string m_friendlyName; + static bool m_standbyBehavior; + //Timer related variables and functions + TpTimer m_locateCastTimer; + void InitializeIARM(); + void DeinitializeIARM(); + //Internal methods + void onLocateCastTimer(); + void getUrlFromAppLaunchParams (const char *app_name, const char *payload, const char *query_string, const char *additional_data_url, char *url); + bool getEntryFromAppLaunchParamList (const char* appName, DynamicAppConfig& retAppConfig); + void dumpDynamicAppConfigCache(string strListName, std::vector appConfigList); + bool deleteFromDynamicAppCache(JsonArray applications); + bool deleteFromDynamicAppCache(vector& appsToDelete); + void updateDynamicAppCache(JsonArray applications); + void getSystemPlugin(); + int updateSystemFriendlyName(); + void onFriendlyNameUpdateHandler(const JsonObject& parameters); + + /** + * Check whether the xdial service is allowed in this device. + */ + static void powerModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + static void threadPowerModeChangeEvent(void); + private: + uint8_t _skipURL{}; + uint32_t _connectionId{}; + PluginHost::IShell* _service{}; + Exchange::IXCast* _xcast{}; + Core::Sink _notification; + uint32_t m_apiVersionNumber; + friend class Notification; + }; + } // namespace Plugin } // namespace WPEFramework diff --git a/XCast/XCastImplementation.cpp b/XCast/XCastImplementation.cpp new file mode 100644 index 0000000000..144ed0b121 --- /dev/null +++ b/XCast/XCastImplementation.cpp @@ -0,0 +1,288 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "XCastImplementation.h" +#include +#include "UtilsJsonRpc.h" + +#define XCAST_IMPL_MAJOR_VERSION 1 +#define XCAST_IMPL_MINOR_VERSION 0 + +namespace WPEFramework { +namespace Plugin { + + SERVICE_REGISTRATION(XCastImplementation, XCAST_IMPL_MAJOR_VERSION, XCAST_IMPL_MINOR_VERSION); + + RtXcastConnector* XCastImplementation::_rtConnector = nullptr; + + XCastImplementation::XCastImplementation() : _adminLock() + { + if(nullptr == _rtConnector) + { + _rtConnector = RtXcastConnector::getInstance(); + if(nullptr != _rtConnector) + { + _rtConnector->setService(this); + if( _rtConnector->initialize()) + { + //We give few seconds delay before the timer is fired. + //m_locateCastTimer.start(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); + } + } + } + } + + XCastImplementation::~XCastImplementation() + { + if(_rtConnector) { + delete _rtConnector; + _rtConnector = nullptr; + } + } + + void XCastImplementation::Register(Exchange::IXCast::INotification* sink) + { + _adminLock.Lock(); + + // Make sure a sink is not registered multiple times. + ASSERT(std::find(_notificationClients.begin(), _notificationClients.end(), sink) == _notificationClients.end()); + + _notificationClients.push_back(sink); + sink->AddRef(); + + _adminLock.Unlock(); + + TRACE_L1("Registered a sink on the xcast inprocess %p", sink); + } + + void XCastImplementation::Unregister(Exchange::IXCast::INotification* sink) + { + _adminLock.Lock(); + std::list::iterator index(std::find(_notificationClients.begin(), _notificationClients.end(), sink)); + + if (index != _notificationClients.end()) { + (*index)->Release(); + _notificationClients.erase(index); + TRACE_L1("Unregistered a sink on the xcast inprocess %p", sink); + } + _adminLock.Unlock(); + } + + uint32_t XCastImplementation::Request(PluginHost::IStateControl::command command) + { + // Not implemented + return Core::ERROR_GENERAL; + } + + uint32_t XCastImplementation::Configure(PluginHost::IShell* service) + { + return Core::ERROR_NONE; + } + + uint32_t XCastImplementation::applicationStateChanged(const string& appName, const string& appstate, const string& appId, const string& error) const + { + uint32_t status = Core::ERROR_GENERAL; + if(!appName.empty() && !appstate.empty() && (nullptr != _rtConnector)) + { + LOGINFO("XcastService::ApplicationStateChanged ARGS = %s : %s : %s : %s ", appName.c_str(), appId.c_str() , appstate.c_str() , error.c_str()); + _rtConnector->applicationStateChanged(appName, appstate, appId, error); + status = Core::ERROR_NONE; + } + return status; + } + + uint32_t XCastImplementation::enableCastService(string friendlyname,bool enableService) const + { + LOGINFO("XcastService::enableCastService"); + if (nullptr != _rtConnector) + { + _rtConnector->enableCastService(friendlyname,enableService); + } + return Core::ERROR_NONE; + } + + uint32_t XCastImplementation::getProtocolVersion(string &protocolVersion) const + { + LOGINFO("XcastService::getProtocolVersion"); + if (nullptr != _rtConnector) + { + protocolVersion = _rtConnector->getProtocolVersion(); + } + return Core::ERROR_NONE; + } + + uint32_t XCastImplementation::registerApplications(IApplicationInfoIterator* const appLists) + { + LOGINFO("XcastService::registerApplications"); + std::vector appConfigListTemp; + uint32_t status = Core::ERROR_GENERAL; + + if ((nullptr != _rtConnector) && (appLists)) + { + Exchange::IXCast::ApplicationInfo entry{}; + + while (appLists->Next(entry) == true) + { + DynamicAppConfig* pDynamicAppConfig = (DynamicAppConfig*) malloc (sizeof(DynamicAppConfig)); + if (pDynamicAppConfig) + { + memset ((void*)pDynamicAppConfig, '0', sizeof(DynamicAppConfig)); + memset (pDynamicAppConfig->appName, '\0', sizeof(pDynamicAppConfig->appName)); + memset (pDynamicAppConfig->prefixes, '\0', sizeof(pDynamicAppConfig->prefixes)); + memset (pDynamicAppConfig->cors, '\0', sizeof(pDynamicAppConfig->cors)); + memset (pDynamicAppConfig->query, '\0', sizeof(pDynamicAppConfig->query)); + memset (pDynamicAppConfig->payload, '\0', sizeof(pDynamicAppConfig->payload)); + + strncpy (pDynamicAppConfig->appName, entry.appName.c_str(), sizeof(pDynamicAppConfig->appName) - 1); + strncpy (pDynamicAppConfig->prefixes, entry.prefixes.c_str(), sizeof(pDynamicAppConfig->prefixes) - 1); + strncpy (pDynamicAppConfig->cors, entry.cors.c_str(), sizeof(pDynamicAppConfig->cors) - 1); + pDynamicAppConfig->allowStop = entry.allowStop; + strncpy (pDynamicAppConfig->query, entry.query.c_str(), sizeof(pDynamicAppConfig->query) - 1); + strncpy (pDynamicAppConfig->payload, entry.payload.c_str(), sizeof(pDynamicAppConfig->payload) - 1); + appConfigListTemp.push_back (pDynamicAppConfig); + } + } + _rtConnector->registerApplications(appConfigListTemp); + status = Core::ERROR_NONE; + } + return status; + } + + void XCastImplementation::dispatchEvent(Event event, string callsign, const JsonObject ¶ms) + { + Core::IWorkerPool::Instance().Submit(Job::Create(this, event, callsign, params)); + } + + void XCastImplementation::Dispatch(Event event, string callsign, const JsonObject params) + { + _adminLock.Lock(); + std::list::iterator index(_notificationClients.begin()); + while (index != _notificationClients.end()) + { + switch(event) + { + case LAUNCH_REQUEST_WITH_PARAMS: + { + string appName = params["appName"].String(); + string strPayLoad = params["strPayLoad"].String(); + string strQuery = params["strQuery"].String(); + string strAddDataUrl = params["strAddDataUrl"].String(); + (*index)->onApplicationLaunchRequestWithLaunchParam(appName,strPayLoad,strQuery,strAddDataUrl); + } + break; + case LAUNCH_REQUEST: + { + string appName = params["appName"].String(); + string parameter = params["parameter"].String(); + (*index)->onApplicationLaunchRequest(appName,parameter); + } + break; + case STOP_REQUEST: + { + string appName = params["appName"].String(); + string appId = params["appId"].String(); + (*index)->onApplicationStopRequest(appName,appId); + } + break; + case HIDE_REQUEST: + { + string appName = params["appName"].String(); + string appId = params["appId"].String(); + (*index)->onApplicationHideRequest(appName,appId); + } + break; + case STATE_REQUEST: + { + string appName = params["appName"].String(); + string appId = params["appId"].String(); + (*index)->onApplicationStateRequest(appName,appId); + } + break; + case RESUME_REQUEST: + { + string appName = params["appName"].String(); + string appId = params["appId"].String(); + (*index)->onApplicationResumeRequest(appName,appId); + } + break; + default: break; + } + ++index; + } + _adminLock.Unlock(); + } + + void XCastImplementation::onXcastApplicationLaunchRequestWithLaunchParam (string appName, string strPayLoad, string strQuery, string strAddDataUrl) + { + LOGINFO("Notify LaunchRequestWithParam, appName: %s, strPayLoad: %s, strQuery: %s, strAddDataUrl: %s", + appName.c_str(),strPayLoad.c_str(),strQuery.c_str(),strAddDataUrl.c_str()); + JsonObject params; + params["appName"] = appName.c_str(); + params["strPayLoad"] = strPayLoad.c_str(); + params["strQuery"] = strQuery.c_str(); + params["strAddDataUrl"] = strAddDataUrl.c_str(); + dispatchEvent(LAUNCH_REQUEST_WITH_PARAMS, "", params); + } + + void XCastImplementation::onXcastApplicationLaunchRequest(string appName, string parameter) + { + LOGINFO("Notify LaunchRequest, appName: %s, parameter: %s",appName.c_str(),parameter.c_str()); + JsonObject params; + params["appName"] = appName.c_str(); + params["parameter"] = parameter.c_str(); + dispatchEvent(LAUNCH_REQUEST, "", params); + } + + void XCastImplementation::onXcastApplicationStopRequest(string appName, string appId) + { + LOGINFO("Notify StopRequest, appName: %s, appId: %s",appName.c_str(),appId.c_str()); + JsonObject params; + params["appName"] = appName.c_str(); + params["appId"] = appId.c_str(); + dispatchEvent(STOP_REQUEST, "", params); + } + + void XCastImplementation::onXcastApplicationHideRequest(string appName, string appId) + { + LOGINFO("Notify StopRequest, appName: %s, appId: %s",appName.c_str(),appId.c_str()); + JsonObject params; + params["appName"] = appName.c_str(); + params["appId"] = appId.c_str(); + dispatchEvent(HIDE_REQUEST, "", params); + } + + void XCastImplementation::onXcastApplicationResumeRequest(string appName, string appId) + { + LOGINFO("Notify StopRequest, appName: %s, appId: %s",appName.c_str(),appId.c_str()); + JsonObject params; + params["appName"] = appName.c_str(); + params["appId"] = appId.c_str(); + dispatchEvent(RESUME_REQUEST, "", params); + } + + void XCastImplementation::onXcastApplicationStateRequest(string appName, string appId) + { + LOGINFO("Notify StopRequest, appName: %s, appId: %s",appName.c_str(),appId.c_str()); + JsonObject params; + params["appName"] = appName.c_str(); + params["appId"] = appId.c_str(); + dispatchEvent(STATE_REQUEST, "", params); + } +} // namespace Plugin +} // namespace WPEFramework diff --git a/XCast/XCastImplementation.h b/XCast/XCastImplementation.h new file mode 100644 index 0000000000..9de35c189f --- /dev/null +++ b/XCast/XCastImplementation.h @@ -0,0 +1,132 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Module.h" +#include +#include +#include "tracing/Logging.h" +#include "RtXcastConnector.h" +#include "RtNotifier.h" +#include + +namespace WPEFramework { +namespace Plugin { + + class XCastImplementation : public Exchange::IXCast, public PluginHost::IStateControl, public RtNotifier { + public: + enum Event { + LAUNCH_REQUEST_WITH_PARAMS, + LAUNCH_REQUEST, + STOP_REQUEST, + HIDE_REQUEST, + STATE_REQUEST, + RESUME_REQUEST + }; + + class EXTERNAL Job : public Core::IDispatch { + protected: + Job(XCastImplementation *tts, Event event,string callsign,JsonObject ¶ms) + : _xcast(tts) + , _event(event) + , _callsign(callsign) + , _params(params) { + if (_xcast != nullptr) { + _xcast->AddRef(); + } + } + + public: + Job() = delete; + Job(const Job&) = delete; + Job& operator=(const Job&) = delete; + ~Job() { + if (_xcast != nullptr) { + _xcast->Release(); + } + } + + public: + static Core::ProxyType Create(XCastImplementation *tts, Event event,string callsign,JsonObject params) { +#ifndef USE_THUNDER_R4 + return (Core::proxy_cast(Core::ProxyType::Create(tts, event, callsign, params))); +#else + return (Core::ProxyType(Core::ProxyType::Create(tts, event, callsign, params))); +#endif + } + + virtual void Dispatch() { + _xcast->Dispatch(_event, _callsign, _params); + } + + private: + XCastImplementation *_xcast; + const Event _event; + const string _callsign; + const JsonObject _params; + }; + + public: + // We do not allow this plugin to be copied !! + XCastImplementation(const XCastImplementation&) = delete; + XCastImplementation& operator=(const XCastImplementation&) = delete; + + virtual void Register(Exchange::IXCast::INotification* sink) override ; + virtual void Unregister(Exchange::IXCast::INotification* sink) override ; + + virtual PluginHost::IStateControl::state State() const override { return PluginHost::IStateControl::RESUMED; } + virtual uint32_t Request(const command state) override; + virtual void Register(IStateControl::INotification* notification) override {} + virtual void Unregister(IStateControl::INotification* notification) override {} + virtual uint32_t Configure(PluginHost::IShell* service) override; + + virtual uint32_t applicationStateChanged(const string& appName, const string& appstate, const string& appId, const string& error) const override; + virtual uint32_t enableCastService(string friendlyname,bool enableService) const override; + virtual uint32_t getProtocolVersion(string &protocolVersion) const override; + virtual uint32_t registerApplications(Exchange::IXCast::IApplicationInfoIterator* const appLists) override; + + virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, string strPayLoad, string strQuery, string strAddDataUrl) override ; + virtual void onXcastApplicationLaunchRequest(string appName, string parameter) override ; + virtual void onXcastApplicationStopRequest(string appName, string appId) override ; + virtual void onXcastApplicationHideRequest(string appName, string appId) override ; + virtual void onXcastApplicationResumeRequest(string appName, string appId) override ; + virtual void onXcastApplicationStateRequest(string appName, string appId) override ; + + BEGIN_INTERFACE_MAP(XCastImplementation) + INTERFACE_ENTRY(Exchange::IXCast) + INTERFACE_ENTRY(PluginHost::IStateControl) + END_INTERFACE_MAP + + private: + static RtXcastConnector* _rtConnector; + mutable Core::CriticalSection _adminLock; + std::list _notificationClients; + + void dispatchEvent(Event,string callsign, const JsonObject ¶ms); + void Dispatch(Event event,string callsign, const JsonObject params); + + public: + XCastImplementation(); + virtual ~XCastImplementation(); + + friend class Job; + }; +} // namespace Plugin +} // namespace WPEFramework \ No newline at end of file From 59345c74ed58fb03d96d6cfbf64296d30f0b4bc5 Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Fri, 13 Sep 2024 00:15:12 +0000 Subject: [PATCH 2/9] RDK-52203: Convert XCast plugin as OutOfProcess Reason for change: Convert XCast plugin as OutOfProcess. Test Procedure: XCast should be converted as OutOfProcess thunder plugin Risks: HIGH Priority: P0 Signed-off-by: yuvaramachandran_gurusamy --- XCast/RtNotifier.h | 17 +- XCast/RtXcastConnector.cpp | 334 ++++++++++++++++++++- XCast/RtXcastConnector.h | 17 +- XCast/XCast.conf.in | 15 +- XCast/XCast.cpp | 439 ++++++++++++++++++++-------- XCast/XCast.h | 79 +++-- XCast/XCastImplementation.cpp | 529 +++++++++++++++++++++++++++++++--- XCast/XCastImplementation.h | 49 +++- 8 files changed, 1253 insertions(+), 226 deletions(-) diff --git a/XCast/RtNotifier.h b/XCast/RtNotifier.h index 94189a4416..2e182867a8 100644 --- a/XCast/RtNotifier.h +++ b/XCast/RtNotifier.h @@ -27,14 +27,15 @@ class RtNotifier { public: - //virtual void onRtServiceDisconnected(void)=0; - virtual void onXcastApplicationLaunchRequest(string appName, string parameter)=0; - virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, - string strPayLoad, string strQuery, string strAddDataUrl)=0; - virtual void onXcastApplicationStopRequest(string appName, string appID)=0; - virtual void onXcastApplicationHideRequest(string appName, string appID)=0; - virtual void onXcastApplicationResumeRequest(string appName, string appID)=0; - virtual void onXcastApplicationStateRequest(string appName, string appID)=0; + virtual void onGDialServiceDisconnected(void)=0; + virtual void onXcastApplicationLaunchRequest(string appName, string parameter)=0; + virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, + string strPayLoad, string strQuery, string strAddDataUrl)=0; + virtual void onXcastApplicationStopRequest(string appName, string appID)=0; + virtual void onXcastApplicationHideRequest(string appName, string appID)=0; + virtual void onXcastApplicationResumeRequest(string appName, string appID)=0; + virtual void onXcastApplicationStateRequest(string appName, string appID)=0; + virtual void onXcastUpdatePowerStateRequest(string powerState)=0; }; #endif diff --git a/XCast/RtXcastConnector.cpp b/XCast/RtXcastConnector.cpp index cc0c09c777..d9eca904e7 100644 --- a/XCast/RtXcastConnector.cpp +++ b/XCast/RtXcastConnector.cpp @@ -18,12 +18,14 @@ **/ #include "RtXcastConnector.h" -#include "Module.h" #include "UtilsJsonRpc.h" #include "rfcapi.h" using namespace std; using namespace WPEFramework; + +#define COMMON_DEVICE_PROPERTIES_FILE "/etc/device.properties" + #define LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS 5000 //5 seconds #define LOCATE_CAST_SECOND_TIMEOUT_IN_MILLIS 15000 //15 seconds #define LOCATE_CAST_THIRD_TIMEOUT_IN_MILLIS 30000 //30 seconds @@ -33,6 +35,11 @@ using namespace WPEFramework; static gdialService* gdialCastObj = NULL; RtXcastConnector * RtXcastConnector::_instance = nullptr; +std::string m_modelName = ""; +std::string m_manufacturerName = ""; +std::string m_defaultfriendlyName = ""; +std::string m_uuid = ""; +std::string m_defaultAppList = ""; //XDIALCAST EVENT CALLBACK /** @@ -106,24 +113,192 @@ void RtXcastConnector::onApplicationStateRequest(string appName, string appID) } } +void RtXcastConnector::onDisconnect(void) +{ + if ( nullptr != m_observer ) + { + m_observer->onGDialServiceDisconnected(); + } +} + +void RtXcastConnector::updatePowerState(string powerState) +{ + if ( nullptr != m_observer ) + { + m_observer->onXcastUpdatePowerStateRequest(powerState); + } +} + RtXcastConnector::~RtXcastConnector() { _instance = nullptr; m_observer = nullptr; } -bool RtXcastConnector::initialize() +bool RtXcastConnector::initialize(const std::string& gdial_interface_name, bool networkStandbyMode ) { - // @@@ TODO for GDial command line arguments @@@ std::vector gdial_args; - gdialCastObj = gdialService::getInstance(this,gdial_args); - return (nullptr != gdialCastObj) ? true:false; + bool returnValue = false, + isFriendlyNameEnabled = true, + isWolWakeEnableEnabled = true; + + if (gdial_interface_name.empty()) + { + LOGINFO("Interface Name should not be empty"); + return false; + } + + lock_guard lock(m_mutexSync); +#ifdef RFC_ENABLED + RFC_ParamData_t param; + WDMP_STATUS wdmpStatus = WDMP_SUCCESS; + wdmpStatus = getRFCParameter(const_cast("XCastPlugin"), "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.Enable", ¶m); + if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) + { + if( param.type == WDMP_BOOLEAN ) + { + if(strncasecmp(param.value,"true",4) != 0 ) { + LOGINFO("----------XCAST RFC Disabled---------- "); + return true; + } + } + } + wdmpStatus = getRFCParameter(const_cast("XCastPlugin"), "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.FriendlyNameEnable", ¶m); + if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) + { + if( param.type == WDMP_BOOLEAN ) + { + if(strncasecmp(param.value,"true",4) == 0 ) { + isFriendlyNameEnabled = true; + } + else{ + isFriendlyNameEnabled = false; + } + } + } + wdmpStatus = getRFCParameter(const_cast("XCastPlugin"), "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.WolWakeEnable", ¶m); + if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) + { + if( param.type == WDMP_BOOLEAN ) + { + if(strncasecmp(param.value,"true",4) == 0 ) { + isWolWakeEnableEnabled = true; + } + else { + isWolWakeEnableEnabled = false; + } + } + } + wdmpStatus = getRFCParameter(const_cast("XCastPlugin"), "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.AppList", ¶m); + if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) + { + if( param.type == WDMP_STRING ) + { + m_defaultAppList = param.value; + } + } +#endif //RFC_ENABLED + std::string temp_interface = ""; + getGDialInterfaceName(temp_interface); + + if (0 == gdial_interface_name.compare("ETHERNET")) + { + LOGINFO("VIface[%s:%s] uses \"eth0\"",gdial_interface_name.c_str(),temp_interface.c_str()); + temp_interface = "eth0"; + } + else if (0 == gdial_interface_name.compare("WIFI")) + { + LOGINFO("VIface[%s:%s] uses \"wlan0\"",gdial_interface_name.c_str(),temp_interface.c_str()); + temp_interface = "wlan0"; + } + else + { + LOGINFO("Actual IFace[%s]",temp_interface.c_str()); + } + + gdial_args.push_back("-I"); + gdial_args.push_back(temp_interface); + + if (m_uuid.empty()) + { + m_uuid = getReceiverID(); + if (!m_uuid.empty()) + { + gdial_args.push_back("-U"); + gdial_args.push_back(m_uuid); + } + } + + if (m_modelName.empty()) + { + if (!(envGetValue("MODEL_NUM", m_modelName))) + { + LOGERR("MODEL_NUM not configured in device properties file"); + } + else{ + gdial_args.push_back("-M"); + gdial_args.push_back(m_modelName); + } + } + + if (m_manufacturerName.empty()) + { + if (!(envGetValue("MFG_NAME", m_manufacturerName))) + { + LOGERR("MFG_NAME not configured in device properties file"); + } + else{ + gdial_args.push_back("-R"); + gdial_args.push_back(m_manufacturerName); + } + } + + if (m_defaultfriendlyName.empty()) + { + m_defaultfriendlyName = m_modelName + "_" + m_manufacturerName; + gdial_args.push_back("-F"); + gdial_args.push_back(m_defaultfriendlyName); + } + + if (!m_defaultAppList.empty()) + { + gdial_args.push_back("-A"); + gdial_args.push_back(m_defaultAppList); + } + + if (isFriendlyNameEnabled) { + gdial_args.push_back("--feature-friendlyname"); + } + if (isWolWakeEnableEnabled && networkStandbyMode ) { + gdial_args.push_back("--feature-wolwake"); + } + if (nullptr == gdialCastObj) + { + gdialCastObj = gdialService::getInstance(this,gdial_args,"XCastOutofProcess"); + if (nullptr != gdialCastObj) + { + returnValue = true; + } + } + LOGINFO("Exiting[%p] ...",gdialCastObj); + return returnValue; +} + +void RtXcastConnector::deinitialize() +{ + lock_guard lock(m_mutexSync); + if (nullptr != gdialCastObj) + { + lock_guard lock(m_mutexSync); + gdialService::destroyInstance(); + gdialCastObj = nullptr; + } } + void RtXcastConnector::shutdown() { LOGINFO("Shutting down rtRemote connectivity"); - gdialService::destroyInstance(); - gdialCastObj = nullptr; + deinitialize(); if(RtXcastConnector::_instance != nullptr) { delete RtXcastConnector::_instance; @@ -131,11 +306,123 @@ void RtXcastConnector::shutdown() } } +std::string RtXcastConnector::getReceiverID(void) +{ + std::ifstream file("/tmp/gpid.txt"); + std::string line, gpidValue, receiverId = ""; + + if (file.is_open()) + { + while (std::getline(file, line)) + { + std::size_t pos = line.find("deviceId"); + if (pos != std::string::npos) + { + std::size_t colonPos = line.find(":", pos); + if (colonPos != std::string::npos) + { + gpidValue = line.substr(colonPos + 1); + // Remove spaces and unwanted characters + gpidValue.erase(std::remove_if(gpidValue.begin(), gpidValue.end(), ::isspace), gpidValue.end()); + gpidValue.erase(std::remove(gpidValue.begin(), gpidValue.end(), '{'), gpidValue.end()); + gpidValue.erase(std::remove(gpidValue.begin(), gpidValue.end(), '}'), gpidValue.end()); + gpidValue.erase(std::remove(gpidValue.begin(), gpidValue.end(), ','), gpidValue.end()); + gpidValue.erase(std::remove(gpidValue.begin(), gpidValue.end(), '/'), gpidValue.end()); + gpidValue.erase(std::remove(gpidValue.begin(), gpidValue.end(), '"'), gpidValue.end()); + } + break; + } + } + // Convert to lowercase + std::transform(gpidValue.begin(), gpidValue.end(), gpidValue.begin(), ::tolower); + receiverId = gpidValue; + } + + if (receiverId.empty()) + { + std::ifstream authService_deviceId("/opt/www/authService/deviceid.dat"); + std::ifstream whitebox_deviceId("/opt/www/whitebox/wbdevice.dat"); + if (authService_deviceId) + { + std::getline(authService_deviceId, receiverId); + } + else if (whitebox_deviceId) + { + std::getline(whitebox_deviceId, receiverId); + } + } + return receiverId; +} + +void RtXcastConnector::getWiFiInterface(std::string& WiFiInterfaceName) +{ + std::string buildType; + std::ifstream file_stream("/opt/wifi_interface"); + + envGetValue("BUILD_TYPE", buildType); + if (file_stream && "prod" != buildType) + { + std::getline(file_stream, WiFiInterfaceName); + } + else + { + envGetValue("WIFI_INTERFACE", WiFiInterfaceName); + } + if (WiFiInterfaceName.empty()) + { + WiFiInterfaceName = "wlan0"; + } +} + +void RtXcastConnector::getGDialInterfaceName(std::string& interfaceName) +{ + std::ifstream file_stream("/tmp/wifi-on"); + if (file_stream) + { + getWiFiInterface(interfaceName); + } + else + { + envGetValue("MOCA_INTERFACE", interfaceName); + if (interfaceName.empty()) + { + interfaceName = "eth1"; + } + } +} + +bool RtXcastConnector::envGetValue(const char *key, std::string &value) +{ + std::ifstream fs(COMMON_DEVICE_PROPERTIES_FILE, std::ifstream::in); + std::string::size_type delimpos; + std::string line; + bool returnValue = false; + value = ""; + if (!fs.fail()) + { + while (std::getline(fs, line)) + { + if (!line.empty() && ((delimpos = line.find('=')) > 0)) + { + std::string itemKey = line.substr(0, delimpos); + if (itemKey == key) + { + value = line.substr(delimpos + 1, std::string::npos); + returnValue = true; + break; + } + } + } + } + return returnValue; +} + int RtXcastConnector::applicationStateChanged( string app, string state, string id, string error) { int status = 0; LOGINFO("XcastService::ApplicationStateChanged ARGS = %s : %s : %s : %s ", app.c_str(), id.c_str() , state.c_str() , error.c_str()); - if(gdialCastObj != NULL) + lock_guard lock(m_mutexSync); + if (gdialCastObj != NULL) { gdialCastObj->ApplicationStateChanged( app, state, id, error); status = 1; @@ -148,6 +435,7 @@ int RtXcastConnector::applicationStateChanged( string app, string state, string void RtXcastConnector::enableCastService(string friendlyname,bool enableService) { LOGINFO("XcastService::enableCastService ARGS = %s : %d ", friendlyname.c_str(), enableService); + lock_guard lock(m_mutexSync); if(gdialCastObj != NULL) { std::string activation = enableService ? "true": "false"; @@ -161,6 +449,7 @@ void RtXcastConnector::enableCastService(string friendlyname,bool enableService) void RtXcastConnector::updateFriendlyName(string friendlyname) { LOGINFO("XcastService::updateFriendlyName ARGS = %s ", friendlyname.c_str()); + lock_guard lock(m_mutexSync); if(gdialCastObj != NULL) { gdialCastObj->FriendlyNameChanged( friendlyname); @@ -174,6 +463,7 @@ string RtXcastConnector::getProtocolVersion(void) { LOGINFO("XcastService::getProtocolVersion "); std::string strVersion; + lock_guard lock(m_mutexSync); if(gdialCastObj != NULL) { strVersion = gdialCastObj->getProtocolVersion(); @@ -204,7 +494,7 @@ void RtXcastConnector::registerApplications(std::vector& appC appReqList->pushBack(appReq); } - + lock_guard lock(m_mutexSync); if(gdialCastObj != NULL) { gdialCastObj->RegisterApplications(appReqList); @@ -213,15 +503,39 @@ void RtXcastConnector::registerApplications(std::vector& appC else { LOGINFO(" gdialCastObj is NULL "); + if (nullptr != appReqList) + { + for (RegisterAppEntry* appEntry : appReqList->getValues()) + { + delete appEntry; + } + delete appReqList; + } + } +} + +void RtXcastConnector::setNetworkStandbyMode(bool nwStandbymode) +{ + lock_guard lock(m_mutexSync); + if(gdialCastObj != NULL) + { + gdialCastObj->setNetworkStandbyMode(nwStandbymode); + LOGINFO("nwStandbymode:%u",nwStandbymode); + } + else + { + LOGINFO("gdialCastObj is NULL"); } } RtXcastConnector * RtXcastConnector::getInstance() { + LOGINFO("Entering ..."); if(RtXcastConnector::_instance == nullptr) { RtXcastConnector::_instance = new RtXcastConnector(); } + LOGINFO("Exiting ..."); return RtXcastConnector::_instance; } @@ -247,4 +561,4 @@ bool RtXcastConnector::IsAppEnabled(char* strAppName) #endif //RFC_ENABLED return ret; -} \ No newline at end of file +} diff --git a/XCast/RtXcastConnector.h b/XCast/RtXcastConnector.h index 954cc5bb78..33c02be297 100644 --- a/XCast/RtXcastConnector.h +++ b/XCast/RtXcastConnector.h @@ -21,7 +21,9 @@ #include #include #include - +#include +#include "Module.h" +#include "tptimer.h" #include "RtNotifier.h" #include "XCastCommon.h" #include @@ -42,7 +44,8 @@ class RtXcastConnector : public GDialNotifier /** * Initialize rtRemote communication with rtDial server */ - bool initialize(); + bool initialize(const std::string& gdial_interface_name, bool networkStandbyMode ); + void deinitialize(); /** Shutdown rtRemote connectivity */ void shutdown(); @@ -68,6 +71,7 @@ class RtXcastConnector : public GDialNotifier void updateFriendlyName(string friendlyname); void registerApplications (std::vector& appConfigList); string getProtocolVersion(void); + void setNetworkStandbyMode(bool nwStandbymode); /** *Request the single instance of this class */ @@ -79,11 +83,13 @@ class RtXcastConnector : public GDialNotifier virtual void onApplicationHideRequest(string appName, string appID) override; virtual void onApplicationResumeRequest(string appName, string appID) override; virtual void onApplicationStateRequest(string appName, string appID) override; + virtual void onDisconnect(void) override; + virtual void updatePowerState(string powerState) override; /** *Call back function for rtConnection */ - //int connectToRemoteService(); + int isGDialStarted(); void setService(RtNotifier * service){ m_observer = service; @@ -101,10 +107,15 @@ class RtXcastConnector : public GDialNotifier // Member function to handle RT messages. //void processRtMessages(); bool IsAppEnabled(char* strAppName); + void getWiFiInterface(std::string& WiFiInterfaceName); + void getGDialInterfaceName(std::string& interfaceName); + std::string getReceiverID(void); + bool envGetValue(const char *key, std::string &value); // Class level contracts // Singleton instance static RtXcastConnector * _instance; + std::recursive_mutex m_mutexSync; // Thread main function //static void threadRun(RtXcastConnector *rtCtx); }; diff --git a/XCast/XCast.conf.in b/XCast/XCast.conf.in index 060338aad8..d595e41ab0 100644 --- a/XCast/XCast.conf.in +++ b/XCast/XCast.conf.in @@ -2,19 +2,8 @@ precondition = ["Platform"] callsign = "org.rdk.Xcast" autostart = "@PLUGIN_XCAST_AUTOSTART@" startuporder = "@PLUGIN_XCAST_STARTUPORDER@" - configuration = JSON() -configuration.add("endpoint", "@PLUGIN_TEXTTOSPEECH_ENDPOINT@") -configuration.add("secureendpoint", "@PLUGIN_TEXTTOSPEECH_SECURE_ENDPOINT@") -configuration.add("endpoint_type", "@PLUGIN_TEXTTOSPEECH_ENDPOINT_TYPE@") -configuration.add("localendpoint", "@PLUGIN_TEXTTOSPEECH_LOCAL_ENDPOINT@") -configuration.add("speechrate", "@PLUGIN_TEXTTOSPEECH_SPEECHRATE@") -configuration.add("satplugincallsign", "@PLUGIN_TEXTTOSPEECH_SATPLUGINCALLSIGN@") -configuration.add("language", "@PLUGIN_TEXTTOSPEECH_LANGUAGE@") -configuration.add("volume", "@PLUGIN_TEXTTOSPEECH_VOLUME@") -configuration.add("rate", "@PLUGIN_TEXTTOSPEECH_RATE@") - rootobject = JSON() -rootobject.add("mode", "@PLUGIN_TEXTTOSPEECH_MODE@") -configuration.add("root", rootobject) \ No newline at end of file +rootobject.add("mode", "@PLUGIN_XCAST_MODE@") +configuration.add("root", rootobject) diff --git a/XCast/XCast.cpp b/XCast/XCast.cpp index 087f59d293..ee856b0002 100644 --- a/XCast/XCast.cpp +++ b/XCast/XCast.cpp @@ -26,9 +26,8 @@ #endif //RFC_ENABLED #include #include -//#include "RtXcastConnector.h" -using namespace std; +using namespace std; // Events // com.comcast.xcast_1 #define EVT_ON_LAUNCH_REQUEST "onApplicationLaunchRequest" @@ -69,6 +68,7 @@ using namespace std; #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 0 #define API_VERSION_NUMBER_PATCH 17 +#define API_VERSION_NUMBER_TEST 10000 namespace WPEFramework { @@ -88,12 +88,8 @@ namespace { namespace Plugin { -/** - *Register XCast module as wpeframework plugin - **/ SERVICE_REGISTRATION(XCast, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); -//static int locateCastObjectRetryCount = 0; #ifdef XCAST_ENABLED_BY_DEFAULT bool XCast::m_xcastEnable = true; #else @@ -107,28 +103,38 @@ bool XCast::m_standbyBehavior = false; #endif IARM_Bus_PWRMgr_PowerState_t XCast::m_powerState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; - -XCast::XCast() : PluginHost::JSONRPC() - , _notification(this) - , m_apiVersionNumber(API_VERSION_NUMBER_MAJOR) +bool XCast::m_networkStandbyMode = false; +static int m_sleeptime = 1; +static bool m_is_restart_req = false; + +XCast *XCast::m_instance{nullptr}; + +XCast::XCast() + : PluginHost::JSONRPC(), + _skipURL(0), + _connectionId(0), + _service(nullptr), + _xcast(nullptr), + _notification(this), + m_apiVersionNumber(API_VERSION_NUMBER_MAJOR) { - + m_instance = this; } XCast::~XCast() { - LOGINFO("Xcast: Dtor "); - if (nullptr != m_SystemPluginObj) - { - delete m_SystemPluginObj; - m_SystemPluginObj = nullptr; - } - _service = nullptr; + LOGINFO("Xcast: Dtor "); + if (nullptr != m_SystemPluginObj) + { + delete m_SystemPluginObj; + m_SystemPluginObj = nullptr; + } + _service = nullptr; } void XCast::RegisterAll() { - LOGINFO("XcastService::Register methods and create onLocateCastTimer "); + LOGINFO("XcastService::Register methods"); Register(METHOD_GET_API_VERSION_NUMBER, &XCast::getApiVersionNumber, this); Register(METHOD_ON_APPLICATION_STATE_CHANGED , &XCast::applicationStateChanged, this); Register(METHOD_SET_ENABLED, &XCast::setEnabled, this); @@ -140,24 +146,31 @@ void XCast::RegisterAll() Register(METHOD_REG_APPLICATIONS, &XCast::registerApplications, this); Register(METHOD_UNREG_APPLICATIONS, &XCast::unregisterApplications, this); Register(METHOD_GET_PROTOCOLVERSION, &XCast::getProtocolVersion, this); - - //m_locateCastTimer.connect( bind( &XCast::onLocateCastTimer, this )); } void XCast::InitializeIARM() { if (Utils::IARM::init()) { + IARM_Bus_PWRMgr_GetPowerState_Param_t getPowerStateParam; + IARM_Bus_PWRMgr_NetworkStandbyMode_Param_t networkStandbyModeParam; IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_MODECHANGED, powerModeChange) ); - IARM_Bus_PWRMgr_GetPowerState_Param_t param; - res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_GetPowerState, - (void *)¶m, sizeof(param)); + + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_MODECHANGED, powerModeChange)); + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_EVENT_NETWORK_STANDBYMODECHANGED, networkStandbyModeChange)); + + res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_GetPowerState,(void *)&getPowerStateParam, sizeof(getPowerStateParam)); if (res == IARM_RESULT_SUCCESS) { - m_powerState = param.curState; + m_powerState = getPowerStateParam.curState; + } + LOGINFO("m_powerState:%d ",m_powerState); + + res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME,IARM_BUS_PWRMGR_API_GetNetworkStandbyMode, (void *)&networkStandbyModeParam,sizeof(networkStandbyModeParam)); + if(res == IARM_RESULT_SUCCESS) { + m_networkStandbyMode = networkStandbyModeParam.bStandbyMode; } - LOGINFO("XcastService::m_powerState:%d ",m_powerState); + LOGINFO("m_networkStandbyMode:%u ",m_networkStandbyMode); } } @@ -176,8 +189,45 @@ void XCast::DeinitializeIARM() Unregister(METHOD_SET_STANDBY_BEHAVIOR); Unregister(METHOD_GET_FRIENDLYNAME); Unregister(METHOD_SET_FRIENDLYNAME); +} +bool XCast::setPowerState(std::string powerState) +{ + IARM_Bus_PWRMgr_PowerState_t cur_powerState = m_powerState, + new_powerState = IARM_BUS_PWRMGR_POWERSTATE_OFF; + bool ret = true; + if ("ON" == powerState) + { + new_powerState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + else if ("STANDBY" == powerState) + { + new_powerState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + } + else if ("TOGGLE" == powerState) + { + new_powerState = ( IARM_BUS_PWRMGR_POWERSTATE_ON == cur_powerState ) ? IARM_BUS_PWRMGR_POWERSTATE_STANDBY : IARM_BUS_PWRMGR_POWERSTATE_ON; + } + + if ((IARM_BUS_PWRMGR_POWERSTATE_OFF != new_powerState) && (cur_powerState != new_powerState)) + { + IARM_Bus_PWRMgr_SetPowerState_Param_t param; + param.newState = new_powerState; + IARM_Result_t res = IARM_Bus_Call(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_API_SetPowerState,(void *)¶m, sizeof(param)); + if(res != IARM_RESULT_SUCCESS) + { + ret = false; + LOGINFO("Failed to change power state [%d] -> [%d] ret[%x]",cur_powerState,new_powerState,res); + } + else + { + LOGINFO("changing power state [%d] -> [%d] success",cur_powerState,new_powerState); + sleep(m_sleeptime); + } + } + return ret; } + void XCast::powerModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len) { if (strcmp(owner, IARM_BUS_PWRMGR_NAME) == 0) { @@ -193,20 +243,72 @@ void XCast::powerModeChange(const char *owner, IARM_EventId_t eventId, void *dat } } +void XCast::networkStandbyModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len) +{ + if ((strcmp(owner, IARM_BUS_PWRMGR_NAME) == 0) && ( eventId == IARM_BUS_PWRMGR_EVENT_NETWORK_STANDBYMODECHANGED )) { + IARM_Bus_PWRMgr_EventData_t *param = (IARM_Bus_PWRMgr_EventData_t *)data; + m_networkStandbyMode = param->data.bNetworkStandbyMode; + LOGWARN("creating worker thread for threadNetworkStandbyModeChangeEvent Mode :%u",m_networkStandbyMode); + std::thread networkStandbyModeChangeThread = std::thread(networkStandbyModeChangeEvent); + networkStandbyModeChangeThread.detach(); + } +} + +void XCast::threadPowerModeChangeEvent(void) +{ + LOGINFO(" threadPowerModeChangeEvent m_standbyBehavior:%d , m_powerState:%d ",m_standbyBehavior,m_powerState); + if(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON) + { + m_sleeptime = 1; + if (m_is_restart_req) + { + m_is_restart_req = false; + } + } + else if(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP ) + { + m_sleeptime = 3; + m_is_restart_req = true; //After DEEPSLEEP, restart xdial again for next transition. + } + + if(m_standbyBehavior == false) + { + if(m_xcastEnable && ( m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) + m_instance->_xcast->enableCastService(m_friendlyName,true); + else + m_instance->_xcast->enableCastService(m_friendlyName,false); + } +} + +void XCast::networkStandbyModeChangeEvent(void) +{ + LOGINFO("m_networkStandbyMode:%u ",m_networkStandbyMode); + if ( m_instance->_xcast) + { + m_instance->_xcast->setNetworkStandbyMode(m_networkStandbyMode); + } +} + const string XCast::Initialize(PluginHost::IShell *service) { - ASSERT(_service == nullptr); + ASSERT (_service == nullptr); + ASSERT (service != nullptr); - _connectionId = 0; _service = service; - _skipURL = static_cast(_service->WebPrefix().length()); + _skipURL = static_cast(service->WebPrefix().length()); - _service->Register(&_notification); + LOGINFO("##### API VER[%d : %d : %d : %d] #####", API_VERSION_NUMBER_MAJOR,API_VERSION_NUMBER_MINOR,API_VERSION_NUMBER_PATCH,API_VERSION_NUMBER_TEST); - _xcast = _service->Root(_connectionId, 5000, _T("XCastImplementation")); + _service->Register(&_notification); - std::string message; - if(_xcast != nullptr) { + string result; + _xcast = _service->Root(_connectionId, 2000, _T("XCastImplementation")); + if (_xcast == nullptr) + { + result = _T("Couldn't create XCast instance"); + } + else + { #ifndef UNIT_TESTING ASSERT(_connectionId != 0); #endif @@ -223,29 +325,25 @@ const string XCast::Initialize(PluginHost::IShell *service) } stateControl->Release(); } - } - if(_xcast != nullptr) { - _xcast->Register(&_notification); - RegisterAll(); - InitializeIARM(); + if(_xcast != nullptr) { + InitializeIARM(); - getSystemPlugin(); - // subscribe for event - m_SystemPluginObj->Subscribe(1000, "onFriendlyNameChanged", &XCast::onFriendlyNameUpdateHandler, this); - if (Core::ERROR_NONE == updateSystemFriendlyName()) - { - LOGINFO("XCast::Initialize m_friendlyName: %s\n ",m_friendlyName.c_str()); + _xcast->Register(&_notification); + _xcast->Initialize(m_networkStandbyMode); + + RegisterAll(); + + getSystemPlugin(); + // subscribe for event + m_SystemPluginObj->Subscribe(1000, "onFriendlyNameChanged", &XCast::onFriendlyNameUpdateHandler, this); + if (Core::ERROR_NONE == updateSystemFriendlyName()) + { + LOGINFO("XCast::Initialize m_friendlyName: %s\n ",m_friendlyName.c_str()); + } } } - else - { - message = _T("XCast could not be instantiated."); - _service->Unregister(&_notification); - _service = nullptr; - } - - return message; + return (result); } void XCast::Deinitialize(PluginHost::IShell* service) @@ -276,7 +374,6 @@ void XCast::Deinitialize(PluginHost::IShell* service) } } } - _xcast = nullptr; _service = nullptr; } @@ -285,7 +382,6 @@ void XCast::Deactivated(RPC::IRemoteConnection* connection) { if (connection->Id() == _connectionId) { ASSERT(_service != nullptr); - LOGINFO("XCast::Deactivated - %p", this); Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); } } @@ -511,6 +607,29 @@ int XCast::updateSystemFriendlyName() return ret; } +void XCast::onFriendlyNameUpdateHandler(const JsonObject& parameters) +{ + string message; + string value; + parameters.ToString(message); + LOGINFO("[Friendly Name Event], %s : %s", __FUNCTION__,message.c_str()); + + if (parameters.HasLabel("friendlyName")) { + value = parameters["friendlyName"].String(); + if(_xcast) + { + m_friendlyName = value; + LOGINFO("onFriendlyNameUpdateHandler :%s",m_friendlyName.c_str()); + if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { + _xcast->enableCastService(m_friendlyName,true); + } + else { + _xcast->enableCastService(m_friendlyName,false); + } + } + } +} + uint32_t XCast::getProtocolVersion(const JsonObject& parameters, JsonObject& response) { string protocolVersion; @@ -869,65 +988,6 @@ uint32_t XCast::unregisterApplications(const JsonObject& parameters, JsonObject& returnResponse(returnStatus); } -#if 0 -//Timer Functions -void XCast::onLocateCastTimer() -{ - int status = _xcast->connectToRemoteService(); - if(status != 0) - { - if(locateCastObjectRetryCount < 4) - { - locateCastObjectRetryCount++; - } - if(locateCastObjectRetryCount == 1) - { - LOGINFO("Retry after 5 sec..."); - m_locateCastTimer.setInterval(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); - } - if(locateCastObjectRetryCount == 2) - { - LOGINFO("Retry after 15 sec..."); - m_locateCastTimer.setInterval(LOCATE_CAST_SECOND_TIMEOUT_IN_MILLIS); - } - if(locateCastObjectRetryCount == 3) - { - LOGINFO("Retry after 30 sec..."); - m_locateCastTimer.setInterval(LOCATE_CAST_THIRD_TIMEOUT_IN_MILLIS); - } - if(locateCastObjectRetryCount == 4) - { - LOGINFO("Retry after 60 sec..."); - m_locateCastTimer.setInterval(LOCATE_CAST_FINAL_TIMEOUT_IN_MILLIS); - } - return ; - }// err != RT_OK - locateCastObjectRetryCount = 0; - m_locateCastTimer.stop(); - - if (NULL != _xcast) - { - std::vector appConfigList; - {lock_guard lck(m_appConfigMutex); - appConfigList = m_appConfigCache; - } - dumpDynamicAppConfigCache(string("m_appConfigCache"), appConfigList); - LOGINFO("XCast::onLocateCastTimer : calling registerApplications"); - registerApplicationsInternal(appConfigList); - } - else { - LOGINFO("XCast::onLocateCastTimer :_xcast: %p", _xcast); - } - - bool enabledStatus = false; - if (m_xcastEnable && ( (m_standbyBehavior == true) || ((m_standbyBehavior == false)&&(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_ON)) ) ) { - enabledStatus = true; - } - _xcast->enableCastService(m_friendlyName,enabledStatus); - LOGINFO("XCast::onLocateCastTimer : Timer still active ? %d ",m_locateCastTimer.isActive()); -} -#endif - uint32_t XCast::registerApplicationsInternal(std::vector appConfigEntries) { std::list appInfoList; @@ -959,15 +1019,8 @@ uint32_t XCast::registerApplicationsInternal(std::vector appC return rc; } -#if 0 -void XCast::onRtServiceDisconnected() +void XCast::getUrlFromAppLaunchParams (const char *app_name, const char *payload, const char *query_string, const char *additional_data_url, char *url) { - LOGINFO("RT communication failure. Reconnecting.. "); - m_locateCastTimer.start(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); -} -#endif - -void XCast::getUrlFromAppLaunchParams (const char *app_name, const char *payload, const char *query_string, const char *additional_data_url, char *url) { LOGINFO("getUrlFromAppLaunchParams : Application launch request: appName: %s query: [%s], payload: [%s], additionalDataUrl [%s]\n", app_name, query_string, payload, additional_data_url); @@ -1053,5 +1106,143 @@ void XCast::getUrlFromAppLaunchParams (const char *app_name, const char *payload LOGINFO(" url is [%s]\r\n", url); } } -} // namespace Plugin -} // namespace WPEFramework \ No newline at end of file + +void XCast::event_onApplicationLaunchRequestWithLaunchParam(string appName,string strPayLoad, string strQuery, string strAddDataUrl) +{ + //TODO + LOGINFO ("XcastService::event_onApplicationLaunchRequestWithLaunchParam "); + if(strAddDataUrl.size() > DIAL_MAX_ADDITIONALURL){ + LOGWARN ("%s - current additional data size (%d) exceeds maximum allowed size (%d) ", __PRETTY_FUNCTION__, (int)strAddDataUrl.size(), DIAL_MAX_ADDITIONALURL); + return; + } + if(strPayLoad.size() > DIAL_MAX_PAYLOAD) { + LOGWARN ("%s - current payload size (%d) exceeds maximum allowed size (%d) ", __PRETTY_FUNCTION__, (int)strPayLoad.size(), DIAL_MAX_PAYLOAD); + return; + } + JsonObject params; + JsonObject urlParam; + char url[DIAL_MAX_PAYLOAD+DIAL_MAX_ADDITIONALURL+100] = {0,}; + + if(_xcast) + { + DynamicAppConfig appConfig{}; + getEntryFromAppLaunchParamList (appName.c_str(), appConfig); + + /*Replacing with App requested payload and query*/ + if (('\0' != appConfig.query[0]) && ('\0' != appConfig.payload[0])) { + getUrlFromAppLaunchParams (appName.c_str(), + appConfig.payload, + appConfig.query, + strAddDataUrl.c_str(), url); + } + else if(('\0' != appConfig.payload[0])){ + getUrlFromAppLaunchParams (appName.c_str(), + appConfig.payload, + strQuery.c_str(), + strAddDataUrl.c_str(), url); + } + else if(('\0' != appConfig.query[0])) { + getUrlFromAppLaunchParams (appName.c_str(), + strPayLoad.c_str(), + appConfig.query, + strAddDataUrl.c_str(), url); + } + else { + getUrlFromAppLaunchParams (appName.c_str(), + strPayLoad.c_str(), + strQuery.c_str(), + strAddDataUrl.c_str(), url); + } + + string strUrl = std::string (url); + if (appName == "Netflix") { + appName.assign("NetflixApp"); + urlParam["pluginUrl"]=strUrl; + } + else { + urlParam["url"]=strUrl; + } + + params["applicationName"]= appName; + params["parameters"]= urlParam; + + sendNotify(EVT_ON_LAUNCH_REQUEST, params); + } +} + +void XCast::event_onApplicationLaunchRequest(string appName, string parameter) +{ + //TODO + LOGINFO ("XcastService::event_onApplicationLaunchRequest "); + JsonObject params; + JsonObject urlParam; + if (appName == "NetflixApp") + urlParam["pluginUrl"]=parameter; + else + urlParam["url"]=parameter; + + params["applicationName"]= appName; + params["parameters"]= urlParam; + + sendNotify(EVT_ON_LAUNCH_REQUEST, params); +} + +void XCast::event_onApplicationStopRequest(string appName, string appID) +{ + //TODO + LOGINFO("XcastService::event_onApplicationStopRequest "); + + JsonObject params; + params["applicationName"] = appName; + params["applicationId"]= appID; + + sendNotify(EVT_ON_STOP_REQUEST, params); +} + +void XCast::event_onApplicationHideRequest(string appName, string appID) +{ + LOGINFO("XcastService::event_onApplicationHideRequest : "); + if (appName.compare("Netflix") == 0 ) + appName = "NetflixApp"; + + + JsonObject params; + params["applicationName"] = appName; + params["applicationId"]= appID; + + sendNotify(EVT_ON_HIDE_REQUEST, params); +} + +void XCast::event_onApplicationStateRequest(string appName, string appID) +{ + LOGINFO("XcastService::event_onApplicationStateRequest: "); + if (appName.compare("Netflix") == 0 ) + appName = "NetflixApp"; + + JsonObject params; + params["applicationName"] = appName; + params["applicationId"]= appID; + + sendNotify(EVT_ON_STATE_REQUEST , params); + +} + +void XCast::event_onApplicationResumeRequest(string appName, string appID) +{ + LOGINFO("XcastService::event_onApplicationResumeRequest "); + if (appName.compare("Netflix") == 0 ) + appName = "NetflixApp"; + + JsonObject params; + params["applicationName"] = appName; + params["applicationId"]= appID; + sendNotify(EVT_ON_RESUME_REQUEST, params); +} + +void XCast::event_onUpdatePowerStateRequest(string powerState) +{ + LOGINFO("PowerState[%s]",powerState.c_str()); + setPowerState(powerState); +} +} // namespace Plugin +} // namespace WPEFramework diff --git a/XCast/XCast.h b/XCast/XCast.h index 854a6221f8..855cda72b6 100644 --- a/XCast/XCast.h +++ b/XCast/XCast.h @@ -35,7 +35,6 @@ #include #include "tracing/Logging.h" #include "tptimer.h" -#include "RtNotifier.h" #include "libIBus.h" #include "libIBusDaemon.h" #include "pwrMgr.h" @@ -47,6 +46,26 @@ namespace WPEFramework { namespace Plugin { class XCast: public PluginHost::IPlugin, public PluginHost::JSONRPC { + public: + BEGIN_INTERFACE_MAP(XCast) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + INTERFACE_AGGREGATE(Exchange::IXCast, _xcast) + END_INTERFACE_MAP + + XCast(); + virtual ~XCast(); + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + virtual string Information() const override { return {}; } + + void event_onApplicationLaunchRequestWithLaunchParam(string appName,string strPayLoad, string strQuery, string strAddDataUrl); + void event_onApplicationLaunchRequest(string appName, string parameter); + void event_onApplicationStopRequest(string appName, string appID); + void event_onApplicationHideRequest(string appName, string appID); + void event_onApplicationStateRequest(string appName, string appID); + void event_onApplicationResumeRequest(string appName, string appID); + void event_onUpdatePowerStateRequest(string powerState); public: class Notification : public RPC::IRemoteConnection::INotification, public Exchange::IXCast::INotification { @@ -65,12 +84,35 @@ namespace Plugin { } public: - virtual void onApplicationLaunchRequestWithLaunchParam(const string& appName, const string& strPayLoad, const string& strQuery, const string& strAddDataUrl) override; - virtual void onApplicationLaunchRequest(const string& appName, const string& parameter) override; - virtual void onApplicationStopRequest(const string& appName, const string& appID) override; - virtual void onApplicationHideRequest(const string& appName, const string& appID) override; - virtual void onApplicationStateRequest(const string& appName, const string& appID) override; - virtual void onApplicationResumeRequest(const string& appName, const string& appID) override; + virtual void onApplicationLaunchRequestWithLaunchParam(const string& appName, const string& strPayLoad, const string& strQuery, const string& strAddDataUrl) override + { + _parent.event_onApplicationLaunchRequestWithLaunchParam(appName, strPayLoad, strQuery, strAddDataUrl); + } + virtual void onApplicationLaunchRequest(const string& appName, const string& parameter) override + { + _parent.event_onApplicationLaunchRequest(appName, parameter); + } + virtual void onApplicationStopRequest(const string& appName, const string& appID) override + { + _parent.event_onApplicationStopRequest(appName, appID); + } + virtual void onApplicationHideRequest(const string& appName, const string& appID) override + { + _parent.event_onApplicationHideRequest(appName, appID); + } + virtual void onApplicationStateRequest(const string& appName, const string& appID) override + { + _parent.event_onApplicationStateRequest(appName, appID); + } + virtual void onApplicationResumeRequest(const string& appName, const string& appID) override + { + _parent.event_onApplicationResumeRequest(appName, appID); + } + virtual void onUpdatePowerStateRequest(const string& powerState) override + { + _parent.event_onUpdatePowerStateRequest(powerState); + } + virtual void Activated(RPC::IRemoteConnection* /* connection */) final { LOGINFO("XCast::Notification::Activated - %p", this); @@ -91,19 +133,6 @@ namespace Plugin { XCast& _parent; }; - BEGIN_INTERFACE_MAP(XCast) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - INTERFACE_AGGREGATE(Exchange::IXCast, _xcast) - END_INTERFACE_MAP - - public: - XCast(); - virtual ~XCast(); - virtual const string Initialize(PluginHost::IShell* service) override; - virtual void Deinitialize(PluginHost::IShell* service) override; - virtual string Information() const override { return {}; } - private: // We do not allow this plugin to be copied !! XCast(const XCast&) = delete; @@ -131,8 +160,9 @@ namespace Plugin { */ static bool m_xcastEnable; static IARM_Bus_PWRMgr_PowerState_t m_powerState; + static bool m_networkStandbyMode; bool m_isDynamicRegistrationsRequired; - mutex m_appConfigMutex; + std::mutex m_appConfigMutex; WPEFramework::JSONRPC::LinkType * m_SystemPluginObj = NULL; std::vector m_appConfigCache; static string m_friendlyName; @@ -147,18 +177,22 @@ namespace Plugin { bool getEntryFromAppLaunchParamList (const char* appName, DynamicAppConfig& retAppConfig); void dumpDynamicAppConfigCache(string strListName, std::vector appConfigList); bool deleteFromDynamicAppCache(JsonArray applications); - bool deleteFromDynamicAppCache(vector& appsToDelete); + bool deleteFromDynamicAppCache(std::vector& appsToDelete); void updateDynamicAppCache(JsonArray applications); void getSystemPlugin(); int updateSystemFriendlyName(); void onFriendlyNameUpdateHandler(const JsonObject& parameters); + bool setPowerState(std::string powerState); /** * Check whether the xdial service is allowed in this device. */ static void powerModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len); static void threadPowerModeChangeEvent(void); + static void networkStandbyModeChange(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + static void networkStandbyModeChangeEvent(void); private: + static XCast *m_instance; uint8_t _skipURL{}; uint32_t _connectionId{}; PluginHost::IShell* _service{}; @@ -167,6 +201,5 @@ namespace Plugin { uint32_t m_apiVersionNumber; friend class Notification; }; - } // namespace Plugin } // namespace WPEFramework diff --git a/XCast/XCastImplementation.cpp b/XCast/XCastImplementation.cpp index 144ed0b121..47cd24b083 100644 --- a/XCast/XCastImplementation.cpp +++ b/XCast/XCastImplementation.cpp @@ -16,44 +16,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "XCastImplementation.h" #include #include "UtilsJsonRpc.h" +#include "rfcapi.h" +#include +#include + +#define SERVER_DETAILS "127.0.0.1:9998" +#define NETWORK_CALLSIGN "org.rdk.Network" +#define NETWORK_CALLSIGN_VER NETWORK_CALLSIGN ".1" +#define THUNDER_RPC_TIMEOUT 2000 +#define MAX_SECURITY_TOKEN_SIZE 1024 -#define XCAST_IMPL_MAJOR_VERSION 1 -#define XCAST_IMPL_MINOR_VERSION 0 +#define API_VERSION_NUMBER_MAJOR 1 +#define API_VERSION_NUMBER_MINOR 0 +#define API_VERSION_NUMBER_PATCH 2 +#define API_VERSION_NUMBER_TEST 100 + +#define LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS 5000 //5 seconds +#define LOCATE_CAST_SECOND_TIMEOUT_IN_MILLIS 10000 //10 seconds +#define LOCATE_CAST_THIRD_TIMEOUT_IN_MILLIS 30000 //30 seconds +#define LOCATE_CAST_FINAL_TIMEOUT_IN_MILLIS 60000 //60 seconds namespace WPEFramework { namespace Plugin { - SERVICE_REGISTRATION(XCastImplementation, XCAST_IMPL_MAJOR_VERSION, XCAST_IMPL_MINOR_VERSION); + SERVICE_REGISTRATION(XCastImplementation, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + XCastImplementation *XCastImplementation::_instance = nullptr; RtXcastConnector* XCastImplementation::_rtConnector = nullptr; + static std::vector appConfigListCache; + static std::mutex m_appConfigMutex; + static bool xcastEnableCache = false; + static string friendlyNameCache = ""; + static string m_activeInterfaceName = ""; XCastImplementation::XCastImplementation() : _adminLock() { - if(nullptr == _rtConnector) - { - _rtConnector = RtXcastConnector::getInstance(); - if(nullptr != _rtConnector) - { - _rtConnector->setService(this); - if( _rtConnector->initialize()) - { - //We give few seconds delay before the timer is fired. - //m_locateCastTimer.start(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); - } - } - } + LOGINFO("##### API VER[%d : %d : %d : %d] #####", API_VERSION_NUMBER_MAJOR,API_VERSION_NUMBER_MINOR,API_VERSION_NUMBER_PATCH,API_VERSION_NUMBER_TEST); + m_locateCastTimer.connect( bind( &XCastImplementation::onLocateCastTimer, this )); } XCastImplementation::~XCastImplementation() { - if(_rtConnector) { - delete _rtConnector; - _rtConnector = nullptr; - } + Deinitialize(); } void XCastImplementation::Register(Exchange::IXCast::INotification* sink) @@ -84,19 +92,49 @@ namespace Plugin { _adminLock.Unlock(); } - uint32_t XCastImplementation::Request(PluginHost::IStateControl::command command) + uint32_t XCastImplementation::Initialize(bool networkStandbyMode) { - // Not implemented - return Core::ERROR_GENERAL; + if(nullptr == _rtConnector) + { + m_networkStandbyMode = networkStandbyMode; + _rtConnector = RtXcastConnector::getInstance(); + if(nullptr != _rtConnector) + { + _rtConnector->setService(this); + if( false == connectToGDialService()) + { + startTimer(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); + } + } + } + return Core::ERROR_NONE; } - uint32_t XCastImplementation::Configure(PluginHost::IShell* service) + void XCastImplementation::Deinitialize(void) { + if(nullptr != _rtConnector) + { + stopTimer(); + _rtConnector->shutdown(); + _rtConnector = nullptr; + } + } + + uint32_t XCastImplementation::enableCastService(string friendlyname,bool enableService) const + { + LOGINFO("XcastService::enableCastService: ARGS = %s : %d", friendlyname.c_str(), enableService); + if (nullptr != _rtConnector) + { + _rtConnector->enableCastService(friendlyname,enableService); + } + xcastEnableCache = enableService; + friendlyNameCache = friendlyname; return Core::ERROR_NONE; } uint32_t XCastImplementation::applicationStateChanged(const string& appName, const string& appstate, const string& appId, const string& error) const { + LOGINFO("ApplicationStateChanged ARGS = %s : %s : %s : %s ", appName.c_str(), appId.c_str() , appstate.c_str() , error.c_str()); uint32_t status = Core::ERROR_GENERAL; if(!appName.empty() && !appstate.empty() && (nullptr != _rtConnector)) { @@ -107,17 +145,7 @@ namespace Plugin { return status; } - uint32_t XCastImplementation::enableCastService(string friendlyname,bool enableService) const - { - LOGINFO("XcastService::enableCastService"); - if (nullptr != _rtConnector) - { - _rtConnector->enableCastService(friendlyname,enableService); - } - return Core::ERROR_NONE; - } - - uint32_t XCastImplementation::getProtocolVersion(string &protocolVersion) const + uint32_t XCastImplementation::getProtocolVersion(std::string &protocolVersion) const { LOGINFO("XcastService::getProtocolVersion"); if (nullptr != _rtConnector) @@ -127,7 +155,7 @@ namespace Plugin { return Core::ERROR_NONE; } - uint32_t XCastImplementation::registerApplications(IApplicationInfoIterator* const appLists) + uint32_t XCastImplementation::registerApplications(Exchange::IXCast::IApplicationInfoIterator* const appLists) { LOGINFO("XcastService::registerApplications"); std::vector appConfigListTemp; @@ -159,11 +187,32 @@ namespace Plugin { } } _rtConnector->registerApplications(appConfigListTemp); + { + lock_guard lck(m_appConfigMutex); + for (DynamicAppConfig* pDynamicAppConfigOld : appConfigListCache) + { + free (pDynamicAppConfigOld); + pDynamicAppConfigOld = NULL; + } + appConfigListCache.clear(); + appConfigListCache = appConfigListTemp; + } status = Core::ERROR_NONE; } return status; } + uint32_t XCastImplementation::setNetworkStandbyMode(bool nwStandbymode) + { + LOGINFO("nwStandbymode: %d", nwStandbymode); + if (nullptr != _rtConnector) + { + _rtConnector->setNetworkStandbyMode(nwStandbymode); + m_networkStandbyMode = nwStandbymode; + } + return Core::ERROR_NONE; + } + void XCastImplementation::dispatchEvent(Event event, string callsign, const JsonObject ¶ms) { Core::IWorkerPool::Instance().Submit(Job::Create(this, event, callsign, params)); @@ -221,6 +270,12 @@ namespace Plugin { (*index)->onApplicationResumeRequest(appName,appId); } break; + case UPDATE_POWERSTATE: + { + string powerState = params["powerstate"].String(); + (*index)->onUpdatePowerStateRequest(powerState); + } + break; default: break; } ++index; @@ -284,5 +339,401 @@ namespace Plugin { params["appId"] = appId.c_str(); dispatchEvent(STATE_REQUEST, "", params); } -} // namespace Plugin -} // namespace WPEFramework + + void XCastImplementation::onXcastUpdatePowerStateRequest(string powerState) + { + LOGINFO("Notify updatePowerState, state: %s",powerState.c_str()); + JsonObject params; + params["powerstate"] = powerState.c_str(); + dispatchEvent(UPDATE_POWERSTATE, "", params); + } + + void XCastImplementation::onGDialServiceDisconnected(void) + { + startTimer(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); + } + + bool XCastImplementation::connectToGDialService(void) + { + std::string interface,ipaddress; + bool status = false; + + getDefaultNameAndIPAddress(interface,ipaddress); + if (!interface.empty()) + { + status = _rtConnector->initialize(interface,m_networkStandbyMode); + if( true == status) + { + m_activeInterfaceName = interface; + } + } + return status; + } + + std::string XCastImplementation::getSecurityToken() + { + std::string token = "token="; + int tokenLength = 0; + unsigned char buffer[MAX_SECURITY_TOKEN_SIZE] = {0}; + static std::string endpoint; + + if(endpoint.empty()) { + Core::SystemInfo::GetEnvironment(_T("THUNDER_ACCESS"), endpoint); + LOGINFO("Thunder RPC Endpoint read from env - %s", endpoint.c_str()); + } + + if(endpoint.empty()) { + Core::File file("/etc/WPEFramework/config.json"); + if(file.Open(true)) { + JsonObject config; + if(config.IElement::FromFile(file)) { + Core::JSON::String port = config.Get("port"); + Core::JSON::String binding = config.Get("binding"); + if(!binding.Value().empty() && !port.Value().empty()) + endpoint = binding.Value() + ":" + port.Value(); + } + file.Close(); + } + + if(endpoint.empty()) + endpoint = _T("127.0.0.1:9998"); + + LOGINFO("Thunder RPC Endpoint read from config file - %s", endpoint.c_str()); + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), endpoint); + } + + string payload = "http://localhost"; + if(payload.empty()) { + tokenLength = GetSecurityToken(sizeof(buffer), buffer); + } else { + int buffLength = std::min(sizeof(buffer), payload.length()); + ::memcpy(buffer, payload.c_str(), buffLength); + tokenLength = GetToken(sizeof(buffer), buffLength, buffer); + } + + if(tokenLength > 0) { + token.append((char*)buffer); + } else { + token.clear(); + } + + LOGINFO("Thunder token - %s", token.empty() ? "" : token.c_str()); + return token; + } + + // Thunder plugins communication + void XCastImplementation::getThunderPlugins() + { + string token = getSecurityToken(); + + m_ControllerObj = new WPEFramework::JSONRPC::LinkType("", "", false, token); + + if (nullptr != m_ControllerObj) + { + auto ev_ret = m_ControllerObj->Subscribe(1000, _T("statechange"),&XCastImplementation::eventHandler_pluginState,this); + if (ev_ret == Core::ERROR_NONE) + { + LOGINFO("Controller - statechange event subscribed"); + } + else + { + LOGERR("Controller - statechange event failed to subscribe : %d",ev_ret); + } + + if (!isPluginActivated(NETWORK_CALLSIGN_VER)) + { + activatePlugin(NETWORK_CALLSIGN_VER); + _networkPluginState = PLUGIN_DEACTIVATED; + } + else + { + _networkPluginState = PLUGIN_ACTIVATED; + } + } + else + { + LOGERR("Unable to get Controller obj"); + } + + if (nullptr == m_NetworkPluginObj) + { + std::string callsign = NETWORK_CALLSIGN_VER; + if(token.empty()) + { + m_NetworkPluginObj = new WPEFramework::JSONRPC::LinkType(_T(NETWORK_CALLSIGN_VER),""); + } + else + { + m_NetworkPluginObj = new WPEFramework::JSONRPC::LinkType(_T(NETWORK_CALLSIGN_VER),"", false, token); + } + + if (nullptr == m_NetworkPluginObj) + { + LOGERR("JSONRPC: %s: initialization failed", NETWORK_CALLSIGN_VER); + } + else + { + LOGINFO("JSONRPC: %s: initialization ok", NETWORK_CALLSIGN_VER); + // Network monitor so we can know ip address of host inside container + if(m_NetworkPluginObj) + { + auto ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onDefaultInterfaceChanged"), &XCastImplementation::eventHandler_onDefaultInterfaceChanged,this); + if ( Core::ERROR_NONE == ev_ret ) + { + LOGINFO("Network - IP address status changed event : subscribed"); + } + else + { + LOGERR("Network - IP address status changed event : failed to subscribe : %d", ev_ret); + } + + ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onIPAddressStatusChanged"), &XCastImplementation::eventHandler_ipAddressChanged,this); + if ( Core::ERROR_NONE == ev_ret ) + { + LOGINFO("Network - IP address status changed event : subscribed"); + } + else + { + LOGERR("Network - IP address status changed event : failed to subscribe : %d", ev_ret); + } + } + } + } + LOGINFO("Exiting..!!!"); + } + + void XCastImplementation::eventHandler_pluginState(const JsonObject& parameters) + { + LOGINFO("Plugin state changed"); + + if( 0 == strncmp(parameters["callsign"].String().c_str(), NETWORK_CALLSIGN_VER, parameters["callsign"].String().length())) + { + if ( 0 == strncmp( parameters["state"].String().c_str(),"Deactivated", parameters["state"].String().length())) + { + LOGINFO("%s plugin got deactivated with reason : %s",parameters["callsign"].String().c_str(), parameters["reason"].String().c_str()); + _instance->activatePlugin(parameters["callsign"].String()); + } + } + } + + int XCastImplementation::activatePlugin(string callsign) + { + JsonObject result, params; + params["callsign"] = callsign; + int rpcRet = Core::ERROR_GENERAL; + if (nullptr != m_ControllerObj) + { + rpcRet = m_ControllerObj->Invoke("activate", params, result); + if(Core::ERROR_NONE == rpcRet) + { + LOGINFO("Activated %s plugin", callsign.c_str()); + } + else + { + LOGERR("Could not activate %s plugin. Failed with %d", callsign.c_str(), rpcRet); + } + } + else + { + LOGERR("Controller not active"); + } + return rpcRet; + } + + int XCastImplementation::deactivatePlugin(string callsign) + { + JsonObject result, params; + params["callsign"] = callsign; + int rpcRet = Core::ERROR_GENERAL; + if (nullptr != m_ControllerObj) + { + rpcRet = m_ControllerObj->Invoke("deactivate", params, result); + if(Core::ERROR_NONE == rpcRet) + { + LOGINFO("Deactivated %s plugin", callsign.c_str()); + } + else + { + LOGERR("Could not deactivate %s plugin. Failed with %d", callsign.c_str(), rpcRet); + } + } + else + { + LOGERR("Controller not active"); + } + return rpcRet; + } + + bool XCastImplementation::isPluginActivated(string callsign) + { + std::string method = "status@" + callsign; + bool isActive = false; + Core::JSON::ArrayType response; + if (nullptr != m_ControllerObj) + { + int ret = m_ControllerObj->Get(THUNDER_RPC_TIMEOUT, method, response); + isActive = (ret == Core::ERROR_NONE && response.Length() > 0 && response[0].JSONState == PluginHost::IShell::ACTIVATED); + LOGINFO("Plugin \"%s\" is %s, error=%d", callsign.c_str(), isActive ? "active" : "not active", ret); + } + else + { + LOGERR("Controller not active"); + } + return isActive; + } + + void XCastImplementation::startTimer(int interval) + { + stopTimer(); + m_locateCastTimer.start(interval); + } + + void XCastImplementation::stopTimer() + { + if (m_locateCastTimer.isActive()) + { + m_locateCastTimer.stop(); + } + } + + bool XCastImplementation::isTimerActive() + { + return (m_locateCastTimer.isActive()); + } + + //Timer Functions + void XCastImplementation::onLocateCastTimer() + { + if( false == connectToGDialService()) + { + LOGINFO("Retry after 10 sec..."); + m_locateCastTimer.setInterval(LOCATE_CAST_SECOND_TIMEOUT_IN_MILLIS); + return ; + }// err != RT_OK + stopTimer(); + + if (NULL != _rtConnector) { + std::vector appConfigList; + lock_guard lck(m_appConfigMutex); + appConfigList = appConfigListCache; + LOGINFO("XCast::onLocateCastTimer : calling registerApplications"); + _rtConnector->registerApplications (appConfigList); + } + else { + LOGINFO("XCast::onLocateCastTimer :_rtConnector: %p", _rtConnector); + } + _rtConnector->enableCastService(friendlyNameCache,xcastEnableCache); + LOGINFO("XCast::onLocateCastTimer : Timer still active ? %d ",m_locateCastTimer.isActive()); + } + + bool XCastImplementation::getDefaultNameAndIPAddress(std::string& interface, std::string& ipaddress) + { + // Read host IP from thunder service and save it into external_network.json + JsonObject Params, Result, Params0, Result0; + bool returnValue = false; + + getThunderPlugins(); + + uint32_t ret = m_NetworkPluginObj->Invoke(THUNDER_RPC_TIMEOUT, _T("getDefaultInterface"), Params0, Result0); + if (Core::ERROR_NONE == ret) + { + if (Result0["success"].Boolean()) + { + interface = Result0["interface"].String(); + } + else + { + LOGERR("XCastImplementation: failed to load interface"); + } + } + + Params.Set(_T("interface"), interface); + Params.Set(_T("ipversion"), string("IPv4")); + + ret = m_NetworkPluginObj->Invoke(THUNDER_RPC_TIMEOUT, _T("getIPSettings"), Params, Result); + if (Core::ERROR_NONE == ret) + { + if (Result["success"].Boolean()) + { + string ipAddress = Result["ipaddr"].String(); + LOGINFO("ipAddress = %s",ipAddress.c_str()); + returnValue = true; + } + else + { + LOGERR("getIPSettings failed"); + } + } + else + { + LOGERR("Failed to invoke method \"getIPSettings\". Error: %d",ret); + } + return returnValue; + } + + void XCastImplementation::updateNWConnectivityStatus(std::string nwInterface, bool nwConnected, std::string ipaddress) + { + bool status = false; + if(nwConnected) + { + if(nwInterface.compare("ETHERNET")==0){ + LOGINFO("Connectivity type Ethernet"); + status = true; + } + else if(nwInterface.compare("WIFI")==0){ + LOGINFO("Connectivity type WIFI"); + status = true; + } + else{ + LOGERR("Connectivity type Unknown"); + } + } + else + { + LOGERR("Connectivity type Unknown"); + } + if (!m_locateCastTimer.isActive()) + { + if (status) + { + if ((0 != nwInterface.compare(m_activeInterfaceName)) || + ((0 == nwInterface.compare(m_activeInterfaceName)) && !ipaddress.empty())) + { + if (_rtConnector) + { + LOGINFO("Stopping GDialService"); + _rtConnector->deinitialize(); + } + LOGINFO("Timer started to monitor active interface"); + startTimer(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); + } + } + } + } + + void XCastImplementation::eventHandler_onDefaultInterfaceChanged(const JsonObject& parameters) + { + std::string oldInterfaceName, newInterfaceName; + oldInterfaceName = parameters["oldInterfaceName"].String(); + newInterfaceName = parameters["newInterfaceName"].String(); + + LOGINFO("XCast onDefaultInterfaceChanged, old interface: %s, new interface: %s", oldInterfaceName.c_str(), newInterfaceName.c_str()); + updateNWConnectivityStatus(newInterfaceName.c_str(), true); + } + + void XCastImplementation::eventHandler_ipAddressChanged(const JsonObject& parameters) + { + if(parameters["status"].String() == "ACQUIRED") + { + string interface = parameters["interface"].String(); + string ipv4Address = parameters["ip4Address"].String(); + bool isAcquired = false; + if (!ipv4Address.empty()) + { + isAcquired = true; + } + updateNWConnectivityStatus(interface.c_str(), isAcquired, ipv4Address.c_str()); + } + } +} // namespace Plugin +} // namespace WPEFramework diff --git a/XCast/XCastImplementation.h b/XCast/XCastImplementation.h index 9de35c189f..0d9382b3ff 100644 --- a/XCast/XCastImplementation.h +++ b/XCast/XCastImplementation.h @@ -32,13 +32,20 @@ namespace Plugin { class XCastImplementation : public Exchange::IXCast, public PluginHost::IStateControl, public RtNotifier { public: + enum PluginState + { + PLUGIN_DEACTIVATED, + PLUGIN_ACTIVATED + }; + enum Event { LAUNCH_REQUEST_WITH_PARAMS, LAUNCH_REQUEST, STOP_REQUEST, HIDE_REQUEST, STATE_REQUEST, - RESUME_REQUEST + RESUME_REQUEST, + UPDATE_POWERSTATE }; class EXTERNAL Job : public Core::IDispatch { @@ -92,15 +99,19 @@ namespace Plugin { virtual void Unregister(Exchange::IXCast::INotification* sink) override ; virtual PluginHost::IStateControl::state State() const override { return PluginHost::IStateControl::RESUMED; } - virtual uint32_t Request(const command state) override; + virtual uint32_t Request(const command state) override { return Core::ERROR_GENERAL; } virtual void Register(IStateControl::INotification* notification) override {} virtual void Unregister(IStateControl::INotification* notification) override {} - virtual uint32_t Configure(PluginHost::IShell* service) override; + virtual uint32_t Configure(PluginHost::IShell* service) override { return Core::ERROR_NONE; } + + virtual uint32_t Initialize(bool networkStandbyMode) override; + virtual void Deinitialize(void) override; virtual uint32_t applicationStateChanged(const string& appName, const string& appstate, const string& appId, const string& error) const override; virtual uint32_t enableCastService(string friendlyname,bool enableService) const override; virtual uint32_t getProtocolVersion(string &protocolVersion) const override; virtual uint32_t registerApplications(Exchange::IXCast::IApplicationInfoIterator* const appLists) override; + virtual uint32_t setNetworkStandbyMode(bool nwStandbymode) override; virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, string strPayLoad, string strQuery, string strAddDataUrl) override ; virtual void onXcastApplicationLaunchRequest(string appName, string parameter) override ; @@ -108,20 +119,46 @@ namespace Plugin { virtual void onXcastApplicationHideRequest(string appName, string appId) override ; virtual void onXcastApplicationResumeRequest(string appName, string appId) override ; virtual void onXcastApplicationStateRequest(string appName, string appId) override ; + virtual void onXcastUpdatePowerStateRequest(string powerState) override; + virtual void onGDialServiceDisconnected(void) override; BEGIN_INTERFACE_MAP(XCastImplementation) - INTERFACE_ENTRY(Exchange::IXCast) - INTERFACE_ENTRY(PluginHost::IStateControl) + INTERFACE_ENTRY(Exchange::IXCast) + INTERFACE_ENTRY(PluginHost::IStateControl) END_INTERFACE_MAP private: static RtXcastConnector* _rtConnector; mutable Core::CriticalSection _adminLock; + TpTimer m_locateCastTimer; + WPEFramework::JSONRPC::LinkType *m_ControllerObj = nullptr; + WPEFramework::JSONRPC::LinkType *m_NetworkPluginObj = nullptr; + PluginState _networkPluginState; std::list _notificationClients; + static XCastImplementation* _instance; + bool m_networkStandbyMode{false}; void dispatchEvent(Event,string callsign, const JsonObject ¶ms); void Dispatch(Event event,string callsign, const JsonObject params); + void onLocateCastTimer(); + void startTimer(int interval); + void stopTimer(); + bool isTimerActive(); + + std::string getSecurityToken(); + void getThunderPlugins(); + int activatePlugin(string callsign); + int deactivatePlugin(string callsign); + bool isPluginActivated(string callsign); + void eventHandler_onDefaultInterfaceChanged(const JsonObject& parameters); + void eventHandler_ipAddressChanged(const JsonObject& parameters); + void eventHandler_pluginState(const JsonObject& parameters); + + bool connectToGDialService(void); + bool getDefaultNameAndIPAddress(std::string& interface, std::string& ipaddress); + void updateNWConnectivityStatus(std::string nwInterface, bool nwConnected, std::string ipaddress = ""); + public: XCastImplementation(); virtual ~XCastImplementation(); @@ -129,4 +166,4 @@ namespace Plugin { friend class Job; }; } // namespace Plugin -} // namespace WPEFramework \ No newline at end of file +} // namespace WPEFramework From b43d33fa1b923d7c58d6fd769759b8f069f7fe59 Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Thu, 19 Sep 2024 16:38:51 +0000 Subject: [PATCH 3/9] RDK-52203: Convert XCast plugin as OutOfProcess Signed-off-by: yuvaramachandran_gurusamy --- XCast/XCast.cpp | 7 ++++++- XCast/XCastImplementation.cpp | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/XCast/XCast.cpp b/XCast/XCast.cpp index ee856b0002..bd7c957b36 100644 --- a/XCast/XCast.cpp +++ b/XCast/XCast.cpp @@ -263,6 +263,9 @@ void XCast::threadPowerModeChangeEvent(void) if (m_is_restart_req) { m_is_restart_req = false; + m_instance->_xcast->Deinitialize(); + sleep(1); + m_instance->_xcast->Initialize(m_networkStandbyMode); } } else if(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP ) @@ -351,8 +354,10 @@ void XCast::Deinitialize(PluginHost::IShell* service) ASSERT(_service == service); ASSERT(_xcast != nullptr); - if(_xcast) + if(_xcast) { + _xcast->Deinitialize(); _xcast->Unregister(&_notification); + } if(_service) _service->Unregister(&_notification); diff --git a/XCast/XCastImplementation.cpp b/XCast/XCastImplementation.cpp index 47cd24b083..538833575e 100644 --- a/XCast/XCastImplementation.cpp +++ b/XCast/XCastImplementation.cpp @@ -480,11 +480,11 @@ namespace Plugin { auto ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onDefaultInterfaceChanged"), &XCastImplementation::eventHandler_onDefaultInterfaceChanged,this); if ( Core::ERROR_NONE == ev_ret ) { - LOGINFO("Network - IP address status changed event : subscribed"); + LOGINFO("Network - DefaultInterface changed event : subscribed"); } else { - LOGERR("Network - IP address status changed event : failed to subscribe : %d", ev_ret); + LOGERR("Network - DefaultInterface changed event : failed to subscribe : %d", ev_ret); } ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onIPAddressStatusChanged"), &XCastImplementation::eventHandler_ipAddressChanged,this); From b7783893c6d9079aae716ad0b3da24367c9c7a36 Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Mon, 23 Sep 2024 16:20:57 +0000 Subject: [PATCH 4/9] RDK-52203: Renamed RtXcastConnector as XCastManager Signed-off-by: yuvaramachandran_gurusamy --- XCast/CMakeLists.txt | 2 +- XCast/XCast.config | 2 +- XCast/XCast.cpp | 17 ++- XCast/XCastImplementation.cpp | 141 +++++++++++------- XCast/XCastImplementation.h | 14 +- ...{RtXcastConnector.cpp => XCastManager.cpp} | 86 +++++------ XCast/{RtXcastConnector.h => XCastManager.h} | 38 ++--- XCast/{RtNotifier.h => XCastNotifier.h} | 15 +- 8 files changed, 165 insertions(+), 150 deletions(-) rename XCast/{RtXcastConnector.cpp => XCastManager.cpp} (85%) rename XCast/{RtXcastConnector.h => XCastManager.h} (78%) rename XCast/{RtNotifier.h => XCastNotifier.h} (84%) diff --git a/XCast/CMakeLists.txt b/XCast/CMakeLists.txt index d21e06e9f1..48b5e68d4f 100644 --- a/XCast/CMakeLists.txt +++ b/XCast/CMakeLists.txt @@ -28,7 +28,7 @@ add_library(${MODULE_NAME} SHARED XCast.cpp XCastImplementation.cpp Module.cpp - RtXcastConnector.cpp) + XCastManager.cpp) find_package(RFC) find_package(IARMBus) diff --git a/XCast/XCast.config b/XCast/XCast.config index 20d85ef465..8efafc571d 100644 --- a/XCast/XCast.config +++ b/XCast/XCast.config @@ -9,4 +9,4 @@ endif() map() kv(mode ${PLUGIN_XCAST_MODE}) end() -ans(rootobject) \ No newline at end of file +ans(rootobject) diff --git a/XCast/XCast.cpp b/XCast/XCast.cpp index bd7c957b36..c52933ed21 100644 --- a/XCast/XCast.cpp +++ b/XCast/XCast.cpp @@ -262,13 +262,13 @@ void XCast::threadPowerModeChangeEvent(void) m_sleeptime = 1; if (m_is_restart_req) { + m_instance->_xcast->Deinitialize(); + sleep(1); + m_instance->_xcast->Initialize(m_networkStandbyMode); m_is_restart_req = false; - m_instance->_xcast->Deinitialize(); - sleep(1); - m_instance->_xcast->Initialize(m_networkStandbyMode); } } - else if(m_powerState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP ) + else if (m_powerState == IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP ) { m_sleeptime = 3; m_is_restart_req = true; //After DEEPSLEEP, restart xdial again for next transition. @@ -300,7 +300,7 @@ const string XCast::Initialize(PluginHost::IShell *service) _service = service; _skipURL = static_cast(service->WebPrefix().length()); - LOGINFO("##### API VER[%d : %d : %d : %d] #####", API_VERSION_NUMBER_MAJOR,API_VERSION_NUMBER_MINOR,API_VERSION_NUMBER_PATCH,API_VERSION_NUMBER_TEST); + LOGINFO("##### API VER[%d : %d : %d] #####", API_VERSION_NUMBER_MAJOR,API_VERSION_NUMBER_MINOR,API_VERSION_NUMBER_PATCH); _service->Register(&_notification); @@ -354,8 +354,9 @@ void XCast::Deinitialize(PluginHost::IShell* service) ASSERT(_service == service); ASSERT(_xcast != nullptr); - if(_xcast) { - _xcast->Deinitialize(); + if(_xcast) + { + _xcast->Deinitialize(); _xcast->Unregister(&_notification); } @@ -483,7 +484,7 @@ uint32_t XCast::setStandbyBehavior(const JsonObject& parameters, JsonObject& res } else { - returnResponse(false); + returnResponse(false); } m_standbyBehavior = enabled; LOGINFO("XcastService::setStandbyBehavior m_standbyBehavior : %d", m_standbyBehavior); diff --git a/XCast/XCastImplementation.cpp b/XCast/XCastImplementation.cpp index 538833575e..537e7a60f4 100644 --- a/XCast/XCastImplementation.cpp +++ b/XCast/XCastImplementation.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2020 RDK Management + * Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,12 +33,9 @@ #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 0 #define API_VERSION_NUMBER_PATCH 2 -#define API_VERSION_NUMBER_TEST 100 #define LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS 5000 //5 seconds #define LOCATE_CAST_SECOND_TIMEOUT_IN_MILLIS 10000 //10 seconds -#define LOCATE_CAST_THIRD_TIMEOUT_IN_MILLIS 30000 //30 seconds -#define LOCATE_CAST_FINAL_TIMEOUT_IN_MILLIS 60000 //60 seconds namespace WPEFramework { namespace Plugin { @@ -46,16 +43,17 @@ namespace Plugin { SERVICE_REGISTRATION(XCastImplementation, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); XCastImplementation *XCastImplementation::_instance = nullptr; - RtXcastConnector* XCastImplementation::_rtConnector = nullptr; + XCastManager* XCastImplementation::m_xcast_manager = nullptr; static std::vector appConfigListCache; static std::mutex m_appConfigMutex; static bool xcastEnableCache = false; - static string friendlyNameCache = ""; + static string friendlyNameCache = "Living Room"; static string m_activeInterfaceName = ""; + static bool m_isDynamicRegistrationsRequired = false; XCastImplementation::XCastImplementation() : _adminLock() { - LOGINFO("##### API VER[%d : %d : %d : %d] #####", API_VERSION_NUMBER_MAJOR,API_VERSION_NUMBER_MINOR,API_VERSION_NUMBER_PATCH,API_VERSION_NUMBER_TEST); + LOGINFO("##### API VER[%d : %d : %d] #####", API_VERSION_NUMBER_MAJOR,API_VERSION_NUMBER_MINOR,API_VERSION_NUMBER_PATCH); m_locateCastTimer.connect( bind( &XCastImplementation::onLocateCastTimer, this )); } @@ -94,13 +92,13 @@ namespace Plugin { uint32_t XCastImplementation::Initialize(bool networkStandbyMode) { - if(nullptr == _rtConnector) + if(nullptr == m_xcast_manager) { m_networkStandbyMode = networkStandbyMode; - _rtConnector = RtXcastConnector::getInstance(); - if(nullptr != _rtConnector) + m_xcast_manager = XCastManager::getInstance(); + if(nullptr != m_xcast_manager) { - _rtConnector->setService(this); + m_xcast_manager->setService(this); if( false == connectToGDialService()) { startTimer(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); @@ -112,20 +110,20 @@ namespace Plugin { void XCastImplementation::Deinitialize(void) { - if(nullptr != _rtConnector) + if(nullptr != m_xcast_manager) { stopTimer(); - _rtConnector->shutdown(); - _rtConnector = nullptr; + m_xcast_manager->shutdown(); + m_xcast_manager = nullptr; } } uint32_t XCastImplementation::enableCastService(string friendlyname,bool enableService) const { LOGINFO("XcastService::enableCastService: ARGS = %s : %d", friendlyname.c_str(), enableService); - if (nullptr != _rtConnector) + if (nullptr != m_xcast_manager) { - _rtConnector->enableCastService(friendlyname,enableService); + m_xcast_manager->enableCastService(friendlyname,enableService); } xcastEnableCache = enableService; friendlyNameCache = friendlyname; @@ -136,10 +134,10 @@ namespace Plugin { { LOGINFO("ApplicationStateChanged ARGS = %s : %s : %s : %s ", appName.c_str(), appId.c_str() , appstate.c_str() , error.c_str()); uint32_t status = Core::ERROR_GENERAL; - if(!appName.empty() && !appstate.empty() && (nullptr != _rtConnector)) + if(!appName.empty() && !appstate.empty() && (nullptr != m_xcast_manager)) { LOGINFO("XcastService::ApplicationStateChanged ARGS = %s : %s : %s : %s ", appName.c_str(), appId.c_str() , appstate.c_str() , error.c_str()); - _rtConnector->applicationStateChanged(appName, appstate, appId, error); + m_xcast_manager->applicationStateChanged(appName, appstate, appId, error); status = Core::ERROR_NONE; } return status; @@ -148,9 +146,9 @@ namespace Plugin { uint32_t XCastImplementation::getProtocolVersion(std::string &protocolVersion) const { LOGINFO("XcastService::getProtocolVersion"); - if (nullptr != _rtConnector) + if (nullptr != m_xcast_manager) { - protocolVersion = _rtConnector->getProtocolVersion(); + protocolVersion = m_xcast_manager->getProtocolVersion(); } return Core::ERROR_NONE; } @@ -161,7 +159,7 @@ namespace Plugin { std::vector appConfigListTemp; uint32_t status = Core::ERROR_GENERAL; - if ((nullptr != _rtConnector) && (appLists)) + if ((nullptr != m_xcast_manager) && (appLists)) { Exchange::IXCast::ApplicationInfo entry{}; @@ -186,7 +184,8 @@ namespace Plugin { appConfigListTemp.push_back (pDynamicAppConfig); } } - _rtConnector->registerApplications(appConfigListTemp); + m_isDynamicRegistrationsRequired = true; + m_xcast_manager->registerApplications(appConfigListTemp); { lock_guard lck(m_appConfigMutex); for (DynamicAppConfig* pDynamicAppConfigOld : appConfigListCache) @@ -196,18 +195,35 @@ namespace Plugin { } appConfigListCache.clear(); appConfigListCache = appConfigListTemp; + dumpDynamicAppCacheList(string("registeredAppsFromUser"), appConfigListCache); } status = Core::ERROR_NONE; } return status; } + void XCastImplementation::dumpDynamicAppCacheList(string strListName, std::vector appConfigList) + { + LOGINFO ("=================Current Apps[%s] size[%d] ===========================", strListName.c_str(), (int)appConfigList.size()); + for (DynamicAppConfig* pDynamicAppConfig : appConfigList) + { + LOGINFO ("Apps: appName:%s, prefixes:%s, cors:%s, allowStop:%d, query:%s, payload:%s", + pDynamicAppConfig->appName, + pDynamicAppConfig->prefixes, + pDynamicAppConfig->cors, + pDynamicAppConfig->allowStop, + pDynamicAppConfig->query, + pDynamicAppConfig->payload); + } + LOGINFO ("================================================================="); + } + uint32_t XCastImplementation::setNetworkStandbyMode(bool nwStandbymode) { LOGINFO("nwStandbymode: %d", nwStandbymode); - if (nullptr != _rtConnector) + if (nullptr != m_xcast_manager) { - _rtConnector->setNetworkStandbyMode(nwStandbymode); + m_xcast_manager->setNetworkStandbyMode(nwStandbymode); m_networkStandbyMode = nwStandbymode; } return Core::ERROR_NONE; @@ -348,8 +364,9 @@ namespace Plugin { dispatchEvent(UPDATE_POWERSTATE, "", params); } - void XCastImplementation::onGDialServiceDisconnected(void) + void XCastImplementation::onGDialServiceStopped(void) { + LOGINFO("Timer triggered to monitor the GDial, check after 5sec"); startTimer(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); } @@ -361,12 +378,13 @@ namespace Plugin { getDefaultNameAndIPAddress(interface,ipaddress); if (!interface.empty()) { - status = _rtConnector->initialize(interface,m_networkStandbyMode); + status = m_xcast_manager->initialize(interface,m_networkStandbyMode); if( true == status) { m_activeInterfaceName = interface; } } + LOGINFO("GDialService[%u]IF[%s]IP[%s]",status,interface.c_str(),ipaddress.c_str()); return status; } @@ -426,34 +444,37 @@ namespace Plugin { { string token = getSecurityToken(); - m_ControllerObj = new WPEFramework::JSONRPC::LinkType("", "", false, token); - - if (nullptr != m_ControllerObj) + if (nullptr == m_ControllerObj) { - auto ev_ret = m_ControllerObj->Subscribe(1000, _T("statechange"),&XCastImplementation::eventHandler_pluginState,this); - if (ev_ret == Core::ERROR_NONE) - { - LOGINFO("Controller - statechange event subscribed"); - } - else - { - LOGERR("Controller - statechange event failed to subscribe : %d",ev_ret); - } + m_ControllerObj = new WPEFramework::JSONRPC::LinkType("", "", false, token); - if (!isPluginActivated(NETWORK_CALLSIGN_VER)) + if (nullptr != m_ControllerObj) { - activatePlugin(NETWORK_CALLSIGN_VER); - _networkPluginState = PLUGIN_DEACTIVATED; + auto ev_ret = m_ControllerObj->Subscribe(1000, _T("statechange"),&XCastImplementation::eventHandler_pluginState,this); + if (ev_ret == Core::ERROR_NONE) + { + LOGINFO("Controller - statechange event subscribed"); + } + else + { + LOGERR("Controller - statechange event failed to subscribe : %d",ev_ret); + } + + if (!isPluginActivated(NETWORK_CALLSIGN_VER)) + { + activatePlugin(NETWORK_CALLSIGN_VER); + _networkPluginState = PLUGIN_DEACTIVATED; + } + else + { + _networkPluginState = PLUGIN_ACTIVATED; + } } else { - _networkPluginState = PLUGIN_ACTIVATED; + LOGERR("Unable to get Controller obj"); } } - else - { - LOGERR("Unable to get Controller obj"); - } if (nullptr == m_NetworkPluginObj) { @@ -480,11 +501,11 @@ namespace Plugin { auto ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onDefaultInterfaceChanged"), &XCastImplementation::eventHandler_onDefaultInterfaceChanged,this); if ( Core::ERROR_NONE == ev_ret ) { - LOGINFO("Network - DefaultInterface changed event : subscribed"); + LOGINFO("Network - Default Interface changed event : subscribed"); } else { - LOGERR("Network - DefaultInterface changed event : failed to subscribe : %d", ev_ret); + LOGERR("Network - Default Interface changed event : failed to subscribe : %d", ev_ret); } ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onIPAddressStatusChanged"), &XCastImplementation::eventHandler_ipAddressChanged,this); @@ -609,20 +630,24 @@ namespace Plugin { LOGINFO("Retry after 10 sec..."); m_locateCastTimer.setInterval(LOCATE_CAST_SECOND_TIMEOUT_IN_MILLIS); return ; - }// err != RT_OK + } stopTimer(); - if (NULL != _rtConnector) { + if ((NULL != m_xcast_manager) && m_isDynamicRegistrationsRequired ) + { std::vector appConfigList; lock_guard lck(m_appConfigMutex); appConfigList = appConfigListCache; - LOGINFO("XCast::onLocateCastTimer : calling registerApplications"); - _rtConnector->registerApplications (appConfigList); + dumpDynamicAppCacheList(string("CachedAppsFromTimer"), appConfigList); + LOGINFO("> calling registerApplications"); + m_xcast_manager->registerApplications (appConfigList); } else { - LOGINFO("XCast::onLocateCastTimer :_rtConnector: %p", _rtConnector); + LOGINFO("m_xcast_manager: %p: m_isDynamicRegistrationsRequired[%u]", + m_xcast_manager, + m_isDynamicRegistrationsRequired); } - _rtConnector->enableCastService(friendlyNameCache,xcastEnableCache); + m_xcast_manager->enableCastService(friendlyNameCache,xcastEnableCache); LOGINFO("XCast::onLocateCastTimer : Timer still active ? %d ",m_locateCastTimer.isActive()); } @@ -655,8 +680,8 @@ namespace Plugin { { if (Result["success"].Boolean()) { - string ipAddress = Result["ipaddr"].String(); - LOGINFO("ipAddress = %s",ipAddress.c_str()); + ipaddress = Result["ipaddr"].String(); + LOGINFO("ipAddress = %s",ipaddress.c_str()); returnValue = true; } else @@ -699,10 +724,10 @@ namespace Plugin { if ((0 != nwInterface.compare(m_activeInterfaceName)) || ((0 == nwInterface.compare(m_activeInterfaceName)) && !ipaddress.empty())) { - if (_rtConnector) + if (m_xcast_manager) { LOGINFO("Stopping GDialService"); - _rtConnector->deinitialize(); + m_xcast_manager->deinitialize(); } LOGINFO("Timer started to monitor active interface"); startTimer(LOCATE_CAST_FIRST_TIMEOUT_IN_MILLIS); diff --git a/XCast/XCastImplementation.h b/XCast/XCastImplementation.h index 0d9382b3ff..f76a256149 100644 --- a/XCast/XCastImplementation.h +++ b/XCast/XCastImplementation.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2020 RDK Management + * Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,14 +23,14 @@ #include #include #include "tracing/Logging.h" -#include "RtXcastConnector.h" -#include "RtNotifier.h" +#include "XCastManager.h" +#include "XCastNotifier.h" #include namespace WPEFramework { namespace Plugin { - class XCastImplementation : public Exchange::IXCast, public PluginHost::IStateControl, public RtNotifier { + class XCastImplementation : public Exchange::IXCast, public PluginHost::IStateControl, public XCastNotifier { public: enum PluginState { @@ -120,7 +120,7 @@ namespace Plugin { virtual void onXcastApplicationResumeRequest(string appName, string appId) override ; virtual void onXcastApplicationStateRequest(string appName, string appId) override ; virtual void onXcastUpdatePowerStateRequest(string powerState) override; - virtual void onGDialServiceDisconnected(void) override; + virtual void onGDialServiceStopped(void) override; BEGIN_INTERFACE_MAP(XCastImplementation) INTERFACE_ENTRY(Exchange::IXCast) @@ -128,7 +128,7 @@ namespace Plugin { END_INTERFACE_MAP private: - static RtXcastConnector* _rtConnector; + static XCastManager* m_xcast_manager; mutable Core::CriticalSection _adminLock; TpTimer m_locateCastTimer; WPEFramework::JSONRPC::LinkType *m_ControllerObj = nullptr; @@ -141,6 +141,8 @@ namespace Plugin { void dispatchEvent(Event,string callsign, const JsonObject ¶ms); void Dispatch(Event event,string callsign, const JsonObject params); + void dumpDynamicAppCacheList(string strListName, std::vector appConfigList); + void onLocateCastTimer(); void startTimer(int interval); void stopTimer(); diff --git a/XCast/RtXcastConnector.cpp b/XCast/XCastManager.cpp similarity index 85% rename from XCast/RtXcastConnector.cpp rename to XCast/XCastManager.cpp index d9eca904e7..d6a220519f 100644 --- a/XCast/RtXcastConnector.cpp +++ b/XCast/XCastManager.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * - * Copyright 2020 RDK Management + * Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ * limitations under the License. **/ -#include "RtXcastConnector.h" +#include "XCastManager.h" #include "UtilsJsonRpc.h" #include "rfcapi.h" @@ -34,7 +34,7 @@ using namespace WPEFramework; static gdialService* gdialCastObj = NULL; -RtXcastConnector * RtXcastConnector::_instance = nullptr; +XCastManager * XCastManager::_instance = nullptr; std::string m_modelName = ""; std::string m_manufacturerName = ""; std::string m_defaultfriendlyName = ""; @@ -45,7 +45,7 @@ std::string m_defaultAppList = ""; /** * Callback function for application launch request from an app */ -void RtXcastConnector::onApplicationLaunchRequestWithLaunchParam(string appName,string strPayLoad, string strQuery, string strAddDataUrl) +void XCastManager::onApplicationLaunchRequestWithLaunchParam(string appName,string strPayLoad, string strQuery, string strAddDataUrl) { if ( nullptr != m_observer ) { @@ -53,7 +53,7 @@ void RtXcastConnector::onApplicationLaunchRequestWithLaunchParam(string appName, } } -void RtXcastConnector::onApplicationLaunchRequest(string appName, string parameter) +void XCastManager::onApplicationLaunchRequest(string appName, string parameter) { if ( nullptr != m_observer ) { @@ -65,7 +65,7 @@ void RtXcastConnector::onApplicationLaunchRequest(string appName, string paramet } } -void RtXcastConnector::onApplicationStopRequest(string appName, string appID) +void XCastManager::onApplicationStopRequest(string appName, string appID) { if ( nullptr != m_observer ) { @@ -77,7 +77,7 @@ void RtXcastConnector::onApplicationStopRequest(string appName, string appID) } } -void RtXcastConnector::onApplicationHideRequest(string appName, string appID) +void XCastManager::onApplicationHideRequest(string appName, string appID) { if ( nullptr != m_observer ) { @@ -89,7 +89,7 @@ void RtXcastConnector::onApplicationHideRequest(string appName, string appID) } } -void RtXcastConnector::onApplicationResumeRequest(string appName, string appID) +void XCastManager::onApplicationResumeRequest(string appName, string appID) { if ( nullptr != m_observer ) { @@ -101,7 +101,7 @@ void RtXcastConnector::onApplicationResumeRequest(string appName, string appID) } } -void RtXcastConnector::onApplicationStateRequest(string appName, string appID) +void XCastManager::onApplicationStateRequest(string appName, string appID) { if ( nullptr != m_observer ) { @@ -113,15 +113,15 @@ void RtXcastConnector::onApplicationStateRequest(string appName, string appID) } } -void RtXcastConnector::onDisconnect(void) +void XCastManager::onStopped(void) { if ( nullptr != m_observer ) { - m_observer->onGDialServiceDisconnected(); + m_observer->onGDialServiceStopped(); } } -void RtXcastConnector::updatePowerState(string powerState) +void XCastManager::updatePowerState(string powerState) { if ( nullptr != m_observer ) { @@ -129,13 +129,13 @@ void RtXcastConnector::updatePowerState(string powerState) } } -RtXcastConnector::~RtXcastConnector() +XCastManager::~XCastManager() { _instance = nullptr; m_observer = nullptr; } -bool RtXcastConnector::initialize(const std::string& gdial_interface_name, bool networkStandbyMode ) +bool XCastManager::initialize(const std::string& gdial_interface_name, bool networkStandbyMode ) { std::vector gdial_args; bool returnValue = false, @@ -144,7 +144,7 @@ bool RtXcastConnector::initialize(const std::string& gdial_interface_name, bool if (gdial_interface_name.empty()) { - LOGINFO("Interface Name should not be empty"); + LOGERR("Interface Name should not be empty"); return false; } @@ -272,41 +272,43 @@ bool RtXcastConnector::initialize(const std::string& gdial_interface_name, bool if (isWolWakeEnableEnabled && networkStandbyMode ) { gdial_args.push_back("--feature-wolwake"); } + if (nullptr == gdialCastObj) { gdialCastObj = gdialService::getInstance(this,gdial_args,"XCastOutofProcess"); - if (nullptr != gdialCastObj) - { - returnValue = true; - } } - LOGINFO("Exiting[%p] ...",gdialCastObj); + + if (nullptr != gdialCastObj) + { + returnValue = true; + LOGINFO("gdialService::getInstance success[%p] ...",gdialCastObj); + } + LOGINFO("Exiting [%u] ...",returnValue); return returnValue; } -void RtXcastConnector::deinitialize() +void XCastManager::deinitialize() { lock_guard lock(m_mutexSync); if (nullptr != gdialCastObj) { - lock_guard lock(m_mutexSync); gdialService::destroyInstance(); gdialCastObj = nullptr; } } -void RtXcastConnector::shutdown() +void XCastManager::shutdown() { - LOGINFO("Shutting down rtRemote connectivity"); + LOGINFO("Shutting down XCastManager"); deinitialize(); - if(RtXcastConnector::_instance != nullptr) + if(XCastManager::_instance != nullptr) { - delete RtXcastConnector::_instance; - RtXcastConnector::_instance = nullptr; + delete XCastManager::_instance; + XCastManager::_instance = nullptr; } } -std::string RtXcastConnector::getReceiverID(void) +std::string XCastManager::getReceiverID(void) { std::ifstream file("/tmp/gpid.txt"); std::string line, gpidValue, receiverId = ""; @@ -354,7 +356,7 @@ std::string RtXcastConnector::getReceiverID(void) return receiverId; } -void RtXcastConnector::getWiFiInterface(std::string& WiFiInterfaceName) +void XCastManager::getWiFiInterface(std::string& WiFiInterfaceName) { std::string buildType; std::ifstream file_stream("/opt/wifi_interface"); @@ -374,7 +376,7 @@ void RtXcastConnector::getWiFiInterface(std::string& WiFiInterfaceName) } } -void RtXcastConnector::getGDialInterfaceName(std::string& interfaceName) +void XCastManager::getGDialInterfaceName(std::string& interfaceName) { std::ifstream file_stream("/tmp/wifi-on"); if (file_stream) @@ -391,7 +393,7 @@ void RtXcastConnector::getGDialInterfaceName(std::string& interfaceName) } } -bool RtXcastConnector::envGetValue(const char *key, std::string &value) +bool XCastManager::envGetValue(const char *key, std::string &value) { std::ifstream fs(COMMON_DEVICE_PROPERTIES_FILE, std::ifstream::in); std::string::size_type delimpos; @@ -417,7 +419,7 @@ bool RtXcastConnector::envGetValue(const char *key, std::string &value) return returnValue; } -int RtXcastConnector::applicationStateChanged( string app, string state, string id, string error) +int XCastManager::applicationStateChanged( string app, string state, string id, string error) { int status = 0; LOGINFO("XcastService::ApplicationStateChanged ARGS = %s : %s : %s : %s ", app.c_str(), id.c_str() , state.c_str() , error.c_str()); @@ -432,7 +434,7 @@ int RtXcastConnector::applicationStateChanged( string app, string state, string return status; }//app && state not empty -void RtXcastConnector::enableCastService(string friendlyname,bool enableService) +void XCastManager::enableCastService(string friendlyname,bool enableService) { LOGINFO("XcastService::enableCastService ARGS = %s : %d ", friendlyname.c_str(), enableService); lock_guard lock(m_mutexSync); @@ -446,7 +448,7 @@ void RtXcastConnector::enableCastService(string friendlyname,bool enableService) LOGINFO(" gdialCastObj is NULL "); } -void RtXcastConnector::updateFriendlyName(string friendlyname) +void XCastManager::updateFriendlyName(string friendlyname) { LOGINFO("XcastService::updateFriendlyName ARGS = %s ", friendlyname.c_str()); lock_guard lock(m_mutexSync); @@ -459,7 +461,7 @@ void RtXcastConnector::updateFriendlyName(string friendlyname) LOGINFO(" gdialCastObj is NULL "); } -string RtXcastConnector::getProtocolVersion(void) +string XCastManager::getProtocolVersion(void) { LOGINFO("XcastService::getProtocolVersion "); std::string strVersion; @@ -477,7 +479,7 @@ string RtXcastConnector::getProtocolVersion(void) return strVersion; } -void RtXcastConnector::registerApplications(std::vector& appConfigList) +void XCastManager::registerApplications(std::vector& appConfigList) { LOGINFO("XcastService::RegisterAppEntryList"); @@ -514,7 +516,7 @@ void RtXcastConnector::registerApplications(std::vector& appC } } -void RtXcastConnector::setNetworkStandbyMode(bool nwStandbymode) +void XCastManager::setNetworkStandbyMode(bool nwStandbymode) { lock_guard lock(m_mutexSync); if(gdialCastObj != NULL) @@ -528,18 +530,18 @@ void RtXcastConnector::setNetworkStandbyMode(bool nwStandbymode) } } -RtXcastConnector * RtXcastConnector::getInstance() +XCastManager * XCastManager::getInstance() { LOGINFO("Entering ..."); - if(RtXcastConnector::_instance == nullptr) + if(XCastManager::_instance == nullptr) { - RtXcastConnector::_instance = new RtXcastConnector(); + XCastManager::_instance = new XCastManager(); } LOGINFO("Exiting ..."); - return RtXcastConnector::_instance; + return XCastManager::_instance; } -bool RtXcastConnector::IsAppEnabled(char* strAppName) +bool XCastManager::IsAppEnabled(char* strAppName) { bool ret = false; #ifdef RFC_ENABLED diff --git a/XCast/RtXcastConnector.h b/XCast/XCastManager.h similarity index 78% rename from XCast/RtXcastConnector.h rename to XCast/XCastManager.h index 33c02be297..414114c1f6 100644 --- a/XCast/RtXcastConnector.h +++ b/XCast/XCastManager.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * - * Copyright 2020 RDK Management + * Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ #include #include "Module.h" #include "tptimer.h" -#include "RtNotifier.h" +#include "XCastNotifier.h" #include "XCastCommon.h" #include #include @@ -32,22 +32,21 @@ using namespace std; /** - * This is the connector class for interacting with xdial client using rtRemote. + * This is the Manager class for interacting with gdial library. */ -class RtXcastConnector : public GDialNotifier +class XCastManager : public GDialNotifier { protected: - //RtXcastConnector():m_runEventThread(true){} - RtXcastConnector(){} + XCastManager(){} public: - virtual ~RtXcastConnector(); + virtual ~XCastManager(); /** - * Initialize rtRemote communication with rtDial server + * Initialize gdialService to communication with gdial server */ bool initialize(const std::string& gdial_interface_name, bool networkStandbyMode ); void deinitialize(); - /** Shutdown rtRemote connectivity */ + /** Shutdown gdialService connectivity */ void shutdown(); /** *The application state change function . This is invoked from application side. @@ -75,7 +74,7 @@ class RtXcastConnector : public GDialNotifier /** *Request the single instance of this class */ - static RtXcastConnector * getInstance(); + static XCastManager * getInstance(); virtual void onApplicationLaunchRequest(string appName, string parameter) override; virtual void onApplicationLaunchRequestWithLaunchParam (string appName,string strPayLoad, string strQuery, string strAddDataUrl) override; @@ -83,7 +82,7 @@ class RtXcastConnector : public GDialNotifier virtual void onApplicationHideRequest(string appName, string appID) override; virtual void onApplicationResumeRequest(string appName, string appID) override; virtual void onApplicationStateRequest(string appName, string appID) override; - virtual void onDisconnect(void) override; + virtual void onStopped(void) override; virtual void updatePowerState(string powerState) override; /** @@ -91,21 +90,12 @@ class RtXcastConnector : public GDialNotifier */ int isGDialStarted(); - void setService(RtNotifier * service){ + void setService(XCastNotifier * service){ m_observer = service; } private: //Internal methods - //RT Connector class - RtNotifier * m_observer; - //Event Monitoring thread - //thread m_eventMtrThread; - // Atomic lock - //mutex m_threadlock; - // Boolean event thread exit condition - //bool m_runEventThread; - // Member function to handle RT messages. - //void processRtMessages(); + XCastNotifier * m_observer; bool IsAppEnabled(char* strAppName); void getWiFiInterface(std::string& WiFiInterfaceName); void getGDialInterfaceName(std::string& interfaceName); @@ -114,8 +104,6 @@ class RtXcastConnector : public GDialNotifier // Class level contracts // Singleton instance - static RtXcastConnector * _instance; + static XCastManager * _instance; std::recursive_mutex m_mutexSync; - // Thread main function - //static void threadRun(RtXcastConnector *rtCtx); }; diff --git a/XCast/RtNotifier.h b/XCast/XCastNotifier.h similarity index 84% rename from XCast/RtNotifier.h rename to XCast/XCastNotifier.h index 2e182867a8..3047a11d9f 100644 --- a/XCast/RtNotifier.h +++ b/XCast/XCastNotifier.h @@ -16,26 +16,23 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -#ifndef RT_NOTIFIER_H -#define RT_NOTIFIER_H +#ifndef XCAST_NOTIFIER_H +#define XCAST_NOTIFIER_H /** * Abstract class for Notification. */ using namespace std; -class RtNotifier +class XCastNotifier { public: - - virtual void onGDialServiceDisconnected(void)=0; + virtual void onGDialServiceStopped(void)=0; virtual void onXcastApplicationLaunchRequest(string appName, string parameter)=0; - virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName, - string strPayLoad, string strQuery, string strAddDataUrl)=0; + virtual void onXcastApplicationLaunchRequestWithLaunchParam (string appName,string strPayLoad, string strQuery, string strAddDataUrl)=0; virtual void onXcastApplicationStopRequest(string appName, string appID)=0; virtual void onXcastApplicationHideRequest(string appName, string appID)=0; virtual void onXcastApplicationResumeRequest(string appName, string appID)=0; virtual void onXcastApplicationStateRequest(string appName, string appID)=0; virtual void onXcastUpdatePowerStateRequest(string powerState)=0; }; -#endif - +#endif \ No newline at end of file From e82a1f03e5ec648bd861c106da23701d45498acb Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Sun, 20 Oct 2024 21:57:17 +0000 Subject: [PATCH 5/9] RDK-53913: Syncup RDKE changes here Signed-off-by: yuvaramachandran_gurusamy --- XCast/CMakeLists.txt | 8 ++++++-- XCast/XCastImplementation.cpp | 5 +++++ XCast/XCastManager.h | 4 ++-- XCast/XCastNotifier.h | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/XCast/CMakeLists.txt b/XCast/CMakeLists.txt index 48b5e68d4f..6495a3a414 100644 --- a/XCast/CMakeLists.txt +++ b/XCast/CMakeLists.txt @@ -28,11 +28,15 @@ add_library(${MODULE_NAME} SHARED XCast.cpp XCastImplementation.cpp Module.cpp - XCastManager.cpp) + XCastManager.cpp) find_package(RFC) find_package(IARMBus) find_package(GLIB REQUIRED) +find_package(WPEFrameworkSecurityUtil) +if(NOT WPEFRAMEWORK_SECURITYUTIL_FOUND) + add_definitions(-DSECURITY_TOKEN_ENABLED=0) +endif() find_library(XDIAL_LIBRARIES NAMES gdial-server) @@ -50,7 +54,7 @@ target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS}) if(NOT RDK_SERVICES_L1_TEST) target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${RFC_LIBRARIES} ${IARMBUS_LIBRARIES} ${XDIAL_LIBRARIES}) else(RDK_SERVICES_L1_TEST) - target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${RFC_LIBRARIES} ${IARMBUS_LIBRARIES}) + target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${RFC_LIBRARIES} ${IARMBUS_LIBRARIES}) endif() install(TARGETS ${MODULE_NAME} diff --git a/XCast/XCastImplementation.cpp b/XCast/XCastImplementation.cpp index 537e7a60f4..86177541ca 100644 --- a/XCast/XCastImplementation.cpp +++ b/XCast/XCastImplementation.cpp @@ -21,8 +21,13 @@ #include #include "UtilsJsonRpc.h" #include "rfcapi.h" +#if defined(SECURITY_TOKEN_ENABLED) && ((SECURITY_TOKEN_ENABLED == 0) || (SECURITY_TOKEN_ENABLED == false)) +#define GetSecurityToken(a, b) 0 +#define GetToken(a, b, c) 0 +#else #include #include +#endif #define SERVER_DETAILS "127.0.0.1:9998" #define NETWORK_CALLSIGN "org.rdk.Network" diff --git a/XCast/XCastManager.h b/XCast/XCastManager.h index 414114c1f6..488c7da03f 100644 --- a/XCast/XCastManager.h +++ b/XCast/XCastManager.h @@ -26,8 +26,8 @@ #include "tptimer.h" #include "XCastNotifier.h" #include "XCastCommon.h" -#include -#include +#include +#include using namespace std; diff --git a/XCast/XCastNotifier.h b/XCast/XCastNotifier.h index 3047a11d9f..34c0234a16 100644 --- a/XCast/XCastNotifier.h +++ b/XCast/XCastNotifier.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2020 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,4 +35,4 @@ class XCastNotifier virtual void onXcastApplicationStateRequest(string appName, string appID)=0; virtual void onXcastUpdatePowerStateRequest(string powerState)=0; }; -#endif \ No newline at end of file +#endif From 6b94511161c0db88c5e7b4aee251f31dde0bb303 Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Mon, 21 Oct 2024 19:26:51 +0000 Subject: [PATCH 6/9] RDK-53913: Added the error handling while accessing remote object Signed-off-by: yuvaramachandran_gurusamy --- XCast/XCastImplementation.cpp | 37 +++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/XCast/XCastImplementation.cpp b/XCast/XCastImplementation.cpp index 86177541ca..40b4af0452 100644 --- a/XCast/XCastImplementation.cpp +++ b/XCast/XCastImplementation.cpp @@ -455,10 +455,12 @@ namespace Plugin { if (nullptr != m_ControllerObj) { + bool isSubscribed = false; auto ev_ret = m_ControllerObj->Subscribe(1000, _T("statechange"),&XCastImplementation::eventHandler_pluginState,this); if (ev_ret == Core::ERROR_NONE) { LOGINFO("Controller - statechange event subscribed"); + isSubscribed = true; } else { @@ -474,6 +476,12 @@ namespace Plugin { { _networkPluginState = PLUGIN_ACTIVATED; } + + if (false == isSubscribed) + { + delete m_ControllerObj; + m_ControllerObj = nullptr; + } } else { @@ -503,24 +511,31 @@ namespace Plugin { // Network monitor so we can know ip address of host inside container if(m_NetworkPluginObj) { + bool isSubscribed = false; auto ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onDefaultInterfaceChanged"), &XCastImplementation::eventHandler_onDefaultInterfaceChanged,this); if ( Core::ERROR_NONE == ev_ret ) { LOGINFO("Network - Default Interface changed event : subscribed"); + ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onIPAddressStatusChanged"), &XCastImplementation::eventHandler_ipAddressChanged,this); + if ( Core::ERROR_NONE == ev_ret ) + { + LOGINFO("Network - IP address status changed event : subscribed"); + isSubscribed = true; + } + else + { + LOGERR("Network - IP address status changed event : failed to subscribe : %d", ev_ret); + } } else { LOGERR("Network - Default Interface changed event : failed to subscribe : %d", ev_ret); } - - ev_ret = m_NetworkPluginObj->Subscribe(THUNDER_RPC_TIMEOUT, _T("onIPAddressStatusChanged"), &XCastImplementation::eventHandler_ipAddressChanged,this); - if ( Core::ERROR_NONE == ev_ret ) - { - LOGINFO("Network - IP address status changed event : subscribed"); - } - else + if (false == isSubscribed) { - LOGERR("Network - IP address status changed event : failed to subscribe : %d", ev_ret); + LOGERR("Network events subscription failed"); + delete m_NetworkPluginObj; + m_NetworkPluginObj = nullptr; } } } @@ -664,6 +679,12 @@ namespace Plugin { getThunderPlugins(); + if (nullptr == m_NetworkPluginObj) + { + LOGINFO("WARN::Unable to get Network plugin handle not yet"); + return false; + } + uint32_t ret = m_NetworkPluginObj->Invoke(THUNDER_RPC_TIMEOUT, _T("getDefaultInterface"), Params0, Result0); if (Core::ERROR_NONE == ret) { From b377b0c46fcb6e7b36cfa0934c6f1b92643e68e6 Mon Sep 17 00:00:00 2001 From: yuvaramachandran_gurusamy Date: Tue, 29 Oct 2024 19:03:42 +0530 Subject: [PATCH 7/9] RDK-53913: Disable L1 tests for XCast as IIterator not ported in R2 Signed-off-by: yuvaramachandran_gurusamy --- .github/workflows/L1-tests.yml | 3 +-- Tests/L1Tests/CMakeLists.txt | 7 +++---- Tests/L1Tests/tests/test_XCast.cpp | 3 ++- l1tests.cmake | 1 - 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 9f00c60f58..8808eff279 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -141,8 +141,7 @@ jobs: run: > cd "${{github.workspace}}/ThunderInterfaces" && - git apply "${{github.workspace}}/rdkservices/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch" - && + git apply "${{github.workspace}}/rdkservices/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch" && cd .. - name: Build ThunderInterfaces diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 9d503372c2..feeba72963 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -89,7 +89,7 @@ include_directories(../../LocationSync ../../HdmiCec ../../HdmiCec_2 ../../HdmiCecSource - ../../XCast + ../../XCast ../../FrontPanel ../../HdmiCecSink ../../RDKShell @@ -133,9 +133,9 @@ link_directories(../../LocationSync ../../HdmiCec ../../HdmiCec_2 ../../HdmiCecSource - ../../XCast + ../../XCast ../../FrontPanel - ../../HdmiCecSink + ../../HdmiCecSink ../../RDKShell ../../MaintenanceManager ../../Packager @@ -177,7 +177,6 @@ target_link_libraries(${PROJECT_NAME} ${NAMESPACE}HdmiCec ${NAMESPACE}HdmiCec_2 ${NAMESPACE}HdmiCecSource - ${NAMESPACE}XCast ${NAMESPACE}FrontPanel ${NAMESPACE}HdmiCecSink ${NAMESPACE}RDKShell diff --git a/Tests/L1Tests/tests/test_XCast.cpp b/Tests/L1Tests/tests/test_XCast.cpp index 1fb8888e9e..3b0189239b 100755 --- a/Tests/L1Tests/tests/test_XCast.cpp +++ b/Tests/L1Tests/tests/test_XCast.cpp @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#if 0 #include #include "FactoriesImplementation.h" @@ -614,3 +614,4 @@ TEST_F(XCastInitializedEventTest, onApplicationStopRequest) plugin->onXcastApplicationStopRequest("Netflix", "1234"); handler.Unsubscribe(0, _T("onApplicationStopRequest"), _T("client.events"), message); } +#endif diff --git a/l1tests.cmake b/l1tests.cmake index 63654c3c7c..edfacf9d92 100755 --- a/l1tests.cmake +++ b/l1tests.cmake @@ -207,7 +207,6 @@ set(PLUGIN_MOTION_DETECTION ON) set(PLUGIN_COMPOSITEINPUT ON) set(PLUGIN_OCICONTAINER ON) set(HAS_FRONT_PANEL ON) -set(PLUGIN_XCAST ON) set(PLUGIN_HDMICEC ON) set(PLUGIN_HDMICEC2 ON) set(PLUGIN_HDMICECSOURCE ON) From afbc538586e5b10fb9a26c43788b7589347a81dd Mon Sep 17 00:00:00 2001 From: Adrian Muzyka Date: Tue, 22 Oct 2024 12:45:16 +0200 Subject: [PATCH 8/9] RDK-53686 Analytics sysTime validation, generate sessionId and attributes source alignment --- Analytics/Analytics.conf.in | 1 + Analytics/Analytics.config | 1 + Analytics/Analytics.h | 4 - Analytics/AnalyticsJsonRpc.cpp | 45 -- Analytics/CHANGELOG.md | 3 + Analytics/CMakeLists.txt | 11 +- .../AnalyticsImplementation.cpp | 70 +-- .../Implementation/AnalyticsImplementation.h | 12 +- .../Backend/AnalyticsBackend.cpp | 7 +- .../Implementation/Backend/AnalyticsBackend.h | 10 +- .../Backend/Sift/CMakeLists.txt | 5 +- .../Backend/Sift/SiftBackend.cpp | 44 +- .../Implementation/Backend/Sift/SiftBackend.h | 4 +- .../Backend/Sift/SiftConfig.cpp | 133 +++-- .../Implementation/Backend/Sift/SiftConfig.h | 13 +- .../Backend/Sift/SiftUploader.cpp | 13 +- .../Backend/Sift/SiftUploader.h | 4 +- .../Implementation/SystemTime/CMakeLists.txt | 27 + .../Implementation/SystemTime/SystemTime.cpp | 493 ++++++++++++++++++ .../Implementation/SystemTime/SystemTime.h | 99 ++++ .../0001-Add-IAnalytics-interface-R2.patch | 14 +- Tests/L1Tests/tests/test_Analytics.cpp | 14 - 22 files changed, 795 insertions(+), 232 deletions(-) create mode 100644 Analytics/Implementation/SystemTime/CMakeLists.txt create mode 100644 Analytics/Implementation/SystemTime/SystemTime.cpp create mode 100644 Analytics/Implementation/SystemTime/SystemTime.h diff --git a/Analytics/Analytics.conf.in b/Analytics/Analytics.conf.in index 0a6fe352e8..c5c8f738df 100644 --- a/Analytics/Analytics.conf.in +++ b/Analytics/Analytics.conf.in @@ -15,6 +15,7 @@ if boolean("@PLUGIN_ANALYTICS_SIFT_BACKEND_ENABLED@"): sift.add("productname", "@PLUGIN_ANALYTICS_SIFT_PRODUCT_NAME@") sift.add("loggername", "@PLUGIN_ANALYTICS_SIFT_LOGGER_NAME@") sift.add("loggerversion", "@PLUGIN_ANALYTICS_SIFT_LOGGER_VERSION@") + sift.add("platformdefault", "@PLUGIN_ANALYTICS_SIFT_PLATFORM_DEFAULT@") sift.add("maxrandomisationwindowtime", "@PLUGIN_ANALYTICS_SIFT_MAX_RANDOMISATION_WINDOW_TIME@") sift.add("maxeventsinpost", "@PLUGIN_ANALYTICS_SIFT_MAX_EVENTS_IN_POST@") sift.add("maxretries", "@PLUGIN_ANALYTICS_SIFT_MAX_RETRIES@") diff --git a/Analytics/Analytics.config b/Analytics/Analytics.config index 55d1e98150..e525e36a3d 100644 --- a/Analytics/Analytics.config +++ b/Analytics/Analytics.config @@ -20,6 +20,7 @@ if(PLUGIN_ANALYTICS_SIFT_BACKEND_ENABLED) kv(productname ${PLUGIN_ANALYTICS_SIFT_PRODUCT_NAME}) kv(loggername ${PLUGIN_ANALYTICS_SIFT_LOGGER_NAME}) kv(loggerversion ${PLUGIN_ANALYTICS_SIFT_LOGGER_VERSION}) + kv(platformdefault ${PLUGIN_ANALYTICS_SIFT_PLATFORM_DEFAULT}) kv(maxrandomisationwindowtime, ${PLUGIN_ANALYTICS_SIFT_MAX_RANDOMISATION_WINDOW_TIME}) kv(maxeventsinpost, ${PLUGIN_ANALYTICS_SIFT_MAX_EVENTS_IN_POST}) kv(maxretries, ${PLUGIN_ANALYTICS_SIFT_MAX_RETRIES}) diff --git a/Analytics/Analytics.h b/Analytics/Analytics.h index 8b8b1434a3..8baed6a4bd 100644 --- a/Analytics/Analytics.h +++ b/Analytics/Analytics.h @@ -68,8 +68,6 @@ namespace WPEFramework { END_INTERFACE_MAP static const string ANALYTICS_METHOD_SEND_EVENT; - static const string ANALYTICS_METHOD_SET_SESSION_ID; - static const string ANALYTICS_METHOD_SET_TIME_READY; private: void Deactivated(RPC::IRemoteConnection* connection); @@ -78,8 +76,6 @@ namespace WPEFramework { void UnregisterAll(); uint32_t SendEventWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t SetSessionIdWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t SetTimeReadyWrapper(const JsonObject& parameters, JsonObject& response); private: PluginHost::IShell* mService; diff --git a/Analytics/AnalyticsJsonRpc.cpp b/Analytics/AnalyticsJsonRpc.cpp index f5139ec1e5..d3fb127ad0 100644 --- a/Analytics/AnalyticsJsonRpc.cpp +++ b/Analytics/AnalyticsJsonRpc.cpp @@ -21,9 +21,6 @@ #include "UtilsJsonRpc.h" const string WPEFramework::Plugin::Analytics::ANALYTICS_METHOD_SEND_EVENT = "sendEvent"; -// TODO: To be removed once the Analytics is capable of handling it internally -const string WPEFramework::Plugin::Analytics::ANALYTICS_METHOD_SET_SESSION_ID = "setSessionId"; -const string WPEFramework::Plugin::Analytics::ANALYTICS_METHOD_SET_TIME_READY = "setTimeReady"; namespace WPEFramework { @@ -34,15 +31,11 @@ namespace Plugin { void Analytics::RegisterAll() { Register(_T(ANALYTICS_METHOD_SEND_EVENT), &Analytics::SendEventWrapper, this); - Register(_T(ANALYTICS_METHOD_SET_SESSION_ID), &Analytics::SetSessionIdWrapper, this); - Register(_T(ANALYTICS_METHOD_SET_TIME_READY), &Analytics::SetTimeReadyWrapper, this); } void Analytics::UnregisterAll() { Unregister(_T(ANALYTICS_METHOD_SEND_EVENT)); - Unregister(_T(ANALYTICS_METHOD_SET_SESSION_ID)); - Unregister(_T(ANALYTICS_METHOD_SET_TIME_READY)); } // API implementation @@ -93,44 +86,6 @@ namespace Plugin { returnResponse(result == Core::ERROR_NONE); } - // Method: setSessionId - Set the session ID - // Return codes: - // - ERROR_NONE: Success - // - ERROR_GENERAL: Failed to set the session ID - uint32_t Analytics::SetSessionIdWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - uint32_t result = Core::ERROR_NONE; - - returnIfStringParamNotFound(parameters, "sessionId"); - - string sessionId = parameters["sessionId"].String(); - - if (mAnalytics != nullptr) { - result = mAnalytics->SetSessionId(sessionId); - } - - returnResponse(result == Core::ERROR_NONE); - } - - // Method: setTimeReady - Set the time ready - // Return codes: - // - ERROR_NONE: Success - // - ERROR_GENERAL: Failed to set the time ready - uint32_t Analytics::SetTimeReadyWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - uint32_t result = Core::ERROR_NONE; - - if (mAnalytics != nullptr) { - result = mAnalytics->SetTimeReady(); - } - - returnResponse(result == Core::ERROR_NONE); - } - } } \ No newline at end of file diff --git a/Analytics/CHANGELOG.md b/Analytics/CHANGELOG.md index e23241b2ce..053a2bab2b 100644 --- a/Analytics/CHANGELOG.md +++ b/Analytics/CHANGELOG.md @@ -14,6 +14,9 @@ All notable changes to this RDK Service will be documented in this file. For more details, refer to versioning section under Main README. +## [1.0.1] - 2024-10-16 +- Support generation of sessionID, SysTime validation and limit nbr of external attributes for Sift + ## [1.0.0] - 2024-07-25 ### Added - New RDK Service Analytics to handle analytics events and send them to dedicated backends diff --git a/Analytics/CMakeLists.txt b/Analytics/CMakeLists.txt index 247f6200d2..b350bccc2b 100644 --- a/Analytics/CMakeLists.txt +++ b/Analytics/CMakeLists.txt @@ -20,7 +20,7 @@ set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) set(VERSION_MAJOR 1) set(VERSION_MINOR 0) -set(VERSION_PATCH 0) +set(VERSION_PATCH 1) add_compile_definitions(ANALYTICS_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(ANALYTICS_MINOR_VERSION=${VERSION_MINOR}) @@ -42,13 +42,14 @@ set(PLUGIN_ANALYTICS_SIFT_ENV "prod" CACHE STRING "Sift environment") set(PLUGIN_ANALYTICS_SIFT_PRODUCT_NAME "entos" CACHE STRING "Sift product name") #entos-immerse in Sift2.0 set(PLUGIN_ANALYTICS_SIFT_LOGGER_NAME "Analytics" CACHE STRING "Sift logger name") set(PLUGIN_ANALYTICS_SIFT_LOGGER_VERSION "${MODULE_VERSION}" CACHE STRING "Sift logger version") +set(PLUGIN_ANALYTICS_SIFT_PLATFORM_DEFAULT "entos:rdk" CACHE STRING "Sift platform default value") set(PLUGIN_ANALYTICS_SIFT_MAX_RANDOMISATION_WINDOW_TIME 300 CACHE STRING "Sift max randomisation window time of posting queued events") set(PLUGIN_ANALYTICS_SIFT_MAX_EVENTS_IN_POST 10 CACHE STRING "Sift max events in post") set(PLUGIN_ANALYTICS_SIFT_MAX_RETRIES 10 CACHE STRING "Sift max retries posting events") set(PLUGIN_ANALYTICS_SIFT_MIN_RETRY_PERIOD 1 CACHE STRING "Sift min retry period seconds") set(PLUGIN_ANALYTICS_SIFT_MAX_RETRY_PERIOD 30 CACHE STRING "Sift max retry period seconds") set(PLUGIN_ANALYTICS_SIFT_EXPONENTIAL_PERIODIC_FACTOR 2 CACHE STRING "Sift exponential periodic factor") -set(PLUGIN_ANALYTICS_SIFT_STORE_PATH "/opt/persistent/sky/AnalyticsSiftStore" CACHE STRING "Sift store path") +set(PLUGIN_ANALYTICS_SIFT_STORE_PATH "/persistent/AnalyticsSiftStore" CACHE STRING "Sift store path") set(PLUGIN_ANALYTICS_SIFT_STORE_EVENTS_LIMIT 1000 CACHE STRING "Sift store events limit") set(PLUGIN_ANALYTICS_SIFT_URL "" CACHE STRING "Sift URL") @@ -67,8 +68,11 @@ add_library(${MODULE_NAME} SHARED Module.cpp) target_include_directories(${MODULE_NAME} PRIVATE Implementation) +target_include_directories(${MODULE_NAME} PRIVATE Implementation/SystemTime) +target_include_directories(${MODULE_NAME} PRIVATE ../) target_include_directories(${MODULE_NAME} PRIVATE ../helpers) +add_subdirectory(Implementation/SystemTime) add_subdirectory(Implementation/LocalStore) add_subdirectory(Implementation/Backend) @@ -85,7 +89,8 @@ target_link_libraries(${MODULE_NAME} ${NAMESPACE}Definitions::${NAMESPACE}Definitions ${DS_LIBRARIES} ${IARMBUS_LIBRARIES} - ${MODULE_NAME}Backends) + ${MODULE_NAME}Backends + ${MODULE_NAME}SystemTime) install(TARGETS ${MODULE_NAME} DESTINATION lib/${STORAGE_DIRECTORY}/plugins) diff --git a/Analytics/Implementation/AnalyticsImplementation.cpp b/Analytics/Implementation/AnalyticsImplementation.cpp index 4a2d2e211c..2f4c03829f 100644 --- a/Analytics/Implementation/AnalyticsImplementation.cpp +++ b/Analytics/Implementation/AnalyticsImplementation.cpp @@ -19,6 +19,7 @@ #include "AnalyticsImplementation.h" #include "Backend/AnalyticsBackend.h" #include "UtilsLogging.h" +#include "SystemTime.h" #include #include @@ -36,7 +37,7 @@ namespace Plugin { mQueueCondition(), mActionQueue(), mEventQueue(), - mBackends(IAnalyticsBackendAdministrator::Instances()), + mBackends(IAnalyticsBackendAdministrator::Create()), mSysTimeValid(false), mShell(nullptr) { @@ -45,6 +46,7 @@ namespace Plugin { AnalyticsImplementation::~AnalyticsImplementation() { + LOGINFO("AnalyticsImplementation::~AnalyticsImplementation()"); std::unique_lock lock(mQueueMutex); mActionQueue.push({ACTION_TYPE_SHUTDOWN, nullptr}); lock.unlock(); @@ -52,13 +54,13 @@ namespace Plugin { mThread.join(); } - /* virtual */ uint32_t AnalyticsImplementation::SendEvent(const string& eventName, + /* virtual */ Core::hresult AnalyticsImplementation::SendEvent(const string& eventName, const string& eventVersion, const string& eventSource, const string& eventSourceVersion, - RPC::IStringIterator* const& cetList, - const uint64_t& epochTimestamp, - const uint64_t& uptimeTimestamp, + IStringIterator* const& cetList, + const uint64_t epochTimestamp, + const uint64_t uptimeTimestamp, const string& eventPayload) { std::shared_ptr event = std::make_shared(); @@ -98,28 +100,6 @@ namespace Plugin { return Core::ERROR_NONE; } - uint32_t AnalyticsImplementation::SetSessionId(const string& id) - { - uint32_t ret = Core::ERROR_GENERAL; - // set session id in sift backend - if (mBackends.find(IAnalyticsBackend::SIFT) != mBackends.end()) - { - ret = mBackends.at(IAnalyticsBackend::SIFT).SetSessionId(id); - } - - return ret; - } - - uint32_t AnalyticsImplementation::SetTimeReady() - { - // set time ready action - std::unique_lock lock(mQueueMutex); - mActionQueue.push({ACTION_TYPE_SET_TIME_READY, nullptr}); - lock.unlock(); - mQueueCondition.notify_one(); - return Core::ERROR_NONE; - } - uint32_t AnalyticsImplementation::Configure(PluginHost::IShell* shell) { LOGINFO("Configuring Analytics"); @@ -127,10 +107,16 @@ namespace Plugin { ASSERT(shell != nullptr); mShell = shell; + mSysTime = std::make_shared(shell); + if(mSysTime == nullptr) + { + LOGERR("Failed to create SystemTime instance"); + } + for (auto &backend : mBackends) { LOGINFO("Configuring backend: %s", backend.first.c_str()); - backend.second.Configure(shell); + backend.second->Configure(shell, mSysTime); } return result; @@ -177,7 +163,7 @@ namespace Plugin { switch (action.type) { case ACTION_POPULATE_TIME_INFO: - //mSysTimeValid = IsSysTimeValid(); + mSysTimeValid = IsSysTimeValid(); if ( mSysTimeValid ) { @@ -225,24 +211,8 @@ namespace Plugin { } break; case ACTION_TYPE_SHUTDOWN: + LOGINFO("Shutting down Analytics"); return; - case ACTION_TYPE_SET_TIME_READY: - { - mSysTimeValid = true; - // Send the events from the queue, if there are any. - while ( !mEventQueue.empty() ) - { - AnalyticsImplementation::Event event = mEventQueue.front(); - // convert uptime to epoch timestamp - if (event.epochTimestamp == 0) - { - event.epochTimestamp = ConvertUptimeToTimestampInMs(event.uptimeTimestamp); - } - - SendEventToBackend( event ); - mEventQueue.pop(); - } - }break; default: break; } @@ -254,8 +224,10 @@ namespace Plugin { bool AnalyticsImplementation::IsSysTimeValid() { bool ret = false; - //TODO: Add system time validationm - // For now, relay on setTimeReady call + if (mSysTime != nullptr) + { + ret = mSysTime->IsSystemTimeAvailable(); + } return ret; } @@ -279,7 +251,7 @@ namespace Plugin { else if (mBackends.find(IAnalyticsBackend::SIFT) != mBackends.end()) { LOGINFO("Sending event to Sift backend: %s", event.eventName.c_str()); - mBackends.at(IAnalyticsBackend::SIFT).SendEvent(backendEvent); + mBackends.at(IAnalyticsBackend::SIFT)->SendEvent(backendEvent); } } diff --git a/Analytics/Implementation/AnalyticsImplementation.h b/Analytics/Implementation/AnalyticsImplementation.h index 2dc6f98377..1a1255bfbd 100644 --- a/Analytics/Implementation/AnalyticsImplementation.h +++ b/Analytics/Implementation/AnalyticsImplementation.h @@ -22,6 +22,7 @@ #include #include #include "Backend/AnalyticsBackend.h" +#include "SystemTime.h" #include #include @@ -76,16 +77,14 @@ namespace Plugin { // IAnalyticsImplementation interface - uint32_t SendEvent(const string& eventName, + Core::hresult SendEvent(const string& eventName, const string& eventVersion, const string& eventSource, const string& eventSourceVersion, - RPC::IStringIterator* const& cetList, - const uint64_t& epochTimestamp, - const uint64_t& uptimeTimestamp, + IStringIterator* const& cetList, + const uint64_t epochTimestamp, + const uint64_t uptimeTimestamp, const string& eventPayload) override; - uint32_t SetSessionId(const string& id) override; - uint32_t SetTimeReady() override; // IConfiguration interface @@ -107,6 +106,7 @@ namespace Plugin { const IAnalyticsBackends mBackends; bool mSysTimeValid; PluginHost::IShell* mShell; + SystemTimePtr mSysTime; }; } } \ No newline at end of file diff --git a/Analytics/Implementation/Backend/AnalyticsBackend.cpp b/Analytics/Implementation/Backend/AnalyticsBackend.cpp index 9e43324792..ea3520801d 100644 --- a/Analytics/Implementation/Backend/AnalyticsBackend.cpp +++ b/Analytics/Implementation/Backend/AnalyticsBackend.cpp @@ -27,12 +27,11 @@ namespace Plugin { const std::string IAnalyticsBackend::SIFT = "Sift"; -IAnalyticsBackends& IAnalyticsBackendAdministrator::Instances() +IAnalyticsBackends IAnalyticsBackendAdministrator::Create() { - static SiftBackend siftBackend; - static IAnalyticsBackends backendInstances = { + IAnalyticsBackends backendInstances = { #ifdef ANALYTICS_SIFT_BACKEND - {IAnalyticsBackend::SIFT, siftBackend}, + {IAnalyticsBackend::SIFT, std::make_shared()}, #endif }; return (backendInstances); diff --git a/Analytics/Implementation/Backend/AnalyticsBackend.h b/Analytics/Implementation/Backend/AnalyticsBackend.h index 5ee93b37b7..4330e58d34 100644 --- a/Analytics/Implementation/Backend/AnalyticsBackend.h +++ b/Analytics/Implementation/Backend/AnalyticsBackend.h @@ -21,6 +21,7 @@ #include #include #include "../../Module.h" +#include "../SystemTime/SystemTime.h" // Interface for Analytics Backedn namespace WPEFramework { @@ -42,15 +43,16 @@ namespace Plugin { const static std::string SIFT; - virtual uint32_t Configure(PluginHost::IShell* shell) = 0; + virtual uint32_t Configure(PluginHost::IShell* shell, SystemTimePtr sysTime) = 0; virtual uint32_t SendEvent(const Event& event) = 0; - virtual uint32_t SetSessionId(const std::string& sessionId) = 0; }; - typedef std::map IAnalyticsBackends; + typedef std::shared_ptr IAnalyticsBackendPtr; + + typedef std::map IAnalyticsBackends; struct IAnalyticsBackendAdministrator { - static IAnalyticsBackends& Instances(); + static IAnalyticsBackends Create(); virtual ~IAnalyticsBackendAdministrator() = default; }; diff --git a/Analytics/Implementation/Backend/Sift/CMakeLists.txt b/Analytics/Implementation/Backend/Sift/CMakeLists.txt index 5c7992fc32..8ebc4a350d 100644 --- a/Analytics/Implementation/Backend/Sift/CMakeLists.txt +++ b/Analytics/Implementation/Backend/Sift/CMakeLists.txt @@ -32,6 +32,9 @@ endif (CURL_FOUND) target_include_directories(${TARGET_LIB} PUBLIC "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(${TARGET_LIB} PRIVATE ../../../../helpers) target_include_directories(${TARGET_LIB} PRIVATE ../../LocalStore) +target_include_directories(${TARGET_LIB} PRIVATE ../../SystemTime) set_property(TARGET ${TARGET_LIB} PROPERTY POSITION_INDEPENDENT_CODE ON) set_target_properties(${TARGET_LIB} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) -target_link_libraries(${TARGET_LIB} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${NAMESPACE}${PLUGIN_NAME}LocalStore) \ No newline at end of file +target_link_libraries(${TARGET_LIB} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +target_link_libraries(${TARGET_LIB} PRIVATE ${NAMESPACE}${PLUGIN_NAME}LocalStore) +target_link_libraries(${TARGET_LIB} PRIVATE ${NAMESPACE}${PLUGIN_NAME}SystemTime) \ No newline at end of file diff --git a/Analytics/Implementation/Backend/Sift/SiftBackend.cpp b/Analytics/Implementation/Backend/Sift/SiftBackend.cpp index 5a028fb74a..6ffb80536b 100644 --- a/Analytics/Implementation/Backend/Sift/SiftBackend.cpp +++ b/Analytics/Implementation/Backend/Sift/SiftBackend.cpp @@ -40,12 +40,14 @@ namespace WPEFramework , mConfigPtr(nullptr) , mStorePtr(nullptr) , mUploaderPtr(nullptr) + , mSessionId() { mThread = std::thread(&SiftBackend::ActionLoop, this); } SiftBackend::~SiftBackend() { + LOGINFO("SiftBackend::~SiftBackend"); Action action = {ACTION_TYPE_SHUTDOWN, nullptr}; { std::lock_guard lock(mQueueMutex); @@ -55,12 +57,12 @@ namespace WPEFramework mThread.join(); } - /* virtual */ uint32_t SiftBackend::Configure(PluginHost::IShell *shell) + /* virtual */ uint32_t SiftBackend::Configure(PluginHost::IShell *shell, SystemTimePtr sysTime) { ASSERT(shell != nullptr); std::unique_lock lock(mQueueMutex); mShell = shell; - mConfigPtr = std::unique_ptr(new SiftConfig(shell)); + mConfigPtr = std::unique_ptr(new SiftConfig(shell, sysTime)); return Core::ERROR_NONE; } @@ -76,17 +78,6 @@ namespace WPEFramework return Core::ERROR_NONE; } - /* virtual */ uint32_t SiftBackend::SetSessionId(const std::string &sessionId) - { - std::unique_lock lock(mQueueMutex); - if (mConfigPtr != nullptr) - { - mConfigPtr->SetSessionId(sessionId); - return Core::ERROR_NONE; - } - return Core::ERROR_GENERAL; - } - void SiftBackend::ActionLoop() { std::unique_lock lock(mQueueMutex); @@ -153,7 +144,6 @@ namespace WPEFramework { mUploaderPtr = std::unique_ptr(new SiftUploader(mStorePtr, uploaderConfig.url, - uploaderConfig.apiKey, uploaderConfig.maxRandomisationWindowTime, uploaderConfig.maxEventsInPost, uploaderConfig.maxRetries, @@ -172,9 +162,9 @@ namespace WPEFramework configValid = true; // For Sift 1.0 update uploader with auth values if avaliable // So they will be added to the events if missing - if (!attributes.schema2Enabled && !attributes.accountId.empty() && !attributes.deviceId.empty() && !attributes.partnerId.empty()) + if (!attributes.schema2Enabled && !attributes.xboAccountId.empty() && !attributes.xboDeviceId.empty() && !attributes.partnerId.empty()) { - mUploaderPtr->setDeviceInfoRequiredFields(attributes.accountId, attributes.deviceId, attributes.partnerId); + mUploaderPtr->setDeviceInfoRequiredFields(attributes.xboAccountId, attributes.xboDeviceId, attributes.partnerId); } } else @@ -212,6 +202,7 @@ namespace WPEFramework } break; case ACTION_TYPE_SHUTDOWN: + LOGINFO("Shutting down SiftBackend"); return; default: break; @@ -223,6 +214,11 @@ namespace WPEFramework bool SiftBackend::SendEventInternal(const Event &event, const SiftConfig::Attributes &attributes) { + if (mSessionId.empty()) + { + mSessionId = GenerateRandomUUID(); + } + JsonObject eventJson = JsonObject(); if (attributes.schema2Enabled) { @@ -260,13 +256,13 @@ namespace WPEFramework } eventJson["device_model"] = attributes.deviceModel; eventJson["device_type"] = attributes.deviceType; - eventJson["device_timezone"] = std::stoi(attributes.deviceTimeZone); + eventJson["device_timezone"] = attributes.deviceTimeZone; eventJson["device_os_name"] = attributes.deviceOsName; eventJson["device_os_version"] = attributes.deviceOsVersion; eventJson["platform"] = attributes.platform; eventJson["device_manufacturer"] = attributes.deviceManufacturer; eventJson["authenticated"] = attributes.authenticated; - eventJson["session_id"] = attributes.sessionId; + eventJson["session_id"] = mSessionId; eventJson["proposition"] = attributes.proposition; if (!attributes.retailer.empty()) { @@ -318,13 +314,13 @@ namespace WPEFramework eventJson["event_name"] = event.eventName; eventJson["event_schema"] = attributes.productName + "/" + event.eventName + "/" + event.eventVersion; eventJson["event_payload"] = JsonObject(event.eventPayload); - eventJson["session_id"] = attributes.sessionId; + eventJson["session_id"] = mSessionId; eventJson["event_id"] = GenerateRandomUUID(); - if (!attributes.accountId.empty() && !attributes.deviceId.empty() && !attributes.partnerId.empty()) + if (!attributes.xboAccountId.empty() && !attributes.xboDeviceId.empty() && !attributes.partnerId.empty()) { - eventJson["account_id"] = attributes.accountId; - eventJson["device_id"] = attributes.deviceId; + eventJson["account_id"] = attributes.xboAccountId; + eventJson["device_id"] = attributes.xboDeviceId; eventJson["partner_id"] = attributes.partnerId; } else @@ -335,9 +331,9 @@ namespace WPEFramework eventJson["app_name"] = attributes.deviceAppName; eventJson["app_ver"] = attributes.deviceAppVersion; eventJson["device_model"] = attributes.deviceModel; - eventJson["device_timezone"] = std::stoi(attributes.deviceTimeZone); + eventJson["device_timezone"] = attributes.deviceTimeZone; eventJson["platform"] = attributes.platform; - eventJson["os_ver"] = attributes.deviceSoftwareVersion; + eventJson["os_ver"] = attributes.deviceOsVersion; eventJson["device_language"] = ""; // Empty for now eventJson["timestamp"] = event.epochTimestamp; eventJson["device_type"] = attributes.deviceType; diff --git a/Analytics/Implementation/Backend/Sift/SiftBackend.h b/Analytics/Implementation/Backend/Sift/SiftBackend.h index e7f167a0b4..2057ab6508 100644 --- a/Analytics/Implementation/Backend/Sift/SiftBackend.h +++ b/Analytics/Implementation/Backend/Sift/SiftBackend.h @@ -40,8 +40,7 @@ namespace Plugin { SiftBackend(); ~SiftBackend(); uint32_t SendEvent(const Event& event) override; - uint32_t Configure(PluginHost::IShell* shell) override; - uint32_t SetSessionId(const std::string& sessionId) override; + uint32_t Configure(PluginHost::IShell* shell, SystemTimePtr sysTime) override; private: @@ -83,6 +82,7 @@ namespace Plugin { SiftConfigPtr mConfigPtr; SiftStorePtr mStorePtr; SiftUploaderPtr mUploaderPtr; + std::string mSessionId; }; } diff --git a/Analytics/Implementation/Backend/Sift/SiftConfig.cpp b/Analytics/Implementation/Backend/Sift/SiftConfig.cpp index ab8f23de51..71abc1ff52 100644 --- a/Analytics/Implementation/Backend/Sift/SiftConfig.cpp +++ b/Analytics/Implementation/Backend/Sift/SiftConfig.cpp @@ -55,6 +55,7 @@ namespace WPEFramework , ProductName() , LoggerName() , LoggerVersion() + , PlatformDfl("entos:rdk") , MaxRandomisationWindowTime(300) , MaxEventsInPost(10) , MaxRetries(10) @@ -72,6 +73,7 @@ namespace WPEFramework Add(_T("productname"), &ProductName); Add(_T("loggername"), &LoggerName); Add(_T("loggerversion"), &LoggerVersion); + Add(_T("platformdefalut"), &PlatformDfl); Add(_T("maxrandomisationwindowtime"), &MaxRandomisationWindowTime); Add(_T("maxeventsinpost"), &MaxEventsInPost); Add(_T("maxretries"), &MaxRetries); @@ -91,6 +93,7 @@ namespace WPEFramework Core::JSON::String ProductName; Core::JSON::String LoggerName; Core::JSON::String LoggerVersion; + Core::JSON::String PlatformDfl; Core::JSON::DecUInt32 MaxRandomisationWindowTime; Core::JSON::DecUInt32 MaxEventsInPost; Core::JSON::DecUInt32 MaxRetries; @@ -303,13 +306,14 @@ namespace WPEFramework } }; - SiftConfig::SiftConfig(PluginHost::IShell *shell) : mInitializationThread(), + SiftConfig::SiftConfig(PluginHost::IShell *shell, SystemTimePtr systemTime) : mInitializationThread(), mMonitorKeys(), mMutex(), mAttributes(), mStoreConfig(), mUploaderConfig(), - mShell(shell) + mShell(shell), + mSystemTime(systemTime) { ASSERT(shell != nullptr); ParsePluginConfig(); @@ -319,6 +323,7 @@ namespace WPEFramework SiftConfig::~SiftConfig() { + LOGINFO("SiftConfig::~SiftConfig"); mInitializationThread.join(); // Unregister for notifications auto interface = mShell->QueryInterfaceByCallsign(PERSISTENT_STORE_CALLSIGN); @@ -338,6 +343,7 @@ namespace WPEFramework { // Get latest values from AuthService GetAuthServiceValues(); + bool timeZoneValid = GetTimeZone(); mMutex.lock(); @@ -349,8 +355,10 @@ namespace WPEFramework bool activatedValid = mAttributes.activated ? (!mAttributes.xboDeviceId.empty() && !mAttributes.xboAccountId.empty()) : true; - valid = (!mAttributes.sessionId.empty() - && !mAttributes.commonSchema.empty() + // Sift2.0 platform equals proposition + mAttributes.platform = mAttributes.proposition; + + valid = (!mAttributes.commonSchema.empty() && !mAttributes.productName.empty() && !mAttributes.productVersion.empty() && !mAttributes.loggerName.empty() @@ -359,15 +367,14 @@ namespace WPEFramework && activatedValid && !mAttributes.deviceModel.empty() && !mAttributes.deviceType.empty() - && !mAttributes.deviceTimeZone.empty() && !mAttributes.deviceOsName.empty() && !mAttributes.deviceOsVersion.empty() && !mAttributes.platform.empty() && !mAttributes.deviceManufacturer.empty() - && !mAttributes.sessionId.empty() && !mAttributes.proposition.empty() && !mAttributes.deviceSerialNumber.empty() - && !mAttributes.deviceMacAddress.empty()); + && !mAttributes.deviceMacAddress.empty() + && timeZoneValid); LOGINFO(" commonSchema: %s," " productName: %s," @@ -378,15 +385,14 @@ namespace WPEFramework " activatedValid %d," " deviceModel: %s," " deviceType: %s," - " deviceTimeZone: %s," " deviceOsName: %s," " deviceOsVersion: %s," " platform: %s," " deviceManufacturer: %s," - " sessionId: %s," " proposition: %s," " deviceSerialNumber: %s," - " deviceMacAddress: %s,", + " deviceMacAddress: %s," + " timeZoneValid: %d", mAttributes.commonSchema.c_str(), mAttributes.productName.c_str(), mAttributes.productVersion.c_str(), @@ -396,15 +402,14 @@ namespace WPEFramework activatedValid, mAttributes.deviceModel.c_str(), mAttributes.deviceType.c_str(), - mAttributes.deviceTimeZone.c_str(), mAttributes.deviceOsName.c_str(), mAttributes.deviceOsVersion.c_str(), mAttributes.platform.c_str(), mAttributes.deviceManufacturer.c_str(), - mAttributes.sessionId.c_str(), mAttributes.proposition.c_str(), mAttributes.deviceSerialNumber.c_str(), - mAttributes.deviceMacAddress.c_str()); + mAttributes.deviceMacAddress.c_str(), + timeZoneValid); if (valid) { @@ -420,24 +425,25 @@ namespace WPEFramework } else //Sift 1.0 required attributes { - valid = (!mAttributes.sessionId.empty() - && !mAttributes.productName.empty() + + valid = (!mAttributes.productName.empty() && !mAttributes.deviceAppName.empty() && !mAttributes.deviceAppVersion.empty() && !mAttributes.deviceModel.empty() - && !mAttributes.deviceTimeZone.empty() && !mAttributes.platform.empty() - && !mAttributes.deviceSoftwareVersion.empty() - && !mAttributes.deviceType.empty()); + && !mAttributes.deviceOsVersion.empty() + && !mAttributes.deviceType.empty() + && timeZoneValid); - LOGINFO("%s, %s, %s, %s, %s, %s, %s", + LOGINFO("%s, %s, %s, %s, %s, %s, %s, %d", mAttributes.productName.c_str(), mAttributes.deviceAppName.c_str(), mAttributes.deviceAppVersion.c_str(), mAttributes.deviceModel.c_str(), mAttributes.platform.c_str(), - mAttributes.deviceSoftwareVersion.c_str(), - mAttributes.deviceType.c_str()); + mAttributes.deviceOsVersion.c_str(), + mAttributes.deviceType.c_str(), + timeZoneValid); } if (valid) @@ -464,8 +470,7 @@ namespace WPEFramework bool SiftConfig::GetUploaderConfig(UploaderConfig &config) { mMutex.lock(); - bool valid = !mUploaderConfig.url.empty() - && !mUploaderConfig.apiKey.empty(); + bool valid = !mUploaderConfig.url.empty(); if (valid) { config = mUploaderConfig; @@ -474,13 +479,6 @@ namespace WPEFramework return valid; } - void SiftConfig::SetSessionId(const std::string &sessionId) - { - mMutex.lock(); - mAttributes.sessionId = sessionId; - mMutex.unlock(); - } - void SiftConfig::TriggerInitialization() { mInitializationThread = std::thread(&SiftConfig::Initialize, this); @@ -489,38 +487,32 @@ namespace WPEFramework void SiftConfig::InitializeKeysMap() { //SIFT 2.0 attributes from persistent storage - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceHardwareModel"] = &mAttributes.deviceModel; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceType"] = &mAttributes.deviceType; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["devicePlatform"] = &mAttributes.platform; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["modelNumber"] = &mAttributes.deviceOsVersion; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["manufacturer"] = &mAttributes.deviceManufacturer; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["serialNumber"] = &mAttributes.deviceSerialNumber; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["macAddress"] = &mAttributes.deviceMacAddress; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["entertainmentOSVersion"] = &mAttributes.productVersion; - mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["proposition"] = &mAttributes.proposition; + //For Sift 1.0 use default values form config + if (mAttributes.schema2Enabled) + { + mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["proposition"] = &mAttributes.proposition; + } mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["retailer"] = &mAttributes.retailer; mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["jvagent"] = &mAttributes.jvAgent; mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["coam"] = &mAttributes.coam; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["country"] = &mAttributes.country;//TODO - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["region"] = &mAttributes.region;//TODO mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["accountType"] = &mAttributes.accountType; mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["operator"] = &mAttributes.accountOperator; mKeysMap[PERSISTENT_STORE_ACCOUNT_PROFILE_NAMESPACE]["detailType"] = &mAttributes.accountDetailType; - //TODO: Values provided by AS but should be provided by RDK - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceTimeZone"] = &mAttributes.deviceTimeZone; - //SIFT 1.0 attributes from persistent storage - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceSoftwareVersion"] = &mAttributes.deviceSoftwareVersion; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceAppName"] = &mAttributes.deviceAppName; mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceAppVersion"] = &mAttributes.deviceAppVersion; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["accountId"] = &mAttributes.accountId; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["deviceId"] = &mAttributes.deviceId; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["partnerId"] = &mAttributes.partnerId; // If Sift url empty, try to get from persistent store - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["sift_url"] = &mUploaderConfig.url; - mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["sift_xapikey"] = &mUploaderConfig.apiKey; + if (mUploaderConfig.url.empty()) + { + mKeysMap[PERSISTENT_STORE_ANALYTICS_NAMESPACE]["sift_url"] = &mUploaderConfig.url; + } } void SiftConfig::ParsePluginConfig() @@ -546,6 +538,10 @@ namespace WPEFramework mAttributes.loggerName = config.Sift.LoggerName.Value(); mAttributes.loggerVersion = config.Sift.LoggerVersion.Value(); mAttributes.deviceOsName = config.DeviceOsName.Value(); + + // Set a default values for platform and proposition if not available in Persistent Store + mAttributes.platform = config.Sift.PlatformDfl.Value(); + mAttributes.proposition = config.Sift.PlatformDfl.Value(); mStoreConfig.path = config.Sift.StorePath.Value(); mStoreConfig.eventsLimit = config.Sift.EventsLimit.Value(); @@ -558,12 +554,13 @@ namespace WPEFramework mUploaderConfig.maxRetryPeriod = config.Sift.MaxRetryPeriod.Value(); mUploaderConfig.exponentialPeriodicFactor = config.Sift.ExponentialPeriodicFactor.Value(); - SYSLOG(Logging::Startup, (_T("Parsed Analytics config: '%s', '%s', '%s', '%s', '%s', '%s'."), + SYSLOG(Logging::Startup, (_T("Parsed Analytics config: '%s', '%s', '%s', '%s', '%s', '%s', '%s'."), mAttributes.commonSchema.c_str(), mAttributes.env.c_str(), mAttributes.productName.c_str(), mAttributes.loggerName.c_str(), mAttributes.loggerVersion.c_str(), + mAttributes.platform.c_str(), mAttributes.deviceOsName.c_str() )); } @@ -607,8 +604,6 @@ namespace WPEFramework { ActivatePlugin(mShell, AUTHSERVICE_CALLSIGN); } - - GetAuthServiceValues(); //Activate System plugin if needed if (IsPluginActivated(mShell, SYSTEM_CALLSIGN) == false) @@ -635,6 +630,22 @@ namespace WPEFramework LOGINFO("Got env %s", mAttributes.env.c_str()); } + if (result == Core::ERROR_NONE && response.HasLabel("estb_mac")) + { + mMutex.lock(); + mAttributes.deviceMacAddress = response["estb_mac"].String(); + mMutex.unlock(); + LOGINFO("Got deviceMacAddress %s", mAttributes.deviceMacAddress.c_str()); + } + + if (result == Core::ERROR_NONE && response.HasLabel("model_number")) + { + mMutex.lock(); + mAttributes.deviceModel = response["model_number"].String(); + mMutex.unlock(); + LOGINFO("Got deviceModel %s", mAttributes.deviceModel.c_str()); + } + // Get deviceFriendlyName from System.1.getFriendlyName[friendlyName] result = systemLink->Invoke(JSONRPC_THUNDER_TIMEOUT, "getFriendlyName", params, response); if (result == Core::ERROR_NONE && response.HasLabel("friendlyName")) @@ -766,8 +777,8 @@ namespace WPEFramework { mMutex.lock(); mAttributes.xboAccountId = response["serviceAccountId"].String(); - mMutex.unlock(); LOGINFO("Got xboAccountId %s", mAttributes.xboAccountId.c_str()); + mMutex.unlock(); } // get xboDeviceId from AuthService.getXDeviceId @@ -776,8 +787,8 @@ namespace WPEFramework { mMutex.lock(); mAttributes.xboDeviceId = response["xDeviceId"].String(); - mMutex.unlock(); LOGINFO("Got xboDeviceId %s", mAttributes.xboDeviceId.c_str()); + mMutex.unlock(); } mMutex.lock(); @@ -792,6 +803,28 @@ namespace WPEFramework } } + bool SiftConfig::GetTimeZone() + { + int32_t timeZoneOffsetSec = 0; + SystemTime::TimeZoneAccuracy accuracy = SystemTime::TimeZoneAccuracy::ACC_UNDEFINED; + + if (mSystemTime != nullptr && mSystemTime->IsSystemTimeAvailable()) + { + accuracy = mSystemTime->GetTimeZoneOffset(timeZoneOffsetSec); + mMutex.lock(); + mAttributes.deviceTimeZone = timeZoneOffsetSec * 1000; + LOGINFO("Got deviceTimeZone %d, accuracy %d", mAttributes.deviceTimeZone, accuracy); + mMutex.unlock(); + } + + if (accuracy == SystemTime::TimeZoneAccuracy::FINAL) + { + return true; + } + + return false; + } + void SiftConfig::ActivatePlugin(PluginHost::IShell *shell, const char *callSign) { JsonObject joParams; diff --git a/Analytics/Implementation/Backend/Sift/SiftConfig.h b/Analytics/Implementation/Backend/Sift/SiftConfig.h index 09032dddc2..46aa0c9635 100644 --- a/Analytics/Implementation/Backend/Sift/SiftConfig.h +++ b/Analytics/Implementation/Backend/Sift/SiftConfig.h @@ -19,6 +19,7 @@ #pragma once #include "../../../Module.h" +#include "../../SystemTime/SystemTime.h" #include #include #include @@ -47,13 +48,12 @@ namespace WPEFramework bool activated; std::string deviceModel; std::string deviceType; - std::string deviceTimeZone; + int32_t deviceTimeZone; std::string deviceOsName; std::string deviceOsVersion; std::string platform; std::string deviceManufacturer; bool authenticated; - std::string sessionId; std::string proposition; std::string retailer; std::string jvAgent; @@ -68,11 +68,8 @@ namespace WPEFramework std::string accountDetailType; // Sift 1.0 atributes that left - std::string deviceSoftwareVersion; std::string deviceAppName; std::string deviceAppVersion; - std::string accountId; - std::string deviceId; }; struct StoreConfig @@ -84,7 +81,6 @@ namespace WPEFramework struct UploaderConfig { std::string url; - std::string apiKey; uint32_t maxRandomisationWindowTime; uint32_t maxEventsInPost; uint32_t maxRetries; @@ -96,13 +92,12 @@ namespace WPEFramework SiftConfig(const SiftConfig &) = delete; SiftConfig &operator=(const SiftConfig &) = delete; - SiftConfig(PluginHost::IShell *shell); + SiftConfig(PluginHost::IShell *shell, SystemTimePtr systemTime); ~SiftConfig(); bool GetAttributes(Attributes &attributes); bool GetStoreConfig(StoreConfig &config); bool GetUploaderConfig(UploaderConfig &config); - void SetSessionId(const std::string &sessionId); private: class MonitorKeys : public Exchange::IStore::INotification { @@ -136,6 +131,7 @@ namespace WPEFramework uint32_t GetValueFromPersistent(const string &ns, const string &key, string &value); void GetAuthServiceValues(); + bool GetTimeZone(); static void ActivatePlugin(PluginHost::IShell *shell, const char *callSign); static bool IsPluginActivated(PluginHost::IShell *shell, const char *callSign); @@ -147,6 +143,7 @@ namespace WPEFramework UploaderConfig mUploaderConfig; PluginHost::IShell *mShell; std::map> mKeysMap; + SystemTimePtr mSystemTime; }; typedef std::unique_ptr SiftConfigPtr; diff --git a/Analytics/Implementation/Backend/Sift/SiftUploader.cpp b/Analytics/Implementation/Backend/Sift/SiftUploader.cpp index e3a839bd7d..814551730e 100644 --- a/Analytics/Implementation/Backend/Sift/SiftUploader.cpp +++ b/Analytics/Implementation/Backend/Sift/SiftUploader.cpp @@ -31,7 +31,6 @@ namespace WPEFramework { SiftUploader::SiftUploader(SiftStorePtr storePtr, const std::string &url, - const std::string &apiKey, const uint32_t &maxRandomisationWindowTime, const uint32_t &maxEventsInPost, const uint32_t &maxRetries, @@ -40,7 +39,6 @@ namespace WPEFramework const uint32_t &exponentialPeriodicFactor) : mStorePtr(storePtr) , mUrl(url) - , mApiKey(apiKey) , mMaxRandomisationWindowTime(maxRandomisationWindowTime) , mMaxEventsInPost(maxEventsInPost) , mMaxRetries(maxRetries) @@ -57,6 +55,7 @@ namespace WPEFramework SiftUploader::~SiftUploader() { + LOGINFO("SiftUploader::~SiftUploader"); { std::lock_guard lock(mMutex); mStop = true; @@ -88,7 +87,7 @@ namespace WPEFramework [this] () { return mStop; } ); if (mStop) { - LOGINFO("SiftUploader exit"); + LOGINFO("SiftUploader Run exit"); return; } @@ -142,7 +141,7 @@ namespace WPEFramework do { - respcode = PostJson(mUrl, mApiKey, jsonEventPayload, resp); + respcode = PostJson(mUrl, jsonEventPayload, resp); } while ((respcode != 200) && (respcode != 400) && PerformWaitIfRetryNeeded()); if ((respcode == 200) || (respcode == 400)) @@ -375,13 +374,13 @@ namespace WPEFramework return size * nmemb; } - uint32_t SiftUploader::PostJson(const std::string &url, const std::string &apiKey, const std::string &json, std::string &response) + uint32_t SiftUploader::PostJson(const std::string &url, const std::string &json, std::string &response) { CURL *curl; CURLcode res; uint32_t retHttpCode = 0; - if (url.empty() || apiKey.empty() || json.empty()) + if (url.empty() || json.empty()) { LOGERR("Invalid parameters for postJson"); return retHttpCode; @@ -400,9 +399,7 @@ namespace WPEFramework // Create a linked list of custom headers struct curl_slist *headers = NULL; - std::string keyHeader("X-Api-Key: " + apiKey); headers = curl_slist_append(headers, "Content-Type: application/json"); - headers = curl_slist_append(headers, keyHeader.data()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); diff --git a/Analytics/Implementation/Backend/Sift/SiftUploader.h b/Analytics/Implementation/Backend/Sift/SiftUploader.h index 7da53d549d..a3856394c4 100644 --- a/Analytics/Implementation/Backend/Sift/SiftUploader.h +++ b/Analytics/Implementation/Backend/Sift/SiftUploader.h @@ -38,7 +38,6 @@ namespace WPEFramework SiftUploader(SiftStorePtr storePtr, const std::string &url, - const std::string &apiKey, const uint32_t &maxRandomisationWindowTime, const uint32_t &maxEventsInPost, const uint32_t &maxRetries, @@ -69,11 +68,10 @@ namespace WPEFramework void updateEventDeviceInfoIfRequired(JsonObject &event) const; void validateResponse(const std::string &response, const std::vector &events) const; - static uint32_t PostJson(const std::string& url, const std::string& apiKey, const std::string& json, std::string &response); + static uint32_t PostJson(const std::string& url, const std::string& json, std::string &response); SiftStorePtr mStorePtr; std::string mUrl; - std::string mApiKey; uint32_t mMaxRandomisationWindowTime; uint32_t mMaxEventsInPost; uint32_t mMaxRetries; diff --git a/Analytics/Implementation/SystemTime/CMakeLists.txt b/Analytics/Implementation/SystemTime/CMakeLists.txt new file mode 100644 index 0000000000..23f1e3ad53 --- /dev/null +++ b/Analytics/Implementation/SystemTime/CMakeLists.txt @@ -0,0 +1,27 @@ +# If not stated otherwise in this file or this component's license file the +# following copyright and licenses apply: +# +# Copyright 2020 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +set(TARGET_LIB ${NAMESPACE}${PLUGIN_NAME}SystemTime) + +add_library(${TARGET_LIB} STATIC) + +target_sources(${TARGET_LIB} PRIVATE SystemTime.cpp) + +target_include_directories(${TARGET_LIB} PUBLIC "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(${TARGET_LIB} PRIVATE ../../../helpers) +set_property(TARGET ${TARGET_LIB} PROPERTY POSITION_INDEPENDENT_CODE ON) +set_target_properties(${TARGET_LIB} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) +target_link_libraries(${TARGET_LIB} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) \ No newline at end of file diff --git a/Analytics/Implementation/SystemTime/SystemTime.cpp b/Analytics/Implementation/SystemTime/SystemTime.cpp new file mode 100644 index 0000000000..36aee1d972 --- /dev/null +++ b/Analytics/Implementation/SystemTime/SystemTime.cpp @@ -0,0 +1,493 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#include "SystemTime.h" +#include "UtilsLogging.h" +#include "secure_wrapper.h" + +#define JSONRPC_THUNDER_TIMEOUT 2000 +#define THUNDER_ACCESS_DEFAULT_VALUE "127.0.0.1:9998" +#define SYSTEM_CALLSIGN "org.rdk.System.1" + +namespace WPEFramework +{ + namespace Plugin + { + const std::string TIME_QUALITY_STALE{"Stale"}; + const std::string TIME_QUALITY_GOOD{"Good"}; + const std::string TIME_QUALITY_SECURE{"Secure"}; + + SystemTime::SystemTime(PluginHost::IShell *shell) : mQueueLock(), + mQueueCondition(), + mQueue(), + mLock(), + mSystemLink(nullptr), + mTimeQuality(TIME_QUALITY_STALE), + mTimeZone(), + mTimeZoneAccuracyString(), + mTimeZoneAccuracy(ACC_UNDEFINED), + mTimeZoneOffsetSec(0), + mTransitionMap(), + mIsSystemTimeAvailable(false), + mShell(shell) + { + mEventThread = std::thread(&SystemTime::EventLoop, this); + + Event event = {EVENT_INITIALISE, std::string()}; + std::unique_lock lock(mQueueLock); + mQueue.push(event); + lock.unlock(); + mQueueCondition.notify_one(); + } + + SystemTime::~SystemTime() + { + LOGINFO("SystemTime::~SystemTime"); + Event event = {EVENT_SHUTDOWN, std::string()}; + { + std::lock_guard lock(mQueueLock); + mQueue.push(event); + } + mQueueCondition.notify_one(); + mEventThread.join(); + if (mSystemLink != nullptr) + { + mSystemLink->Unsubscribe(JSONRPC_THUNDER_TIMEOUT, _T("onTimeStatusChanged")); + mSystemLink->Unsubscribe(JSONRPC_THUNDER_TIMEOUT, _T("onTimeZoneDSTChanged")); + } + } + + bool SystemTime::IsSystemTimeAvailable() + { + bool isAvailable = false; + { + std::lock_guard guard(mLock); + isAvailable = mIsSystemTimeAvailable; + } + + if (isAvailable == false && mSystemLink != nullptr) + { + JsonObject params; + JsonObject response; + + uint32_t result = mSystemLink->Invoke(JSONRPC_THUNDER_TIMEOUT, "getTimeStatus", params, response); + if (result == Core::ERROR_NONE && response.HasLabel("TimeQuality")) + { + mTimeQuality = response["TimeQuality"].String(); + if (mTimeQuality == TIME_QUALITY_GOOD || mTimeQuality == TIME_QUALITY_SECURE) + { + std::lock_guard guard(mLock); + mIsSystemTimeAvailable = true; + isAvailable = true; + } + } + } + + LOGINFO("IsSystemTimeAvailable: %d", isAvailable); + return isAvailable; + } + + SystemTime::TimeZoneAccuracy SystemTime::GetTimeZoneOffset(int32_t &offsetSec) + { + SystemTime::TimeZoneAccuracy accuracy = ACC_UNDEFINED; + { + std::lock_guard guard(mLock); + offsetSec = mTimeZoneOffsetSec; + accuracy = mTimeZoneAccuracy; + } + + return accuracy; + } + + void SystemTime::onTimeStatusChanged(const JsonObject& parameters) + { + std::string parametersString; + parameters.ToString(parametersString); + LOGINFO("onTimeStatusChanged: %s", parametersString.c_str()); + Event event = {EVENT_TIME_STATUS_CHANGED, parametersString}; + std::lock_guard lock(mQueueLock); + mQueue.push(event); + mQueueCondition.notify_one(); + } + + void SystemTime::onTimeZoneDSTChanged(const JsonObject& parameters) + { + std::string parametersString; + parameters.ToString(parametersString); + LOGINFO("onTimeZoneDSTChanged: %s", parametersString.c_str()); + Event event = {EVENT_TIME_ZONE_CHANGED, parametersString}; + std::lock_guard lock(mQueueLock); + mQueue.push(event); + mQueueCondition.notify_one(); + } + + void SystemTime::CreateSystemLink() + { + if (mSystemLink == nullptr) + { + std::string thunderAccessValue = THUNDER_ACCESS_DEFAULT_VALUE; + char *thunderAccessValueEnv = getenv("THUNDER_ACCESS_VALUE"); + if (NULL != thunderAccessValueEnv) + { + thunderAccessValue = thunderAccessValueEnv; + } + + // Generate jsonrpc token + std::string token; + // TODO: use interfaces and remove token + auto security = mShell->QueryInterfaceByCallsign("SecurityAgent"); + if (security != nullptr) + { + std::string payload = "http://localhost"; + if (security->CreateToken( + static_cast(payload.length()), + reinterpret_cast(payload.c_str()), + token) == Core::ERROR_NONE) + { + LOGINFO("Got security token\n"); + } + else + { + LOGINFO("Failed to get security token\n"); + } + security->Release(); + } + else + { + LOGINFO("No security agent\n"); + } + + std::string query = "token=" + token; + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(thunderAccessValue))); + mSystemLink = std::make_shared>(SYSTEM_CALLSIGN, "", false, query); + } + } + + void SystemTime::SubscribeForEvents() + { + if (mSystemLink != nullptr) + { + uint32_t ret = mSystemLink->Subscribe(JSONRPC_THUNDER_TIMEOUT, _T("onTimeStatusChanged"), &SystemTime::onTimeStatusChanged, this); + if (ret != Core::ERROR_NONE) + { + LOGERR("Failed to subscribe to onTimeStatusChanged"); + } + + ret = mSystemLink->Subscribe(JSONRPC_THUNDER_TIMEOUT, _T("onTimeZoneDSTChanged"), &SystemTime::onTimeZoneDSTChanged, this); + if (ret != Core::ERROR_NONE) + { + LOGERR("Failed to subscribe to onTimeZoneDSTChanged"); + } + } + } + + void SystemTime::UpdateTimeStatus() + { + JsonObject params; + JsonObject response; + + uint32_t result = mSystemLink->Invoke(JSONRPC_THUNDER_TIMEOUT, "getTimeStatus", params, response); + if (result == Core::ERROR_NONE && response.HasLabel("TimeQuality")) + { + std::lock_guard guard(mLock); + mTimeQuality = response["TimeQuality"].String(); + if (mTimeQuality == TIME_QUALITY_GOOD || mTimeQuality == TIME_QUALITY_SECURE) + { + mIsSystemTimeAvailable = true; + } + else + { + mIsSystemTimeAvailable = false; + } + } + } + + void SystemTime::UpdateTimeZone() + { + JsonObject params; + JsonObject response; + // Get timeZone from System.1.getTimeZoneDST + uint32_t result = mSystemLink->Invoke(JSONRPC_THUNDER_TIMEOUT, "getTimeZoneDST", params, response); + if (result == Core::ERROR_NONE && response.HasLabel("timeZone") && response.HasLabel("accuracy")) + { + std::string tz = response["timeZone"].String(); + std::string accuracy = response["accuracy"].String(); + + std::lock_guard guard(mLock); + if (mTimeZone != tz || mTimeZoneAccuracyString != accuracy) + { + std::pair tzParsed = ParseTimeZone(tz, accuracy); + mTimeZone = tz; + mTimeZoneAccuracyString = accuracy; + mTimeZoneAccuracy = tzParsed.first; + mTimeZoneOffsetSec = tzParsed.second; + } + } + } + + std::pair SystemTime::ParseTimeZone(const string &timeZone, const std::string &accuracy) + { + std::pair result = {ACC_UNDEFINED, 0}; + if (timeZone.empty()) + { + return result; + } + + static const std::map accuracyMap = { + {"INITIAL", INITIAL}, + {"INTERIM", INTERIM}, + {"FINAL", FINAL}}; + + auto accuracyItr = accuracyMap.find(accuracy); + if (accuracyItr == accuracyMap.end()) + { + result.first = ACC_UNDEFINED; + } else { + result.first = accuracyItr->second; + } + + if (timeZone == "Universal") + { + result.second = 0; + LOGINFO("timeZoneOff: %d", result.second); + return result; + } + + PopulateTimeZoneTransitionMap(timeZone, accuracy); + + if (mTransitionMap.empty()) + { + result.first = ACC_UNDEFINED; + return result; + } + + time_t currentTime = time(NULL); + auto currentTimeEndItr = mTransitionMap.lower_bound(currentTime); + + if (currentTimeEndItr != mTransitionMap.end()) + { + result.second = currentTimeEndItr->second; + LOGINFO("timeZoneOff: %d", result.second); + } + else if (mTransitionMap.empty() == false) + { + currentTimeEndItr--; // take the last transition when all transitions are from past + result.second = currentTimeEndItr->second; + LOGINFO("timeZoneOff: %d", result.second); + } + else + { + LOGERR( "There is no time transition information for this timezone: %s", mTimeZone.c_str()); + result.second = 0; + result.first = ACC_UNDEFINED; + } + + return result; + } + + void SystemTime::PopulateTimeZoneTransitionMap(const std::string &newTimeZone, const std::string &accuracy) + { + if (accuracy == "FINAL") + { + if (mTimeZone != newTimeZone) + { + mTransitionMap.clear(); + mTimeZone = newTimeZone; + } + } + else + { + mTimeZone.clear(); + mTransitionMap.clear(); + } + + if (mTransitionMap.empty() && !mTimeZone.empty()) + { + FILE *fp = v_secure_popen("r", "zdump -v %s", mTimeZone.c_str()); + if (fp != NULL) + { + LOGINFO("v_secure_popen of zdump -v %s succeeded", mTimeZone.c_str()); + + // Tue Jan 19 03:14:07 2038 UT = Tue Jan 19 04:14:07 2038 CET isdst=0 gmtoff=3600 + char buf[256] = {0}; + + while (fgets(buf, sizeof(buf), fp) != NULL) + { + // " Tue Jan 19 03:14:07 2038 UT = Tue Jan 19 04:14:07 2038 CET isdst=0 gmtoff=3600" + std::string temp(buf); + struct tm utcTime = {0}; + + temp.erase(0, temp.find(" ") + 2); // Remove " " -> 2 spaces + + auto utOff = temp.find(" UT = "); + std::string date = temp.substr(0, utOff); // Capture UTC date "Tue Jan 19 03:14:07 2038" + + // Remove everything to " UT = ", "Tue Jan 19 04:14:07 2038 CET isdst=0 gmtoff=3600" is left + temp.erase(0, utOff + sizeof(" UT = ") - 1); + + // Remove until next 5 spaces, "CET isdst=0 gmtoff=3600" will be left + auto spaceCount = 5; + while (spaceCount > 0) + { + auto spOff = temp.find(" "); + // In case of one-digit day of month there are two spaces before that + if (spaceCount == 4) + { + // thus + 2 to remove it (it applies also to two-digits but it's ok because it's removed anyway) + temp.erase(0, spOff + 2); + } + else + { + temp.erase(0, spOff + 1); + } + spaceCount--; + } + + char timeZone[5] = {0}; + int32_t isDst = 0; + int32_t gmtOff = 0; + sscanf(temp.c_str(), "%s isdst=%d gmtoff=%d", timeZone, &isDst, &gmtOff); + strptime(date.c_str(), "%A %B %d %H:%M:%S %Y", &utcTime); + + // Years below 70 are not supported by epoch + if (utcTime.tm_year > 70) + { + utcTime.tm_zone = "UTC"; + utcTime.tm_gmtoff = 0; + + // years after 2038 are rounding off to -1 + if (utcTime.tm_year < 138) + { + time_t utcTimeGm = timegm(&utcTime); + mTransitionMap[utcTimeGm] = gmtOff; + } + else + { + break; // stop parsing as we wont add anything after 2038 to map + } + } + else + { + // validate the line + if (utcTime.tm_year > 0) + { + mTransitionMap[utcTime.tm_year] = gmtOff; + } + } + } + + v_secure_pclose(fp); + } + else + { + LOGERR("v_secure_popen of zdump -v %s failed", mTimeZone.c_str()); + } + } + else + { + LOGINFO("No update required"); + } + } + + + void SystemTime::EventLoop() + { + while (true) + { + Event event; + { + std::unique_lock lock(mQueueLock); + mQueueCondition.wait(lock, [this] + { return !mQueue.empty(); }); + event = mQueue.front(); + mQueue.pop(); + } + + switch (event.type) + { + case EVENT_INITIALISE: + { + if (mSystemLink == nullptr) + { + CreateSystemLink(); + if (mSystemLink != nullptr) + { + SubscribeForEvents(); + UpdateTimeStatus(); + UpdateTimeZone(); + } + else + { + LOGERR("Failed to create JSONRPC link with %s", SYSTEM_CALLSIGN); + } + } + } + break; + case EVENT_TIME_STATUS_CHANGED: + { + JsonObject response(event.payload); + if (response.HasLabel("TimeQuality")) + { + std::lock_guard guard(mLock); + mTimeQuality = response["TimeQuality"].String(); + if (mTimeQuality == TIME_QUALITY_GOOD || mTimeQuality == TIME_QUALITY_SECURE) + { + mIsSystemTimeAvailable = true; + } + else + { + mIsSystemTimeAvailable = false; + } + } + } + break; + case EVENT_TIME_ZONE_CHANGED: + { + JsonObject response(event.payload); + if (response.HasLabel("newTimeZone") && response.HasLabel("newAccuracy")) + { + std::string tz = response["newTimeZone"].String(); + std::string accuracy = response["newAccuracy"].String(); + + std::lock_guard guard(mLock); + if (mTimeZone != tz || mTimeZoneAccuracyString != accuracy) + { + std::pair tzParsed = ParseTimeZone(tz, accuracy); + mTimeZone = tz; + mTimeZoneAccuracyString = accuracy; + mTimeZoneAccuracy = tzParsed.first; + mTimeZoneOffsetSec = tzParsed.second; + } + } + } + break; + case EVENT_SHUTDOWN: + { + LOGINFO("Shutting down SystemTime event loop"); + return; + } + default: + { + LOGERR("Unhandled event received, event: %d", event.type); + break; + } + } + } + } + } +} \ No newline at end of file diff --git a/Analytics/Implementation/SystemTime/SystemTime.h b/Analytics/Implementation/SystemTime/SystemTime.h new file mode 100644 index 0000000000..8b4022a411 --- /dev/null +++ b/Analytics/Implementation/SystemTime/SystemTime.h @@ -0,0 +1,99 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "../../Module.h" + +namespace WPEFramework +{ + namespace Plugin + { + class SystemTime + { + public: + enum TimeZoneAccuracy + { + INITIAL, + INTERIM, + FINAL, + ACC_UNDEFINED + }; + + SystemTime(PluginHost::IShell *shell); + ~SystemTime(); + + bool IsSystemTimeAvailable(); + TimeZoneAccuracy GetTimeZoneOffset(int32_t &offsetSec); + + private: + enum EventType + { + EVENT_UNDEF, + EVENT_INITIALISE, + EVENT_TIME_STATUS_CHANGED, + EVENT_TIME_ZONE_CHANGED, + EVENT_SHUTDOWN + }; + + struct Event + { + EventType type; + std::string payload; + }; + + void onTimeStatusChanged(const JsonObject& parameters); + void onTimeZoneDSTChanged(const JsonObject& parameters); + + void CreateSystemLink(); + void SubscribeForEvents(); + void UpdateTimeStatus(); + void UpdateTimeZone(); + std::pair ParseTimeZone(const string &timeZone, const std::string &accuracy); + void PopulateTimeZoneTransitionMap(const std::string &newTimeZone, const std::string &accuracy); + void EventLoop(); + + + std::mutex mQueueLock; + std::condition_variable mQueueCondition; + std::queue mQueue; + + std::thread mEventThread; + std::mutex mLock; + std::shared_ptr> mSystemLink; + std::string mTimeQuality; + std::string mTimeZone; + std::string mTimeZoneAccuracyString; + TimeZoneAccuracy mTimeZoneAccuracy; + int32_t mTimeZoneOffsetSec; + std::map mTransitionMap; + bool mIsSystemTimeAvailable; + PluginHost::IShell *mShell; + }; + + typedef std::shared_ptr SystemTimePtr; + } +} \ No newline at end of file diff --git a/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch b/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch index 8045170a33..413b3b7c1d 100644 --- a/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch +++ b/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch @@ -1,4 +1,4 @@ -From 9a2398b7bc356f341e25c414e45b6919df135d58 Mon Sep 17 00:00:00 2001 +From 326e1f2371147945ec609cfc7f2555625c69611f Mon Sep 17 00:00:00 2001 From: Adrian Muzyka Date: Thu, 19 Sep 2024 12:34:27 +0200 Subject: [PATCH] Add IAnalytics interface R2 @@ -11,7 +11,7 @@ Subject: [PATCH] Add IAnalytics interface R2 diff --git a/interfaces/IAnalytics.h b/interfaces/IAnalytics.h new file mode 100644 -index 0000000..19f5a3a +index 0000000..00fd04e --- /dev/null +++ b/interfaces/IAnalytics.h @@ -0,0 +1,27 @@ @@ -29,16 +29,16 @@ index 0000000..19f5a3a + + virtual ~IAnalytics() override = default; + ++ using IStringIterator = RPC::IIteratorType; ++ + virtual uint32_t SendEvent(const string& eventName /* @in */, + const string& eventVersion /* @in */, + const string& eventSource /* @in */, + const string& eventSourceVersion /* @in */, -+ RPC::IStringIterator* const& cetList /* @in */, -+ const uint64_t& epochTimestamp /* @in */, -+ const uint64_t& uptimeTimestamp /* @in */, ++ IStringIterator* const& cetList /* @in */, ++ const uint64_t epochTimestamp /* @in */, ++ const uint64_t uptimeTimestamp /* @in */, + const string& eventPayload /* @in */ ) = 0; -+ virtual uint32_t SetSessionId(const string& id /* @in */) = 0; -+ virtual uint32_t SetTimeReady() = 0; + }; +} +} diff --git a/Tests/L1Tests/tests/test_Analytics.cpp b/Tests/L1Tests/tests/test_Analytics.cpp index 92a96fbc34..68d6f5eb5a 100644 --- a/Tests/L1Tests/tests/test_Analytics.cpp +++ b/Tests/L1Tests/tests/test_Analytics.cpp @@ -23,8 +23,6 @@ class AnalyticsTest : public ::testing::Test { TEST_F(AnalyticsTest, RegisteredMethods) { EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendEvent"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setSessionId"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setTimeReady"))); } TEST_F(AnalyticsTest, sendEvent) @@ -33,17 +31,5 @@ TEST_F(AnalyticsTest, sendEvent) EXPECT_EQ(response, string("{\"success\":true}")); } -TEST_F(AnalyticsTest, setSessionId) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setSessionId"), _T("{\"sessionId\":\"123456789\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(AnalyticsTest, setTimeReady) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeReady"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - From be3c8eb3d4355d0c3682728828a2620fe70c59a2 Mon Sep 17 00:00:00 2001 From: Adrian Muzyka Date: Mon, 28 Oct 2024 12:46:50 +0100 Subject: [PATCH 9/9] RDK-53686 Analytics JsonRpc uses autogenerated API --- .github/workflows/L1-tests.yml | 4 - .github/workflows/L2-tests-R4-4-1.yml | 3 + Analytics/Analytics.cpp | 28 +++++- Analytics/Analytics.h | 19 +--- Analytics/AnalyticsJsonRpc.cpp | 91 ------------------- Analytics/CMakeLists.txt | 5 - .../AnalyticsImplementation.cpp | 27 ++++++ Tests/L1Tests/CMakeLists.txt | 3 - .../0001-Add-IAnalytics-interface-R2.patch | 59 ------------ Tests/L1Tests/tests/test_Analytics.cpp | 35 ------- .../0001-Add-IAnalytics-interface-R4.4.patch | 74 +++++++++++++++ l1tests.cmake | 2 - 12 files changed, 131 insertions(+), 219 deletions(-) delete mode 100644 Analytics/AnalyticsJsonRpc.cpp delete mode 100644 Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch delete mode 100644 Tests/L1Tests/tests/test_Analytics.cpp create mode 100644 Tests/L2Tests/patches/0001-Add-IAnalytics-interface-R4.4.patch diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 9f00c60f58..33b7aa071e 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -141,8 +141,6 @@ jobs: run: > cd "${{github.workspace}}/ThunderInterfaces" && - git apply "${{github.workspace}}/rdkservices/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch" - && cd .. - name: Build ThunderInterfaces @@ -296,8 +294,6 @@ jobs: -DPLUGIN_TEXTTOSPEECH=ON -DPLUGIN_SYSTEMAUDIOPLAYER=ON -DPLUGIN_MIRACAST=ON - -DPLUGIN_ANALYTICS=ON - -DPLUGIN_ANALYTICS_SIFT_BACKEND=ON -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} && cmake --build build/rdkservices -j8 diff --git a/.github/workflows/L2-tests-R4-4-1.yml b/.github/workflows/L2-tests-R4-4-1.yml index 84f4f8b9ea..50cbaede6c 100755 --- a/.github/workflows/L2-tests-R4-4-1.yml +++ b/.github/workflows/L2-tests-R4-4-1.yml @@ -146,6 +146,7 @@ jobs: patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/RDKV-48604-User-Settings-Thunder-Plugin.patch patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/Use_Legact_Alt_In_ThunderInterfaces_Based_On_ThunderTools_R4.4.3.patch patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/RDK-51362-System-Mode-Thunder-Plugin.patch + patch -p1 < ${{github.workspace}}/rdkservices/Tests/L2Tests/patches/0001-Add-IAnalytics-interface-R4.4.patch cd .. - name: Build ThunderInterfaces @@ -278,6 +279,8 @@ jobs: -DPLUGIN_L2Tests=ON -DRDK_SERVICE_L2_TEST=ON -DDS_FOUND=ON + -DPLUGIN_ANALYTICS=ON + -DPLUGIN_ANALYTICS_SIFT_BACKEND=ON -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} && cmake --build build/rdkservices -j8 diff --git a/Analytics/Analytics.cpp b/Analytics/Analytics.cpp index 03595602d5..dbfa368152 100644 --- a/Analytics/Analytics.cpp +++ b/Analytics/Analytics.cpp @@ -42,13 +42,25 @@ namespace { namespace Plugin { SERVICE_REGISTRATION(Analytics, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + Analytics::Analytics(): mConnectionId(0), mAnalytics(nullptr) + { + SYSLOG(Logging::Startup, (_T("Analytics Constructor"))); + } + + Analytics::~Analytics() + { + SYSLOG(Logging::Shutdown, (string(_T("Analytics Destructor")))); + } + /* virtual */ const string Analytics::Initialize(PluginHost::IShell* service) { ASSERT(service != nullptr); - mService = service; - ASSERT(mAnalytics == nullptr); + SYSLOG(Logging::Startup, (_T("Analytics::Initialize: PID=%u"), getpid())); + + mService = service; + mAnalytics = service->Root(mConnectionId, 2000, _T("AnalyticsImplementation")); ASSERT(mAnalytics != nullptr); @@ -58,7 +70,12 @@ namespace Plugin { configConnection->Configure(service); configConnection->Release(); } - RegisterAll(); + // Invoking Plugin API register to wpeframework + Exchange::JAnalytics::Register(*this, mAnalytics); + } + else + { + SYSLOG(Logging::Startup, (_T("Analytics::Initialize: Failed to initialise Analytics plugin"))); } // On success return empty, to indicate there is no error text. return ((mAnalytics != nullptr)) @@ -68,10 +85,11 @@ namespace Plugin { /* virtual */ void Analytics::Deinitialize(PluginHost::IShell* service) { - TRACE(Trace::Information, (_T("Analytics::Deinitialize"))); + SYSLOG(Logging::Shutdown, (string(_T("Analytics::Deinitialize")))); ASSERT(service == mService); if (mAnalytics != nullptr) { + Exchange::JAnalytics::Unregister(*this); RPC::IRemoteConnection *connection(service->RemoteConnection(mConnectionId)); VARIABLE_IS_NOT_USED uint32_t result = mAnalytics->Release(); @@ -93,12 +111,12 @@ namespace Plugin { connection->Release(); } } + SYSLOG(Logging::Shutdown, (string(_T("Analytics de-initialised")))); } void Analytics::Deactivated(RPC::IRemoteConnection* connection) { if (connection->Id() == mConnectionId) { - TRACE(Trace::Information, (_T("Analytics::Deactivated"))); ASSERT(mService != nullptr); diff --git a/Analytics/Analytics.h b/Analytics/Analytics.h index 8baed6a4bd..3aac8bc167 100644 --- a/Analytics/Analytics.h +++ b/Analytics/Analytics.h @@ -22,6 +22,8 @@ #include "Module.h" #include +#include +#include namespace WPEFramework { @@ -47,16 +49,8 @@ namespace WPEFramework { Analytics& operator=(const Analytics&) = delete; public: - Analytics(): - mConnectionId(0), - mAnalytics(nullptr) - { - RegisterAll(); - } - virtual ~Analytics() - { - UnregisterAll(); - } + Analytics(); + virtual ~Analytics(); virtual const string Initialize(PluginHost::IShell* shell) override; virtual void Deinitialize(PluginHost::IShell* service) override; virtual string Information() const override { return {}; } @@ -71,11 +65,6 @@ namespace WPEFramework { private: void Deactivated(RPC::IRemoteConnection* connection); - // JSONRPC methods - void RegisterAll(); - void UnregisterAll(); - - uint32_t SendEventWrapper(const JsonObject& parameters, JsonObject& response); private: PluginHost::IShell* mService; diff --git a/Analytics/AnalyticsJsonRpc.cpp b/Analytics/AnalyticsJsonRpc.cpp deleted file mode 100644 index d3fb127ad0..0000000000 --- a/Analytics/AnalyticsJsonRpc.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Analytics.h" -#include "UtilsJsonRpc.h" - -const string WPEFramework::Plugin::Analytics::ANALYTICS_METHOD_SEND_EVENT = "sendEvent"; - -namespace WPEFramework { - -namespace Plugin { - // Registration - // - - void Analytics::RegisterAll() - { - Register(_T(ANALYTICS_METHOD_SEND_EVENT), &Analytics::SendEventWrapper, this); - } - - void Analytics::UnregisterAll() - { - Unregister(_T(ANALYTICS_METHOD_SEND_EVENT)); - } - - // API implementation - // - - // Method: sendEvent - Send an event to the analytics server - // Return codes: - // - ERROR_NONE: Success - // - ERROR_GENERAL: Failed to send the event - uint32_t Analytics::SendEventWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - uint32_t result = Core::ERROR_NONE; - - returnIfStringParamNotFound(parameters, "eventName"); - returnIfStringParamNotFound(parameters, "eventSource"); - returnIfStringParamNotFound(parameters, "eventSourceVersion"); - returnIfParamNotFound(parameters, "cetList"); - returnIfParamNotFound(parameters, "eventPayload"); - - string eventName = parameters["eventName"].String(); - string eventVersion = (parameters.HasLabel("eventVersion") ? parameters["eventVersion"].String() : ""); - string eventSource = parameters["eventSource"].String(); - string eventSourceVersion = parameters["eventSourceVersion"].String(); - JsonArray cetListJson = parameters["cetList"].Array(); - std::list cetList; - for (int i=0; i::Create(cetList); - uint64_t epochTimestamp = (parameters.HasLabel("epochTimestamp"))? parameters["epochTimestamp"].Number() : 0; - uint64_t uptimeTimestamp = (parameters.HasLabel("uptimeTimestamp"))? parameters["uptimeTimestamp"].Number() : 0; - string eventPayload = parameters["eventPayload"].String(); - - if (mAnalytics != nullptr) { - result = mAnalytics->SendEvent(eventName, - eventVersion, - eventSource, - eventSourceVersion, - cetListIterator, - epochTimestamp, - uptimeTimestamp, - eventPayload); - } - - cetListIterator->Release(); - returnResponse(result == Core::ERROR_NONE); - } - -} - -} \ No newline at end of file diff --git a/Analytics/CMakeLists.txt b/Analytics/CMakeLists.txt index b350bccc2b..05b1ba12de 100644 --- a/Analytics/CMakeLists.txt +++ b/Analytics/CMakeLists.txt @@ -58,12 +58,9 @@ message("Setup ${MODULE_NAME} v${MODULE_VERSION}") find_package(${NAMESPACE}Plugins REQUIRED) find_package(${NAMESPACE}Definitions REQUIRED) find_package(CompileSettingsDebug CONFIG REQUIRED) -find_package(DS) -find_package(IARMBus) add_library(${MODULE_NAME} SHARED Analytics.cpp - AnalyticsJsonRpc.cpp Implementation/AnalyticsImplementation.cpp Module.cpp) @@ -87,8 +84,6 @@ target_link_libraries(${MODULE_NAME} CompileSettingsDebug::CompileSettingsDebug ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${NAMESPACE}Definitions::${NAMESPACE}Definitions - ${DS_LIBRARIES} - ${IARMBUS_LIBRARIES} ${MODULE_NAME}Backends ${MODULE_NAME}SystemTime) diff --git a/Analytics/Implementation/AnalyticsImplementation.cpp b/Analytics/Implementation/AnalyticsImplementation.cpp index 2f4c03829f..2def66ad2d 100644 --- a/Analytics/Implementation/AnalyticsImplementation.cpp +++ b/Analytics/Implementation/AnalyticsImplementation.cpp @@ -87,6 +87,33 @@ namespace Plugin { LOGINFO("Uptime Timestamp: %" PRIu64, uptimeTimestamp); LOGINFO("Event Payload: %s", eventPayload.c_str()); + bool valid = true; + if (eventName.empty()) + { + LOGERR("eventName is empty"); + valid = false; + } + if (eventSource.empty()) + { + LOGERR("eventSource is empty"); + valid = false; + } + if (eventSourceVersion.empty()) + { + LOGERR("eventSourceVersion is empty"); + valid = false; + } + if (eventPayload.empty()) + { + LOGERR("eventPayload is empty"); + valid = false; + } + + if (valid == false) + { + return Core::ERROR_GENERAL; + } + // Fill the uptime if no time provided if (event->epochTimestamp == 0 && event->uptimeTimestamp == 0) { diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 9d503372c2..8f34225f93 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -102,7 +102,6 @@ include_directories(../../LocationSync ../../Miracast/MiracastService/P2P ../../Miracast/MiracastPlayer ../../Miracast/MiracastPlayer/RTSP - ../../Analytics ) link_directories(../../LocationSync ../../SecurityAgent @@ -142,7 +141,6 @@ link_directories(../../LocationSync ../../TextToSpeech ../../SystemAudioPlayer ../../Miracast - ../../Analytics ) target_link_libraries(${PROJECT_NAME} @@ -187,7 +185,6 @@ target_link_libraries(${PROJECT_NAME} ${NAMESPACE}SystemAudioPlayer ${NAMESPACE}MiracastService ${NAMESPACE}MiracastPlayer - ${NAMESPACE}Analytics ) target_include_directories(${PROJECT_NAME} diff --git a/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch b/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch deleted file mode 100644 index 413b3b7c1d..0000000000 --- a/Tests/L1Tests/patches/0001-Add-IAnalytics-interface-R2.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 326e1f2371147945ec609cfc7f2555625c69611f Mon Sep 17 00:00:00 2001 -From: Adrian Muzyka -Date: Thu, 19 Sep 2024 12:34:27 +0200 -Subject: [PATCH] Add IAnalytics interface R2 - ---- - interfaces/IAnalytics.h | 27 +++++++++++++++++++++++++++ - interfaces/Ids.h | 1 + - 2 files changed, 28 insertions(+) - create mode 100644 interfaces/IAnalytics.h - -diff --git a/interfaces/IAnalytics.h b/interfaces/IAnalytics.h -new file mode 100644 -index 0000000..00fd04e ---- /dev/null -+++ b/interfaces/IAnalytics.h -@@ -0,0 +1,27 @@ -+#pragma once -+ -+#include "Module.h" -+ -+// @stubgen:include -+ -+namespace WPEFramework { -+namespace Exchange { -+ -+ struct EXTERNAL IAnalytics : virtual public Core::IUnknown { -+ enum { ID = ID_ANALYTICS }; -+ -+ virtual ~IAnalytics() override = default; -+ -+ using IStringIterator = RPC::IIteratorType; -+ -+ virtual uint32_t SendEvent(const string& eventName /* @in */, -+ const string& eventVersion /* @in */, -+ const string& eventSource /* @in */, -+ const string& eventSourceVersion /* @in */, -+ IStringIterator* const& cetList /* @in */, -+ const uint64_t epochTimestamp /* @in */, -+ const uint64_t uptimeTimestamp /* @in */, -+ const string& eventPayload /* @in */ ) = 0; -+ }; -+} -+} -diff --git a/interfaces/Ids.h b/interfaces/Ids.h -index 7ef9a42..fa5c1dd 100644 ---- a/interfaces/Ids.h -+++ b/interfaces/Ids.h -@@ -288,6 +288,7 @@ namespace Exchange { - ID_DTV_TRANSPORT, - ID_TEXT_TO_SPEECH, - ID_TEXT_TO_SPEECH_NOTIFICATION, -+ ID_ANALYTICS, - - }; - } --- -2.25.1 - diff --git a/Tests/L1Tests/tests/test_Analytics.cpp b/Tests/L1Tests/tests/test_Analytics.cpp deleted file mode 100644 index 68d6f5eb5a..0000000000 --- a/Tests/L1Tests/tests/test_Analytics.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#include "Analytics.h" - -using namespace WPEFramework; - -class AnalyticsTest : public ::testing::Test { -protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - Core::JSONRPC::Connection connection; - string response; - - AnalyticsTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , connection(1, 0) - { - } - virtual ~AnalyticsTest() = default; -}; - -TEST_F(AnalyticsTest, RegisteredMethods) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendEvent"))); -} - -TEST_F(AnalyticsTest, sendEvent) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendEvent"), _T("{\"eventName\":\"tile_impression\", \"eventVersion\":\"1\", \"eventSource\":\"ImmerseUI\", \"eventSourceVersion\":\"1.2\", \"cetList\":[\"cet1\",\"cet2\",\"cet3\"], \"eventPayload\": { \"event_trigger\": \"user_key_select\"}}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - - - diff --git a/Tests/L2Tests/patches/0001-Add-IAnalytics-interface-R4.4.patch b/Tests/L2Tests/patches/0001-Add-IAnalytics-interface-R4.4.patch new file mode 100644 index 0000000000..faf903a67a --- /dev/null +++ b/Tests/L2Tests/patches/0001-Add-IAnalytics-interface-R4.4.patch @@ -0,0 +1,74 @@ +From 940f48745071ff6036d24a9d40bf7b314852538e Mon Sep 17 00:00:00 2001 +From: Adrian Muzyka +Date: Tue, 29 Oct 2024 07:37:13 +0100 +Subject: [PATCH] Add IAnalytics interface R4.4 + +--- + interfaces/IAnalytics.h | 39 +++++++++++++++++++++++++++++++++++++++ + interfaces/Ids.h | 4 +++- + 2 files changed, 42 insertions(+), 1 deletion(-) + create mode 100644 interfaces/IAnalytics.h + +diff --git a/interfaces/IAnalytics.h b/interfaces/IAnalytics.h +new file mode 100644 +index 0000000..c33d8e0 +--- /dev/null ++++ b/interfaces/IAnalytics.h +@@ -0,0 +1,39 @@ ++#pragma once ++ ++#include "Module.h" ++ ++// @stubgen:include ++ ++namespace WPEFramework { ++namespace Exchange { ++ // @json 1.0.0 ++ struct EXTERNAL IAnalytics : virtual public Core::IUnknown { ++ enum { ID = ID_ANALYTICS }; ++ ++ virtual ~IAnalytics() override = default; ++ ++ using IStringIterator = RPC::IIteratorType; ++ ++ ++ // @alt sendEvent ++ // @brief Send an event to the analytics server ++ // @param eventName: Name of the event ++ // @param eventVersion: Version of the event ++ // @param eventSource: Source of the event ++ // @param eventSourceVersion: Version of the event source ++ // @param cetList: List of CETs ++ // @param epochTimestamp: Epoch timestamp of the event ++ // @param uptimeTimestamp: Uptime timestamp of the event ++ // @param eventPayload: Payload of the event ++ ++ virtual Core::hresult SendEvent(const string& eventName /* @in @text eventName*/, ++ const string& eventVersion /* @in @text eventVersion*/, ++ const string& eventSource /* @in @text eventSource*/, ++ const string& eventSourceVersion /* @in @text eventSourceVersion*/, ++ IStringIterator* const& cetList /* @in @text cetList*/, ++ const uint64_t epochTimestamp /* @in @text epochTimestamp*/, ++ const uint64_t uptimeTimestamp /* @in @text uptimeTimestamp*/, ++ const string& eventPayload /* @in @text eventPayload*/ ) = 0; ++ }; ++} ++} +diff --git a/interfaces/Ids.h b/interfaces/Ids.h +index 7d53320..0296d66 100644 +--- a/interfaces/Ids.h ++++ b/interfaces/Ids.h +@@ -368,7 +368,9 @@ namespace Exchange { + ID_DEVICE_OPTIMIZE_STATE_ACTIVATOR = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x510, + + ID_SYSTEM_MODE = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x520, +- ID_SYSTEM_MODE_NOTIFICATION = ID_SYSTEM_MODE + 1 ++ ID_SYSTEM_MODE_NOTIFICATION = ID_SYSTEM_MODE + 1, ++ ++ ID_ANALYTICS = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x530, + }; + } + } +-- +2.25.1 + diff --git a/l1tests.cmake b/l1tests.cmake index 63654c3c7c..15196b6d46 100755 --- a/l1tests.cmake +++ b/l1tests.cmake @@ -217,5 +217,3 @@ set(PLUGIN_MAINTENANCEMANAGER ON) set(PLUGIN_PACKAGER ON) set(DS_FOUND ON) set(PLUGIN_SYSTEMAUDIOPLAYER ON) -set(PLUGIN_ANALYTICS ON) -set(PLUGIN_ANALYTICS_SIFT_BACKEND ON)