diff options
author | Alexander Kutsan <akutsan@luxoft.com> | 2017-08-10 14:07:07 +0300 |
---|---|---|
committer | Andrey Oleynik <aoleynik@luxoft.com> | 2017-08-16 22:32:33 +0300 |
commit | 06729e8b744374a4d9694f669101b6c554ce42e0 (patch) | |
tree | 7fd73e4e64a831755fa02bbbd8ee8ccfb8f09efd | |
parent | 41fe2979a5f1f8a13428ae4fe88f37ee9824c92e (diff) | |
download | sdl_core-06729e8b744374a4d9694f669101b6c554ce42e0.tar.gz |
Arhitecture changes for support RC plugin
44 files changed, 3914 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a62aed45c..b8fd497a09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ option(ENABLE_GCOV "gcov code coverage feature" OFF) option(ENABLE_SANITIZE "Sanitize tool" OFF) option(ENABLE_SECURITY "Security Ford protocol protection" ON) option(ENABLE_HMI_PTU_DECRYPTION "Policy table update parsed by hmi" ON) -option(ENABLE_EXTENDED_POLICY "Turns extended flow which requires embedded system interaction" ON) +option(REMOTE_CONTROL "Enable Reverse functionality" ON) option(USE_COTIRE "Use Cotire to speed up build (currently only for commands tests)" ON) option(USE_GOLD_LD "Use gold linker intead of GNU linker" ON) option(USE_CCACHE "Turn on ccache usage" ON) @@ -160,6 +160,11 @@ if (OS_TYPE_OPTION) endif() endif() +if (REMOTE_CONTROL) + add_definitions(-DSDL_REMOTE_CONTROL) + message(STATUS "Remote control support is enabled (aka Reverse SDL or SDL-RC)") +endif() + #Jenkins integration section end add_custom_target(pasa-tarball @@ -409,6 +414,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL "QNX") set(RTLIB ) endif() +SET(RPATH_DIRECTORIES + ${CMAKE_INSTALL_PREFIX}/bin/plugins + /usr/local/lib + /usr/local + ${CMAKE_INSTALL_PREFIX}/bin +) +SET(CMAKE_SKIP_BUILD_RPATH FALSE) +SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +SET(CMAKE_INSTALL_RPATH "${RPATH_DIRECTORIES}") +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + + # Building tests if(BUILD_TESTS) enable_testing() diff --git a/src/appMain/CMakeLists.txt b/src/appMain/CMakeLists.txt index cd67dc5f60..64c88bf22f 100644 --- a/src/appMain/CMakeLists.txt +++ b/src/appMain/CMakeLists.txt @@ -44,6 +44,7 @@ endif() include_directories( ${COMPONENTS_DIR}/protocol_handler/include ${COMPONENTS_DIR}/application_manager/include + ${COMPONENTS_DIR}/remote_control/include ${COMPONENTS_DIR}/formatters/include ${COMPONENTS_DIR}/transport_manager/include ${COMPONENTS_DIR}/security_manager/include @@ -56,9 +57,10 @@ include_directories( ${COMPONENTS_DIR}/smart_objects/include ${COMPONENTS_DIR}/media_manager/include ${COMPONENTS_DIR}/telemetry_monitor/include - ${POLICY_PATH}/include/ + ${COMPONENTS_DIR}/functional_module/include + ${POLICY_PATH}/include ${POLICY_GLOBAL_INCLUDE_PATH}/ - ${COMPONENTS_DIR}/rpc_base/include/ + ${COMPONENTS_DIR}/rpc_base/include ${COMPONENTS_DIR}/resumption/include ${COMPONENTS_DIR}/dbus/include ${CMAKE_BINARY_DIR}/src/components @@ -115,6 +117,12 @@ set(LIBRARIES ConfigProfile Resumption ) +if(REMOTE_CONTROL) + SET (LIBRARIES + ${LIBRARIES} + FunctionalModule + ) +endif(REMOTE_CONTROL) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") list(APPEND LIBRARIES pthread) @@ -210,6 +218,18 @@ install( ${CMAKE_SOURCE_DIR}/mycert.pem ${CMAKE_SOURCE_DIR}/mykey.pem DESTINATION bin ) +if (REMOTE_CONTROL) + install( + FILES "${CMAKE_SOURCE_DIR}/src/components/remote_control/remote_sdl_pt.json" + DESTINATION ${CMAKE_BINARY_DIR}/bin + RENAME sdl_preloaded_pt.json + ) +else () + install( + FILES sdl_preloaded_pt.json + DESTINATION bin + ) +endif () if (${QT_HMI}) if (CMAKE_SYSTEM_NAME STREQUAL "QNX") diff --git a/src/appMain/life_cycle.h b/src/appMain/life_cycle.h index f1b3800254..586711d53e 100644 --- a/src/appMain/life_cycle.h +++ b/src/appMain/life_cycle.h @@ -44,6 +44,10 @@ #include "hmi_message_handler/messagebroker_adapter.h" #endif // #if ( defined (MESSAGEBROKER_HMIADAPTER) || defined(PASA_HMI) ) #include "application_manager/application_manager_impl.h" +#ifdef SDL_REMOTE_CONTROL +#include "application_manager/core_service.h" +#include "functional_module/plugin_manager.h" +#endif // SDL_REMOTE_CONTROL #include "connection_handler/connection_handler_impl.h" #include "protocol_handler/protocol_handler_impl.h" #include "transport_manager/transport_manager.h" diff --git a/src/components/CMakeLists.txt b/src/components/CMakeLists.txt index 0304ce986f..e1071e826f 100644 --- a/src/components/CMakeLists.txt +++ b/src/components/CMakeLists.txt @@ -86,6 +86,12 @@ add_subdirectory(./config_profile) # --- Media Manager add_subdirectory(./media_manager) +if(REMOTE_CONTROL) + # --- CAN Module + add_subdirectory(./remote_control) + # --- Functional module + add_subdirectory(./functional_module) +endif() # --- Telemetry Monitor if(TELEMETRY_MONITOR) add_subdirectory(./telemetry_monitor) diff --git a/src/components/application_manager/include/application_manager/app_extension.h b/src/components/application_manager/include/application_manager/app_extension.h new file mode 100644 index 0000000000..221601a307 --- /dev/null +++ b/src/components/application_manager/include/application_manager/app_extension.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_EXTENSION_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_EXTENSION_H_ + +#include "utils/shared_ptr.h" + +namespace application_manager { + +typedef int AppExtensionUID; + +class AppExtension { + public: + explicit AppExtension(AppExtensionUID uid) : kUid_(uid) {} + virtual ~AppExtension() {} + AppExtensionUID uid() const { + return kUid_; + } + + private: + const AppExtensionUID kUid_; +}; + +typedef utils::SharedPtr<AppExtension> AppExtensionPtr; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_EXTENSION_H_ diff --git a/src/components/application_manager/include/application_manager/core_service.h b/src/components/application_manager/include/application_manager/core_service.h new file mode 100644 index 0000000000..d746b953dc --- /dev/null +++ b/src/components/application_manager/include/application_manager/core_service.h @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_CORE_SERVICE_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_CORE_SERVICE_H_ + +#include <string> +#include <vector> +#include "application_manager/service.h" +#include "application_manager/application.h" +#include "policy/policy_types.h" + +namespace Json { +class Value; +} + +namespace application_manager { + +struct CommandParametersPermissions; + +/** + * @brief Class through which the plug-in can interact with the core + */ +class CoreService : public Service { + public: + /** + * @brief CoreService class destructor + */ + explicit CoreService(ApplicationManager& application_manager); + + /** + * @brief CoreService class destructor + */ + virtual ~CoreService(); + + /** + * @brief Checks message permissions and cuts parameters according + * to policy table permissions + * @param msg message to cut disallowed parameters + * @return result according by mobile API + */ + mobile_apis::Result::eType CheckPolicyPermissions(MessagePtr msg) FINAL; + + /** + * Checks access to requested equipment of vehicle + * @param app_id id of application + * @param module type + * @param rpc name of rpc + * @param params parameters list + * @return return allowed if access exist, + * manual if need to send question to driver otherwise disallowed + */ + TypeAccess CheckAccess(const ApplicationId& app_id, + const std::string& module, + const std::string& rpc, + const std::vector<std::string>& params) FINAL; + + /** + * Checks access to module for application + * @param app_id id of application + * @param module type + * @return true if module is allowed for application + */ + bool CheckModule(const ApplicationId& app_id, + const std::string& module) FINAL; + + /** + * Sets access to functional group which contains given RPC for application + * @param app_id id of application + * @param module type + * @param allowed true if driver has given access + */ + void SetAccess(const ApplicationId& app_id, + const std::string& module, + bool allowed) FINAL; + + /** + * Resets access by group name for all applications + * @param group_name group name + */ + void ResetAccess(const ApplicationId& app_id) FINAL; + + /** + * Resets access by module type for all applications + * @param module type + */ + void ResetAccess(const std::string& module) FINAL; + + /** + * Gets device handler for device with certain ID + * @param device_id the ID of the connected device + * @return device handler if device with requested ID was found + */ + uint32_t GetDeviceHandlerById(const std::string& device_id) FINAL; + + /** + * Sets device as primary device + * @param dev_id ID device + */ + void SetPrimaryDevice(const uint32_t dev_id) FINAL; + + /** + * Resets driver's device + */ + void ResetPrimaryDevice() FINAL; + + /** + * Return id of primary device + */ + uint32_t PrimaryDevice() const FINAL; + + /** + * Sets mode of remote control (on/off) + * @param enabled true if remote control is turned on + */ + void SetRemoteControl(bool enabled) FINAL; + + /** + * @brief Is Remote Control allowed by Policy and User + */ + bool IsRemoteControlAllowed() const FINAL; + + /** + * Checks if application has remote control functions + * @param app application + * @return true if application has remote control functions + */ + bool IsRemoteControlApplication(ApplicationSharedPtr app) const FINAL; + + /** + * Removes fake parameters from request to HMI + * @param message message to handle + */ + void RemoveHMIFakeParameters(application_manager::MessagePtr& message) FINAL; + + /** + * @brief Get pointer to application by application id + * @param app_id application id + * return pointer to application + */ + ApplicationSharedPtr GetApplication(ApplicationId app_id) FINAL; + + /** + * @brief Send message to HMI + * @param message Message to HMI + */ + void SendMessageToHMI(const MessagePtr& message) FINAL; + + /** + * @brief Send message to mobile device + * @param message Message to mobile + */ + void SendMessageToMobile(const MessagePtr& message) FINAL; + + /** + * @brief Returns unique correlation ID for next HMI request + * + * @return Unique correlation ID + */ + uint32_t GetNextCorrelationID() FINAL; + + /** + * @brief Returns all applications + * + * @return List with shared pointers to applications + */ + std::vector<ApplicationSharedPtr> GetApplications(AppExtensionUID uid) FINAL; + + /** + * @brief Subscribes to notification from HMI + * @param hmi_notification string with notification name + */ + void SubscribeToHMINotification(const std::string& hmi_notification) FINAL; + + /** + * @brief Change hmi level of app and notify it + * @param app Application to be changed and notified + * @param level New HMI level of app + */ + void ChangeNotifyHMILevel(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level) FINAL; + + /** + * @brief Notify HMI about app changing HMI Level + * only NONE, BACKGROUND and LIMITED levels are sent + * @param app Application to be changed and notified + * @param level New HMI level of app + */ + void NotifyHMIAboutHMILevel(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level) FINAL; + + /** + * Gets all allowed module types + * @param app_id unique identifier of application + * @param list of allowed module types + * @return true if application has allowed modules + */ + bool GetModuleTypes(const std::string& policy_app_id, + std::vector<std::string>* modules) const FINAL; + + MessageValidationResult ValidateMessageBySchema( + const Message& message) OVERRIDE; + + private: + bool AreParametersAllowed(MessagePtr msg, + const CommandParametersPermissions& params); + bool CheckParams(const Json::Value& object, + const policy::RPCParams& allowed_params); + bool IsAllowed(const std::string& name, + const policy::RPCParams& allowed_params); + + ApplicationManager& application_manager_; + + DISALLOW_COPY_AND_ASSIGN(CoreService); +}; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_CORE_SERVICE_H_ diff --git a/src/components/application_manager/include/application_manager/service.h b/src/components/application_manager/include/application_manager/service.h new file mode 100644 index 0000000000..4eea2b0b0f --- /dev/null +++ b/src/components/application_manager/include/application_manager/service.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2017, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_SERVICE_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_SERVICE_H_ + +#include <string> +#include <sstream> +#include <vector> +#include "application_manager/application.h" +#include "application_manager/message.h" + +namespace application_manager { + +enum TypeAccess { kNone, kDisallowed, kAllowed, kManual }; + +enum MessageValidationResult { + SUCCESS = 0, + INVALID_JSON, + INVALID_METADATA, + SCHEMA_MISMATCH, + UNSUPPORTED_PROTOCOL +}; + +typedef std::string PluginFunctionID; + +/** + * @brief Interface to core service + */ +class Service { + public: + virtual ~Service() {} + + /** + * @brief Checks message permissions and cuts parameters according + * to policy table permissions + * @param msg message to cut disallowed parameters + * @return result according by mobile API + */ + virtual mobile_apis::Result::eType CheckPolicyPermissions(MessagePtr msg) = 0; + + /** + * Checks access to requested equipment of vehicle + * @param app_id id of application + * @param module type + * @param rpc name of rpc + * @param params parameters list + * @return return allowed if access exist, + * manual if need to send question to driver otherwise disallowed + */ + virtual TypeAccess CheckAccess(const ApplicationId& app_id, + const std::string& module, + const std::string& rpc, + const std::vector<std::string>& params) = 0; + + /** + * Checks access to module for application + * @param app_id id of application + * @param module type + * @return true if module is allowed for application + */ + virtual bool CheckModule(const ApplicationId& app_id, + const std::string& module) = 0; + + /** + * Sets access to functional group which contains given RPC for application + * @param app_id id of application + * @param module type + * @param allowed true if driver has given access + */ + virtual void SetAccess(const ApplicationId& app_id, + const std::string& module, + bool allowed) = 0; + + /** + * Resets access application to all resources + * @param app_id ID application + */ + virtual void ResetAccess(const ApplicationId& app_id) = 0; + + /** + * Resets access by module and interior zone for all applications + * @param module type + */ + virtual void ResetAccess(const std::string& module) = 0; + + /** + * Gets device handler for device with certain ID + * @param device_id the ID of the connected device + * @return device handler if device with requested ID was found + */ + virtual uint32_t GetDeviceHandlerById(const std::string& device_id) = 0; + + /** + * Sets device as primary device + * @param dev_id ID device + */ + virtual void SetPrimaryDevice(const uint32_t dev_id) = 0; + + /** + * Resets driver's device + */ + virtual void ResetPrimaryDevice() = 0; + + /** + * Return id of primary device + */ + virtual uint32_t PrimaryDevice() const = 0; + + /** + * Sets mode of remote control (on/off) + * @param enabled true if remote control is turned on + */ + virtual void SetRemoteControl(bool enabled) = 0; + + /** + * @brief Is Remote Control allowed by Policy and User + */ + virtual bool IsRemoteControlAllowed() const = 0; + + /** + * @brief Get pointer to application by application id + * @param app_id application id + * return pointer to application + */ + virtual ApplicationSharedPtr GetApplication(ApplicationId app_id) = 0; + + /** + * Removes fake parameters from request to HMI + * @param message message to handle + */ + virtual void RemoveHMIFakeParameters( + application_manager::MessagePtr& message) = 0; + /** + * @brief Send message to HMI + * @param message Message to HMI + */ + virtual void SendMessageToHMI(const MessagePtr& message) = 0; + + /** + * @brief Send message to mobile device + * @param message Message to mobile + */ + virtual void SendMessageToMobile(const MessagePtr& message) = 0; + + /** + * @brief Returns unique correlation ID for next HMI request + * + * @return Unique correlation ID + */ + virtual uint32_t GetNextCorrelationID() = 0; + + /** + * @brief Returns all applications related to plugin + * @param uid ID provided by plugin to its extension to app. + * @return List with shared pointers to applications + */ + virtual std::vector<ApplicationSharedPtr> GetApplications( + AppExtensionUID uid) = 0; + + /** + * @brief Subscribes to notification from HMI + * @param hmi_notification string with notification name + */ + virtual void SubscribeToHMINotification( + const std::string& hmi_notification) = 0; + + /** + * @brief Change hmi level of app and notify it + * @param app Application to be changed and notified + * @param level New HMI level of app + */ + virtual void ChangeNotifyHMILevel(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level) = 0; + + /** + * @brief Notify HMI about app changing HMI Level + * only NONE, BACKGROUND and LIMITED levels are sent + * @param app Application to be changed and notified + * @param level New HMI level of app + */ + virtual void NotifyHMIAboutHMILevel(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level) = 0; + + /** + * Checks if application has remote control functions + * @param app application + * @return true if application has remote control functions + */ + virtual bool IsRemoteControlApplication(ApplicationSharedPtr app) const = 0; + + /** + * Gets all allowed module types + * @param app_id unique identifier of application + * @param list of allowed module types + * @return true if application has allowed modules + */ + virtual bool GetModuleTypes(const std::string& policy_app_id, + std::vector<std::string>* modules) const = 0; + + /** + * @brief ValidateMessageBySchema validates message by xml schema + * @param message message for validation + * @return true if message is valid according to schema, otherwise false + */ + virtual MessageValidationResult ValidateMessageBySchema( + const Message& message) = 0; +}; + +typedef utils::SharedPtr<Service> ServicePtr; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_SERVICE_H_ diff --git a/src/components/application_manager/src/core_service.cc b/src/components/application_manager/src/core_service.cc new file mode 100644 index 0000000000..5aca2e4c34 --- /dev/null +++ b/src/components/application_manager/src/core_service.cc @@ -0,0 +1,306 @@ +/** + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <vector> +#include <algorithm> +#include "application_manager/core_service.h" +#include "application_manager/application_manager_impl.h" +#include "application_manager/policies/policy_handler.h" +#include "application_manager/message_helper.h" +#include "json/json.h" +#include "interfaces/HMI_API.h" + +namespace application_manager { + +namespace { +struct AppExtensionPredicate { + AppExtensionUID uid; + bool operator()(const ApplicationSharedPtr app) { + return app ? app->QueryInterface(uid).valid() : false; + } +}; +} + +CoreService::CoreService(ApplicationManager& application_manager) + : application_manager_(application_manager) {} + +CoreService::~CoreService() {} + +mobile_apis::Result::eType CoreService::CheckPolicyPermissions(MessagePtr msg) { + ApplicationSharedPtr app = GetApplication(msg->connection_key()); + if (!app) { + return mobile_apis::Result::eType::APPLICATION_NOT_REGISTERED; + } + +#ifdef SDL_REMOTE_CONTROL + const RPCParams rpc_params; + CommandParametersPermissions params; + const mobile_apis::Result::eType ret = + application_manager_.CheckPolicyPermissions( + app, msg->function_name(), rpc_params, ¶ms); + + if (ret != mobile_apis::Result::eType::SUCCESS) { + return ret; + } + + if (!AreParametersAllowed(msg, params)) { + return mobile_apis::Result::eType::DISALLOWED; + } + + return ret; +#else + return mobile_apis::Result::eType::SUCCESS; +#endif // SDL_REMOTE_CONTROL +} + +TypeAccess CoreService::CheckAccess(const ApplicationId& app_id, + const std::string& module, + const std::string& rpc, + const std::vector<std::string>& params) { +#ifdef SDL_REMOTE_CONTROL + ApplicationSharedPtr app = GetApplication(app_id); + if (app) { + std::string device_handle = MessageHelper::GetDeviceMacAddressForHandle( + app->device(), application_manager_); + return application_manager_.GetPolicyHandler().CheckAccess( + device_handle, app->policy_app_id(), module, rpc, params); + } +#endif // SDL_REMOTE_CONTROL + return kNone; +} + +bool CoreService::CheckModule(const ApplicationId& app_id, + const std::string& module) { +#ifdef SDL_REMOTE_CONTROL + ApplicationSharedPtr app = GetApplication(app_id); + if (app) { + return application_manager_.GetPolicyHandler().CheckModule( + app->policy_app_id(), module); + } +#endif // SDL_REMOTE_CONTROL + return false; +} + +void CoreService::SetAccess(const ApplicationId& app_id, + const std::string& module, + bool allowed) { +#ifdef SDL_REMOTE_CONTROL + ApplicationSharedPtr app = GetApplication(app_id); + if (app) { + std::string device_handle = MessageHelper::GetDeviceMacAddressForHandle( + app->device(), application_manager_); + application_manager_.GetPolicyHandler().SetAccess( + device_handle, app->policy_app_id(), module, allowed); + } +#endif // SDL_REMOTE_CONTROL +} + +void CoreService::ResetAccess(const ApplicationId& app_id) { +#ifdef SDL_REMOTE_CONTROL + ApplicationSharedPtr app = GetApplication(app_id); + if (app) { + std::string device_handle = MessageHelper::GetDeviceMacAddressForHandle( + app->device(), application_manager_); + application_manager_.GetPolicyHandler().ResetAccess(device_handle, + app->policy_app_id()); + } +#endif // SDL_REMOTE_CONTROL +} + +void CoreService::ResetAccess(const std::string& module) { +#ifdef SDL_REMOTE_CONTROL + application_manager_.GetPolicyHandler().ResetAccess(module); +#endif // SDL_REMOTE_CONTROL +} + +uint32_t CoreService::GetDeviceHandlerById(const std::string& device_id) { + uint32_t device_handle = 0; + application_manager_.connection_handler().GetDeviceID(device_id, + &device_handle); + return device_handle; +} + +void CoreService::SetPrimaryDevice(const uint32_t dev_id) { +#ifdef SDL_REMOTE_CONTROL + std::string device_handle = + MessageHelper::GetDeviceMacAddressForHandle(dev_id, application_manager_); + application_manager_.GetPolicyHandler().SetPrimaryDevice(device_handle); +#endif // SDL_REMOTE_CONTROL +} + +void CoreService::ResetPrimaryDevice() { +#ifdef SDL_REMOTE_CONTROL + application_manager_.GetPolicyHandler().ResetPrimaryDevice(); +#endif // SDL_REMOTE_CONTROL +} + +uint32_t CoreService::PrimaryDevice() const { +#ifdef SDL_REMOTE_CONTROL + return application_manager_.GetPolicyHandler().PrimaryDevice(); +#endif // SDL_REMOTE_CONTROL + return 0; +} + +void CoreService::SetRemoteControl(bool enabled) { +#ifdef SDL_REMOTE_CONTROL + application_manager_.GetPolicyHandler().SetRemoteControl(enabled); +#endif // SDL_REMOTE_CONTROL +} + +bool CoreService::IsRemoteControlAllowed() const { +#ifdef SDL_REMOTE_CONTROL + return application_manager_.GetPolicyHandler().GetRemoteControl(); +#endif // SDL_REMOTE_CONTROL + return false; +} + +bool CoreService::IsRemoteControlApplication(ApplicationSharedPtr app) const { +#ifdef SDL_REMOTE_CONTROL + return application_manager_.GetPolicyHandler().CheckHMIType( + app->policy_app_id(), + mobile_apis::AppHMIType::eType::REMOTE_CONTROL, + app->app_types()); +#endif // SDL_REMOTE_CONTROL + return false; +} + +void CoreService::RemoveHMIFakeParameters( + application_manager::MessagePtr& message) { + application_manager_.RemoveHMIFakeParameters(message); +} + +ApplicationSharedPtr CoreService::GetApplication(ApplicationId app_id) { + return application_manager_.application(app_id); +} + +void CoreService::SendMessageToHMI(const MessagePtr& message) { + application_manager_.SendPostMessageToHMI(message); +} + +void CoreService::SendMessageToMobile(const MessagePtr& message) { + application_manager_.SendPostMessageToMobile(message); +} + +uint32_t CoreService::GetNextCorrelationID() { + return application_manager_.GetNextHMICorrelationID(); +} + +std::vector<ApplicationSharedPtr> CoreService::GetApplications( + AppExtensionUID uid) { + ApplicationSet accessor = application_manager_.applications().GetData(); + AppExtensionPredicate predicate; + predicate.uid = uid; + + std::vector<ApplicationSharedPtr> result; + ApplicationSetConstIt it = + std::find_if(accessor.begin(), accessor.end(), predicate); + while (it != accessor.end()) { + result.push_back(*it); + it = std::find_if(++it, accessor.end(), predicate); + } + return result; +} + +void CoreService::SubscribeToHMINotification( + const std::string& hmi_notification) { + if (!hmi_notification.empty()) { + application_manager_.SubscribeToHMINotification(hmi_notification); + } +} + +void CoreService::ChangeNotifyHMILevel(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level) { + application_manager_.ChangeAppsHMILevel(app->app_id(), level); + MessageHelper::SendHMIStatusNotification(*app, application_manager_); +} + +void CoreService::NotifyHMIAboutHMILevel(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level) { + if (app->hmi_level() != mobile_apis::HMILevel::eType::HMI_FULL) { + MessageHelper::SendActivateAppToHMI( + app->app_id(), + application_manager_, + static_cast<hmi_apis::Common_HMILevel::eType>(level), + true); + } +} + +bool CoreService::AreParametersAllowed( + MessagePtr msg, const CommandParametersPermissions& params) { + Json::Reader reader; + Json::Value json; + bool ret = reader.parse(msg->json_message(), json); + if (ret) { + return CheckParams(json.get(strings::params, Json::Value(Json::nullValue)), + params.allowed_params); + } + return false; +} + +bool CoreService::CheckParams(const Json::Value& object, + const RPCParams& allowed_params) { + if (!object.isObject()) { + return true; + } + for (Json::Value::iterator i = object.begin(); i != object.end(); ++i) { + std::string name = i.memberName(); + if (!IsAllowed(name, allowed_params)) { + return false; + } + } + return true; +} + +bool CoreService::IsAllowed(const std::string& name, + const RPCParams& allowed_params) { + return std::find(allowed_params.begin(), allowed_params.end(), name) != + allowed_params.end(); +} + +bool CoreService::GetModuleTypes(const std::string& policy_app_id, + std::vector<std::string>* modules) const { +#ifdef SDL_REMOTE_CONTROL + return application_manager_.GetPolicyHandler().GetModuleTypes(policy_app_id, + modules); +#endif // SDL_REMOTE_CONTROL + return false; +} + +MessageValidationResult CoreService::ValidateMessageBySchema( + const Message& message) { + const MessageValidationResult result = + application_manager_.ValidateMessageBySchema(message); + LOG4CXX_DEBUG(logger_, "Validation result : " << result); + return result; +} + +} // namespace application_manager diff --git a/src/components/config_profile/include/config_profile/profile.h b/src/components/config_profile/include/config_profile/profile.h index 8a25bcf648..a177d7c410 100644 --- a/src/components/config_profile/include/config_profile/profile.h +++ b/src/components/config_profile/include/config_profile/profile.h @@ -176,9 +176,9 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, const uint16_t video_streaming_port() const OVERRIDE; /** - * @brief Returns port for audio streaming - */ - const uint16_t audio_streaming_port() const; + * @brief Returns port for audio streaming + */ + const uint16_t audio_streaming_port() const OVERRIDE; /** * @brief Returns streaming timeout @@ -212,6 +212,11 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, const std::vector<std::string>& vr_commands() const; /** + * @brief Returns folder containing all plugins + */ + const std::string& plugins_folder() const; + + /** * @brief Maximum command id available for mobile app */ const uint32_t& max_cmd_id() const; @@ -230,7 +235,7 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, /** * @brief Returns desirable thread stack size */ - const uint64_t& thread_min_stack_size() const; + const uint64_t thread_min_stack_size() const; /** * @brief Returns true if audio mixing is supported @@ -365,10 +370,19 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, // TransportManageSettings interface + /* + * @brief Returns true if last state singleton is used + */ bool use_last_state() const OVERRIDE; + /** + * @brief Timeout in transport manager before disconnect + */ uint32_t transport_manager_disconnect_timeout() const OVERRIDE; + /** + * @brief Returns port for TCP transport adapter + */ uint16_t transport_manager_tcp_adapter_port() const OVERRIDE; // TransportManageMMESettings interface @@ -880,6 +894,7 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, std::string iap_pool_protocol_mask_; std::string iap_system_config_; std::string iap2_system_config_; + std::string plugins_folder_; int iap2_hub_connect_attempts_; int iap_hub_connection_wait_timeout_; uint16_t tts_global_properties_timeout_; diff --git a/src/components/config_profile/src/profile.cc b/src/components/config_profile/src/profile.cc index 58709b876c..6389375bb8 100644 --- a/src/components/config_profile/src/profile.cc +++ b/src/components/config_profile/src/profile.cc @@ -141,6 +141,7 @@ const char* kTimeoutPromptKey = "TimeOutPromt"; const char* kHelpTitleKey = "HelpTitle"; const char* kHelpCommandKey = "HelpCommand"; const char* kSystemFilesPathKey = "SystemFilesPath"; +const char* kPluginsFolderKey = "PluginFolder"; const char* kHeartBeatTimeoutKey = "HeartBeatTimeout"; const char* kMaxSupportedProtocolVersionKey = "MaxSupportedProtocolVersion"; const char* kUseLastStateKey = "UseLastState"; @@ -219,6 +220,7 @@ const char* kDefaultPreloadedPTFileName = "sdl_preloaded_pt.json"; const char* kDefaultServerAddress = "127.0.0.1"; const char* kDefaultAppInfoFileName = "app_info.dat"; const char* kDefaultSystemFilesPath = "/tmp/fs/mp/images/ivsu_cache"; +const char* kDefaultPluginsPath = "plugins"; const char* kDefaultTtsDelimiter = ","; const uint32_t kDefaultAudioDataStoppedTimeout = 1000; const uint32_t kDefaultVideoDataStoppedTimeout = 1000; @@ -541,7 +543,7 @@ const uint16_t& Profile::time_testing_port() const { return time_testing_port_; } -const uint64_t& Profile::thread_min_stack_size() const { +const uint64_t Profile::thread_min_stack_size() const { return min_tread_stack_size_; } @@ -661,6 +663,9 @@ const std::string& Profile::system_files_path() const { return system_files_path_; } +const std::string& Profile::plugins_folder() const { + return plugins_folder_; +} const std::vector<uint32_t>& Profile::supported_diag_modes() const { return supported_diag_modes_; } @@ -1556,6 +1561,10 @@ void Profile::UpdateValues() { LOG_UPDATED_VALUE(system_files_path_, kSystemFilesPathKey, kMainSection); + // Plugins folder + ReadStringValue( + &plugins_folder_, kDefaultPluginsPath, kMainSection, kPluginsFolderKey); + LOG_UPDATED_VALUE(plugins_folder_, kPluginsFolderKey, kMainSection); // Heartbeat timeout ReadUIntValue(&heart_beat_timeout_, kDefaultHeartBeatTimeout, diff --git a/src/components/functional_module/CMakeLists.txt b/src/components/functional_module/CMakeLists.txt new file mode 100644 index 0000000000..756a1dd2fe --- /dev/null +++ b/src/components/functional_module/CMakeLists.txt @@ -0,0 +1,58 @@ +if (ENABLE_GCOV) + set(GCOV_FLAGS "-ftest-coverage -fprofile-arcs") +else() + set(GCOV_FLAGS "") +endif() + +set(CMAKE_CXX_FLAGS "-fPIC -std=gnu++0x -Wno-deprecated-declarations -Wall -Werror ${GCOV_FLAGS}") + +if (CMAKE_BUILD_TYPE) + if (${CMAKE_BUILD_TYPE} STREQUAL "Release") + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") + set(CMAKE_CXX_FLAGS_DEBUG "") + else () + set(CMAKE_CXX_FLAGS_RELEASE "") + set(CMAKE_CXX_FLAGS_DEBUG "-g3 -ggdb3 -DDEBUG") + endif() +endif() + +set(GCOV gcov) + +include_directories ( + ${COMPONENTS_DIR}/functional_module/include/ + ${COMPONENTS_DIR}/remote_control/include/ + ${COMPONENTS_DIR}/include/ + ${COMPONENTS_DIR}/application_manager/include + ${COMPONENTS_DIR}/connection_handler/include/ + ${COMPONENTS_DIR}/utils/include + ${POLICY_PATH}/include/ + ${POLICY_GLOBAL_INCLUDE_PATH}/ + ${COMPONENTS_DIR}/config_profile/include + ${COMPONENTS_DIR}/smart_objects/include + ${JSONCPP_INCLUDE_DIRECTORY} + ${LOG4CXX_INCLUDE_DIRECTORY} + ${CMAKE_BINARY_DIR}/src/components/ + + ${COMPONENTS_DIR}/application_manager/test/include/ +) + +set (SOURCES + ./src/generic_module.cc + ./src/plugin_manager.cc + ./src/settings.cc + ./src/timer/timer_director.cc +) +set (LIBRARIES + ApplicationManager +) + +add_library("FunctionalModule" ${SOURCES}) +target_link_libraries("FunctionalModule" ${LIBRARIES} ) + +if(ENABLE_LOG) + target_link_libraries("FunctionalModule" log4cxx -L${LOG4CXX_LIBS_DIRECTORY} ${GCOV}) +endif() + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/src/components/functional_module/include/functional_module/function_ids.h b/src/components/functional_module/include/functional_module/function_ids.h new file mode 100644 index 0000000000..5b8218e37b --- /dev/null +++ b/src/components/functional_module/include/functional_module/function_ids.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_FUNCTION_IDS_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_FUNCTION_IDS_H_ + +namespace functional_modules { + +enum RCFunctionID { + // Remote SDL functions ids + BUTTON_PRESS = 41, + GET_INTERIOR_VEHICLE_DATA = 43, + SET_INTERIOR_VEHICLE_DATA = 44, + ON_INTERIOR_VEHICLE_DATA = 32783, + ON_REMOTE_CONTROL_SETTINGS, +}; + +namespace hmi_api { +const char get_interior_vehicle_data[] = "RC.GetInteriorVehicleData"; +const char set_interior_vehicle_data[] = "RC.SetInteriorVehicleData"; +const char on_interior_vehicle_data[] = "RC.OnInteriorVehicleData"; +const char button_press[] = "Buttons.ButtonPress"; +const char on_remote_control_settings[] = "RC.OnRemoteControlSettings"; + +const char get_user_consent[] = "RC.GetInteriorVehicleDataConsent"; +const char on_app_deactivated[] = "BasicCommunication.OnAppDeactivated"; +const char sdl_activate_app[] = "SDL.ActivateApp"; +} + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_FUNCTION_IDS_H_ diff --git a/src/components/functional_module/include/functional_module/generic_module.h b/src/components/functional_module/include/functional_module/generic_module.h new file mode 100644 index 0000000000..9d003f4e28 --- /dev/null +++ b/src/components/functional_module/include/functional_module/generic_module.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_GENERIC_MODULE_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_GENERIC_MODULE_H_ + +#include <deque> +#include <string> +#include "functional_module/module_observer.h" +#include "functional_module/function_ids.h" +#include "utils/shared_ptr.h" +#include "application_manager/service.h" + +namespace functional_modules { + +enum ProcessResult { + NONE = -1, + PROCESSED, + PARTIALLY_PROCESSED, + CANNOT_PROCESS, + FAILED +}; + +enum ServiceState { IDLE = 0, SUSPENDED, LOWVOLTAGE, HMI_ADAPTER_INITIALIZED }; + +typedef std::string HMIFunctionID; + +class GenericModule; +typedef utils::SharedPtr<GenericModule> ModulePtr; + +struct PluginInfo { + std::string name; + int version; + std::deque<RCFunctionID> rc_function_list; + std::deque<HMIFunctionID> hmi_function_list; +}; + +class GenericModule { + public: + typedef std::deque<ModuleObserver*> Observers; + + virtual ~GenericModule(); + ModuleID GetModuleID() const { + return kModuleId_; + } + virtual PluginInfo GetPluginInfo() const = 0; + + virtual void set_service(application_manager::ServicePtr service); + + /** + * @brief Returns pointer to SDL core service interface + * @return pointer to core service interface + */ + virtual application_manager::ServicePtr service(); + + virtual ProcessResult ProcessMessage(application_manager::MessagePtr msg) = 0; + virtual ProcessResult ProcessHMIMessage( + application_manager::MessagePtr msg) = 0; + virtual void OnServiceStateChanged(ServiceState state); + + /** + * @brief Adds pointer to observer of module to be notified about + * exceptional sutiations in module. + * Raw pointer is passed to avoid circular dependencies. + * Module is not responsible for freeing observer's memory. + */ + void AddObserver(ModuleObserver* const observer); + + /** + * @brief Removes pointer to observer of module when it's no loger + * wants to be notified about exceptional sutiations in module. + * Raw pointer is passed to avoid circular dependencies. + * Module is not responsible for freeing observer's memory. + */ + void RemoveObserver(ModuleObserver* const observer); + + /** + * @brief Remove extension created for specified application + * @param app_id application id + */ + virtual void RemoveAppExtension(uint32_t app_id) = 0; + + /** + * @brief Check registering app can be handled by plugin + * @param msg Registration message + * @param app Application basis already create by Core + */ + virtual bool IsAppForPlugin( + application_manager::ApplicationSharedPtr app) = 0; + + /** + * @brief Notify about change of HMILevel of plugin's app + * @param app App with new HMILevel + * @param old_level Old HMILevel of app + */ + virtual void OnAppHMILevelChanged( + application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType old_level) = 0; + + /** + * @brief Checks if plugin hasn't put restrictions on app's HMI Level + * @param app App with old HMILevel + * @param new_level HMILevel which is about to be set to app + */ + virtual bool CanAppChangeHMILevel( + application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType new_level) { + return true; + } + + /** + * Handles removing (disconnecting) device + * @param device removed + */ + virtual void OnDeviceRemoved( + const connection_handler::DeviceHandle& device) = 0; + + /** + * @brief OnUnregisterApplication handles application unregistering event + * @param app_id application id which was unregistered + */ + virtual void OnUnregisterApplication(const uint32_t app_id) = 0; + + protected: + explicit GenericModule(ModuleID module_id); + void NotifyObservers(ModuleObserver::Errors error); + + /** + * @brief Remove extension for all applications + */ + virtual void RemoveAppExtensions() = 0; + + private: + application_manager::ServicePtr service_; + const ModuleID kModuleId_; + + Observers observers_; + ServiceState state_; + + friend class DriverGenericModuleTest; + DISALLOW_COPY_AND_ASSIGN(GenericModule); +}; + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_GENERIC_MODULE_H_ diff --git a/src/components/functional_module/include/functional_module/module_observer.h b/src/components/functional_module/include/functional_module/module_observer.h new file mode 100644 index 0000000000..1608ef5d42 --- /dev/null +++ b/src/components/functional_module/include/functional_module/module_observer.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_MODULE_OBSERVER_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_MODULE_OBSERVER_H_ + +namespace functional_modules { + +typedef int ModuleID; + +class ModuleObserver { + public: + enum Errors { NONE = -1, OUT_OF_MEMORY, FS_FAILURE }; + virtual ~ModuleObserver() {} + virtual void OnError(Errors error, ModuleID module_id) = 0; +}; +} // namespace functional_modules { + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_MODULE_OBSERVER_H_ diff --git a/src/components/functional_module/include/functional_module/plugin_manager.h b/src/components/functional_module/include/functional_module/plugin_manager.h new file mode 100644 index 0000000000..38368ab01a --- /dev/null +++ b/src/components/functional_module/include/functional_module/plugin_manager.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_PLUGIN_MANAGER_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_PLUGIN_MANAGER_H_ + +#include <map> +#include <string> +#include "functional_module/generic_module.h" +#include "application_manager/service.h" +#include "application_manager/message.h" + +namespace functional_modules { + +class PluginManager : public ModuleObserver { + public: + PluginManager(); + ~PluginManager(); + typedef std::map<ModuleID, ModulePtr> Modules; + int LoadPlugins(const std::string& plugin_path); + void UnloadPlugins(); + void ProcessMessage(application_manager::MessagePtr msg); + ProcessResult ProcessHMIMessage(application_manager::MessagePtr msg); + void SetServiceHandler(application_manager::ServicePtr service) { + service_ = service; + } + bool IsMessageForPlugin(application_manager::MessagePtr msg); + bool IsHMIMessageForPlugin(application_manager::MessagePtr msg); + void OnServiceStateChanged(ServiceState state); + void OnHMIResponse(application_manager::MessagePtr msg); + void OnError(ModuleObserver::Errors error, ModuleID module_id); + + /** + * @brief Remove extension created for specified application + * @param app_id application id + */ + void RemoveAppExtension(uint32_t app_id); + + /** + * @brief Check if app cooperates with one or more plugins, init it + * inside plugin accordingly if needed. + * @param app Application in question. + */ + bool IsAppForPlugins(application_manager::ApplicationSharedPtr app); + + /** + * Check if app cooperates with plugin + * @param app application + * @param module_id unique identifier of plugin + * @return true if application cooperates with this plugin + */ + bool IsAppForPlugin(application_manager::ApplicationSharedPtr app, + ModuleID module_id) const; + + /** + * @brief Notify plugins about change of HMILevel of app + * if app is related to plugin + * @param app App with new HMILevel + * @param old_level Old HMILevel of app + */ + void OnAppHMILevelChanged(application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType old_level); + + /** + * @brief Checks if plugin hasn't put restrictions on app's HMI Level + * @param app App with old HMILevel + * @param new_level HMILevel which is about to be set to app + * @return false if any of the plugins returns false. + */ + bool CanAppChangeHMILevel(application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType new_level); + + /** + * Handles removing (disconnecting) device + * @param device removed + */ + void OnDeviceRemoved(const connection_handler::DeviceHandle& device); + + /** + * @brief OnUnregisterApplication handles application unregistering event + * @param app_id application id which was unregistered + */ + void OnUnregisterApplication(const uint32_t app_id); + + Modules& plugins(); + + private: + Modules plugins_; + std::map<ModuleID, void*> dlls_; + std::map<RCFunctionID, ModulePtr> mobile_subscribers_; + std::map<HMIFunctionID, ModulePtr> hmi_subscribers_; + application_manager::ServicePtr service_; + + DISALLOW_COPY_AND_ASSIGN(PluginManager); +}; + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_PLUGIN_MANAGER_H_ diff --git a/src/components/functional_module/include/functional_module/settings.h b/src/components/functional_module/include/functional_module/settings.h new file mode 100644 index 0000000000..cf78c24e8b --- /dev/null +++ b/src/components/functional_module/include/functional_module/settings.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_SETTINGS_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_SETTINGS_H_ + +#include <string> +#include <sstream> +#include "json/json.h" +#include "utils/macro.h" + +namespace functional_modules { + +/* + * @brief Settings class reads configuration for app from + * default location - smartDeviceLink.ini - or set location + * and provides access to them basing on template methods. + */ +class Settings { + public: + /* + * @brief Constrctor + */ + Settings(); + + /* + * @brief Destructor + */ + virtual ~Settings(); + + /* + * @brief Template method reads value from config file + * stored under param_name in section_name paragraph + * @param section_name Section name i.e [HMI] + * @param param_name Parameter name i.e. ServerAddress + * @returns True if value was read from config file, false otherwise + */ + template <class T> + bool ReadParameter(const std::string& section_name, + const std::string& param_name, + T* param_value) const; + + /* + * @brief Template method reads value from config file + * stored under param_name in [MAIN] paragraph + * @param param_name Parameter name i.e. ServerAddress + * @returns True if value was read from config file, false otherwise + */ + template <class T> + bool ReadParameter(const std::string& param_name, T* param_value) const; + + /* + * @brief Changes path to configuration file + * @param new_path Path to config file + */ + void ChangeConfigFile(const std::string& new_path); + + protected: + virtual std::string ReadParameter(const std::string& section_name, + const std::string& param_name) const; + + private: + const std::string kConfigFile_; + std::string config_file_; +}; + +template <class T> +bool Settings::ReadParameter(const std::string& section_name, + const std::string& param_name, + T* param_value) const { + DCHECK(param_value); + bool result = false; + if (!param_value) { + return result; + } + + std::string param_string = ReadParameter(section_name, param_name); + + if (!param_string.empty()) { + std::stringstream stream(param_string); + stream >> (*param_value); + result = true; + } + + return result; +} + +template <class T> +bool Settings::ReadParameter(const std::string& param_name, + T* param_value) const { + return ReadParameter<T>("MAIN", param_name, param_value); +} + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_SETTINGS_H_ diff --git a/src/components/functional_module/include/functional_module/timer/module_timer.h b/src/components/functional_module/include/functional_module/timer/module_timer.h new file mode 100644 index 0000000000..d7fc0ba043 --- /dev/null +++ b/src/components/functional_module/include/functional_module/timer/module_timer.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_TIMER_MODULE_TIMER_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_TIMER_MODULE_TIMER_H_ + +#include <list> +#include <deque> +#include <algorithm> +#include <time.h> +#include "utils/lock.h" + +namespace functional_modules { + +typedef unsigned int TimeUnit; // seconds + +class Trackable { + public: + Trackable() : start_time_(0) {} + virtual ~Trackable() {} + virtual TimeUnit custom_interval() const { + return 0; + } + virtual TimeUnit start_time() const { + return start_time_; + } + virtual void set_start_time(TimeUnit start_time) { + start_time_ = start_time; + } + + private: + TimeUnit start_time_; +}; + +template <class Trackable> +class TimerObserver { + public: + virtual ~TimerObserver() {} + virtual void OnTimeoutTriggered(const Trackable& expired) = 0; +}; + +template <class Trackable> +class ModuleTimer { + public: + ModuleTimer(); + ~ModuleTimer(); + void set_period(TimeUnit period) { + period_ = period; + } + TimeUnit period() const { + return period_; + } + void AddObserver(TimerObserver<Trackable>* observer); + void RemoveObserver(TimerObserver<Trackable>* observer); + + void CheckTimeout(); + /** + * @brief Gets time in seconds when the nearest request timeout will be + * triggered + * @return time in seconds when the nearest request timeout will be triggered + */ + TimeUnit GetSecondsToNearestTimeout(); + + /* + * @brief Adds object to be tracked by timer. + If same object is already added replaces it with new one + correspondingly updating start time of tracking. + */ + void AddTrackable(const Trackable& object); + void RemoveTrackable(const Trackable& object); + + protected: + void Notify(const Trackable& object); + void OnTimeout(const Trackable& object); + TimeUnit CurrentTime() const; + typename std::list<Trackable> trackables_; + volatile TimeUnit period_; + + private: + std::deque<TimerObserver<Trackable>*> observers_; + mutable sync_primitives::Lock trackables_lock_; + friend class ModuleTimerTest; +}; + +template <class Trackable> +ModuleTimer<Trackable>::ModuleTimer() + : period_(10) {} + +template <class Trackable> +ModuleTimer<Trackable>::~ModuleTimer() { + observers_.clear(); + sync_primitives::AutoLock auto_lock(trackables_lock_); + trackables_.clear(); +} + +template <class Trackable> +void ModuleTimer<Trackable>::AddObserver(TimerObserver<Trackable>* observer) { + DCHECK(observer); + if (!observer) { + return; + } + observers_.push_back(observer); +} + +template <class Trackable> +void ModuleTimer<Trackable>::RemoveObserver( + TimerObserver<Trackable>* observer) { + DCHECK(observer); + if (!observer) { + return; + } + for (typename std::deque<TimerObserver<Trackable>*>::iterator it = + observers_.begin(); + observers_.end() != it; + ++it) { + if (*it == observer) { + observers_.erase(it); + return; + } + } +} + +template <class Trackable> +void ModuleTimer<Trackable>::CheckTimeout() { + sync_primitives::AutoLock trackables_lock(trackables_lock_); + for (typename std::list<Trackable>::iterator it = trackables_.begin(); + trackables_.end() != it; + ++it) { + TimeUnit period = it->custom_interval(); + if (!period) { + period = period_; + } + if (CurrentTime() - it->start_time() >= period) { + OnTimeout(*it); + it = trackables_.erase(it); + } + } +} + +template <class Trackable> +TimeUnit ModuleTimer<Trackable>::GetSecondsToNearestTimeout() { + sync_primitives::AutoLock trackables_lock(trackables_lock_); + TimeUnit result = period_; + for (typename std::list<Trackable>::iterator it = trackables_.begin(); + trackables_.end() != it; + ++it) { + TimeUnit period = it->custom_interval(); + if (!period) { + period = period_; + } + const TimeUnit current_secs_to_timeout = + period - (CurrentTime() - it->start_time()); + if (result > current_secs_to_timeout) { + result = current_secs_to_timeout; + } + } + return result; +} + +template <class Trackable> +void ModuleTimer<Trackable>::AddTrackable(const Trackable& object) { + sync_primitives::AutoLock trackables_lock(trackables_lock_); + trackables_.remove(object); + trackables_.push_back(object); + trackables_.back().set_start_time(CurrentTime()); +} + +template <class Trackable> +void ModuleTimer<Trackable>::RemoveTrackable(const Trackable& object) { + sync_primitives::AutoLock trackables_lock(trackables_lock_); + trackables_.remove(object); +} + +template <class Trackable> +void ModuleTimer<Trackable>::Notify(const Trackable& object) { + for (typename std::deque<TimerObserver<Trackable>*>::const_iterator it = + observers_.begin(); + observers_.end() != it; + ++it) { + (*it)->OnTimeoutTriggered(object); + } +} + +template <class Trackable> +void ModuleTimer<Trackable>::OnTimeout(const Trackable& object) { + Notify(object); +} + +template <class Trackable> +TimeUnit ModuleTimer<Trackable>::CurrentTime() const { + // TODO(PV): move outside to platform-dependant parts + struct timespec current_time; + if (0 == clock_gettime(CLOCK_MONOTONIC, ¤t_time)) { + return current_time.tv_sec; + } else { + return 0; + } +} + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_TIMER_MODULE_TIMER_H_ diff --git a/src/components/functional_module/include/functional_module/timer/timer_director.h b/src/components/functional_module/include/functional_module/timer/timer_director.h new file mode 100644 index 0000000000..65f9f4a6d5 --- /dev/null +++ b/src/components/functional_module/include/functional_module/timer/timer_director.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_TIMER_TIMER_DIRECTOR_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_TIMER_TIMER_DIRECTOR_H_ + +#include <map> +#include "utils/threads/thread.h" +#include "utils/conditional_variable.h" +#include "functional_module/timer/module_timer.h" + +namespace functional_modules { + +template <class T> +class TimerThreadDelegate : public threads::ThreadDelegate { + public: + explicit TimerThreadDelegate(ModuleTimer<T>& timer); + void threadMain(); + void exitThreadMain(); + + /** + * @brief Reset awaiting timer by notifying cond var + */ + void ResetTimer(); + + private: + ModuleTimer<T>& timer_; + volatile bool keep_running_; + mutable sync_primitives::Lock keep_running_lock_; + mutable sync_primitives::ConditionalVariable keep_running_cond_; + friend class TimerThreadDelegateTest; +}; + +class TimerDirector { + public: + TimerDirector(); + ~TimerDirector(); + + /** + * @brief Register timer for execution in separate thread. + Registers only one timer of a type. Attempt to register timer + of already existing type will fail. + */ + template <class T> + void RegisterTimer(ModuleTimer<T>& timer); + template <class T> + void UnregisterTimer(const ModuleTimer<T>& timer); + void UnregisterAllTimers(); + /** + * @brief Reset awaiting timeout for specified module timer + * @param timer timer to reset awaiting timeout + */ + template <class T> + void ResetTimer(ModuleTimer<T>& timer); + + private: + DISALLOW_COPY_AND_ASSIGN(TimerDirector); + std::map<std::string, threads::Thread*> timer_threads_; +}; + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_INCLUDE_FUNCTIONAL_MODULE_TIMER_TIMER_DIRECTOR_H_ diff --git a/src/components/functional_module/src/generic_module.cc b/src/components/functional_module/src/generic_module.cc new file mode 100644 index 0000000000..eec4f7b6d3 --- /dev/null +++ b/src/components/functional_module/src/generic_module.cc @@ -0,0 +1,63 @@ +#include "functional_module/generic_module.h" +namespace functional_modules { + +typedef std::deque<ModuleObserver*>::iterator ModuleObserverIterator; + +GenericModule::GenericModule(ModuleID module_id) + : kModuleId_(module_id), state_(ServiceState::IDLE) {} + +GenericModule::~GenericModule() { + observers_.clear(); +} + +void GenericModule::AddObserver(ModuleObserver* const observer) { + DCHECK(observer); + if (!observer) { + return; + } + observers_.push_back(observer); +} + +void GenericModule::RemoveObserver(ModuleObserver* const observer) { + DCHECK(observer); + if (!observer) { + return; + } + for (ModuleObserverIterator it = observers_.begin(); observers_.end() != it; + ++it) { + if (*it == observer) { + observers_.erase(it); + return; + } + } +} + +void GenericModule::NotifyObservers(ModuleObserver::Errors error) { + for (ModuleObserverIterator it = observers_.begin(); observers_.end() != it; + ++it) { + (*it)->OnError(error, kModuleId_); + } +} + +void GenericModule::set_service(application_manager::ServicePtr service) { + service_ = service; +} + +void GenericModule::OnServiceStateChanged(ServiceState state) { + state_ = state; + + if (HMI_ADAPTER_INITIALIZED == state_) { + // We must subscribe to necessary HMI notifications + service_->SubscribeToHMINotification(hmi_api::on_interior_vehicle_data); + service_->SubscribeToHMINotification(hmi_api::on_remote_control_settings); + // Disabled + // service_->SubscribeToHMINotification(hmi_api::on_reverse_apps_allowing); + // service_->SubscribeToHMINotification(hmi_api::on_device_rank_changed); + } +} + +application_manager::ServicePtr GenericModule::service() { + return service_; +} + +} // namespace functional_modules diff --git a/src/components/functional_module/src/plugin_manager.cc b/src/components/functional_module/src/plugin_manager.cc new file mode 100644 index 0000000000..ab3b0bda05 --- /dev/null +++ b/src/components/functional_module/src/plugin_manager.cc @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <dlfcn.h> +#include <algorithm> +#include "functional_module/plugin_manager.h" +#include "functional_module/function_ids.h" +#include "utils/file_system.h" +#include "utils/logger.h" +#include "json/json.h" + +namespace functional_modules { + +CREATE_LOGGERPTR_GLOBAL(logger_, "PluginManager") + +typedef std::map<ModuleID, ModulePtr>::iterator PluginsIterator; +typedef std::map<RCFunctionID, ModulePtr>::iterator PluginFunctionsIterator; +typedef std::map<HMIFunctionID, ModulePtr>::iterator PluginHMIFunctionsIterator; + +PluginManager::PluginManager() : service_() { + LOG4CXX_DEBUG(logger_, "Creating plugin mgr"); +} + +PluginManager::~PluginManager() { + // TODO(PV): unsubscribe plugins from functions + mobile_subscribers_.clear(); + hmi_subscribers_.clear(); + UnloadPlugins(); +} + +int PluginManager::LoadPlugins(const std::string& plugin_path) { + LOG4CXX_INFO(logger_, "Loading plugins from " << plugin_path); + std::vector<std::string> plugin_files = file_system::ListFiles(plugin_path); + for (size_t i = 0; i < plugin_files.size(); ++i) { + size_t pos = plugin_files[i].find_last_of("."); + if (std::string::npos != pos) { + if (plugin_files[i].substr(pos + 1).compare("so") != 0) { + continue; + } + } else { + continue; + } + std::string full_name = plugin_path + '/' + plugin_files[i]; + void* generic_plugin_dll = dlopen(full_name.c_str(), RTLD_LAZY); + if (NULL == generic_plugin_dll) { + LOG4CXX_ERROR(logger_, + "Failed to open dll " << plugin_files[i] << "\n" + << dlerror()); + continue; + } + typedef GenericModule* (*Create)(); + Create create_manager = + reinterpret_cast<Create>(dlsym(generic_plugin_dll, "Create")); + char* error_string = dlerror(); + if (NULL != error_string) { + LOG4CXX_ERROR(logger_, + "Failed to export dll's " << plugin_files[i] << " symbols\n" + << error_string); + dlclose(generic_plugin_dll); + continue; + } + ModulePtr module = create_manager(); + if (!module) { + LOG4CXX_ERROR(logger_, + "Failed to create plugin main class " << plugin_files[i]); + dlclose(generic_plugin_dll); + continue; + } else { + LOG4CXX_DEBUG(logger_, + "Opened and working plugin from " << plugin_files[i] + << " with id " + << module->GetModuleID()); + dlls_.insert(std::pair<ModuleID, void*>(module->GetModuleID(), + generic_plugin_dll)); + plugins_.insert( + std::pair<ModuleID, ModulePtr>(module->GetModuleID(), module)); + std::deque<RCFunctionID> subscribers = + module->GetPluginInfo().rc_function_list; + for (size_t i = 0; i < subscribers.size(); ++i) { + mobile_subscribers_.insert( + std::pair<RCFunctionID, ModulePtr>(subscribers[i], module)); + } + + std::deque<HMIFunctionID> hmi_subscribers = + module->GetPluginInfo().hmi_function_list; + for (size_t i = 0; i < hmi_subscribers.size(); ++i) { + hmi_subscribers_.insert( + std::pair<HMIFunctionID, ModulePtr>(hmi_subscribers[i], module)); + } + module->set_service(service_); + module->AddObserver(this); + } + } + return plugins_.size(); +} + +void PluginManager::UnloadPlugins() { + for (Modules::iterator it = plugins_.begin(); plugins_.end() != it; ++it) { + it->second->RemoveObserver(this); + } + plugins_.clear(); + + for (std::map<ModuleID, void*>::iterator it = dlls_.begin(); + dlls_.end() != it; + ++it) { + dlclose(it->second); + } + dlls_.clear(); +} + +// TODO(VS): Optimize similar code in ProcessMessage, IsMessageForPlugin, +// ProcessHMIMessage, IsHMIMessageForPlugin methods +// (also we have similar code in can module) +void PluginManager::ProcessMessage(application_manager::MessagePtr msg) { + DCHECK(msg); + if (!msg) { + LOG4CXX_ERROR(logger_, "Null pointer message was received."); + return; + } + if (application_manager::ProtocolVersion::kUnknownProtocol != + msg->protocol_version() && + application_manager::ProtocolVersion::kHMI != msg->protocol_version()) { + PluginFunctionsIterator subscribed_plugin_itr = + mobile_subscribers_.find(static_cast<RCFunctionID>(msg->function_id())); + if (mobile_subscribers_.end() != subscribed_plugin_itr) { + if (subscribed_plugin_itr->second->ProcessMessage(msg) != + ProcessResult::PROCESSED) { + LOG4CXX_ERROR(logger_, "Failed process message!"); + } + } + } +} + +const std::string ExtractMethodName(const Json::Value& value) { + const char* kMethod = "method"; + const char* kResult = "result"; + const char* kError = "error"; + const char* kData = "data"; + + if (value.isMember(kMethod)) { + return value.get(kMethod, "").asCString(); + // Response from HMI + } + if (value.isMember(kResult)) { + const Json::Value& result = value.get(kResult, Json::Value()); + return result.get(kMethod, "").asCString(); + } + if (value.isMember(kError)) { + const Json::Value& error = value.get(kError, Json::Value()); + const Json::Value& data = error.get(kData, Json::Value()); + return data.get(kMethod, "").asCString(); + } + LOG4CXX_WARN(logger_, + "Message with HMI protocol version can not be handled by " + "plugin manager, because required 'method' field was not " + "found, or was containing an invalid string."); + return std::string(); +} + +ProcessResult PluginManager::ProcessHMIMessage( + application_manager::MessagePtr msg) { + DCHECK(msg); + if (!msg) { + LOG4CXX_ERROR(logger_, "Null pointer message was received."); + return ProcessResult::CANNOT_PROCESS; + } + + Json::Value value; + Json::Reader reader; + reader.parse(msg->json_message(), value); + + if (application_manager::ProtocolVersion::kHMI == msg->protocol_version()) { + const std::string& msg_method = ExtractMethodName(value); + if (msg_method.empty()) { + return ProcessResult::CANNOT_PROCESS; + } + PluginHMIFunctionsIterator subscribed_plugin_itr = + hmi_subscribers_.find(msg_method); + if (hmi_subscribers_.end() != subscribed_plugin_itr) { + return subscribed_plugin_itr->second->ProcessHMIMessage(msg); + } + } + + return ProcessResult::CANNOT_PROCESS; +} + +bool PluginManager::IsMessageForPlugin(application_manager::MessagePtr msg) { + DCHECK(msg); + if (!msg) { + LOG4CXX_ERROR(logger_, "Null pointer message was received."); + return false; + } + if (application_manager::ProtocolVersion::kUnknownProtocol != + msg->protocol_version() && + application_manager::ProtocolVersion::kHMI != msg->protocol_version()) { + RCFunctionID id = static_cast<RCFunctionID>(msg->function_id()); + return (mobile_subscribers_.find(id) != mobile_subscribers_.end()); + } else { + return false; + } +} + +bool PluginManager::IsHMIMessageForPlugin(application_manager::MessagePtr msg) { + DCHECK(msg); + if (!msg) { + LOG4CXX_ERROR(logger_, "Null pointer message was received."); + return false; + } + + Json::Value value; + Json::Reader reader; + reader.parse(msg->json_message(), value); + if (application_manager::ProtocolVersion::kHMI == msg->protocol_version()) { + std::string msg_method; + // Request or notification from HMI + if (value.isMember("method") && value["method"].isString()) { + msg_method = value["method"].asCString(); + // Response from HMI + } else if (value.isMember("result") && value["result"].isMember("method") && + value["result"]["method"].isString()) { + msg_method = value["result"]["method"].asCString(); + // Error response from HMI + } else if (value.isMember("error") && value["error"].isMember("data") && + value["error"]["data"].isMember("method") && + value["error"]["data"]["method"].isString()) { + msg_method = value["error"]["data"]["method"].asCString(); + } else { + LOG4CXX_WARN(logger_, + "Message with HMI protocol version can not be handled by " + "plugin manager, because required 'method' field was not " + "found, or was containing an invalid string."); + return false; + } + + return (hmi_subscribers_.find(msg_method) != hmi_subscribers_.end()); + } + + return false; +} + +void PluginManager::OnServiceStateChanged(ServiceState state) { + for (PluginsIterator it = plugins_.begin(); plugins_.end() != it; ++it) { + it->second->OnServiceStateChanged(state); + } +} + +void PluginManager::OnHMIResponse(application_manager::MessagePtr msg) { + // TODO(PV) +} + +void PluginManager::OnError(ModuleObserver::Errors error, ModuleID module_id) { + std::string error_string; + switch (error) { + case ModuleObserver::Errors::OUT_OF_MEMORY: + error_string = "Module run out of memory."; + break; + case ModuleObserver::Errors::FS_FAILURE: + error_string = "Plugin failed to run file system operation."; + break; + default: + break; + } + LOG4CXX_ERROR(logger_, + "Error " << error_string << " was received from module " + << module_id); + // TODO(PV) +} + +void PluginManager::RemoveAppExtension(uint32_t app_id) { + for (PluginsIterator it = plugins_.begin(); plugins_.end() != it; ++it) { + it->second->RemoveAppExtension(app_id); + } +} + +bool PluginManager::IsAppForPlugins( + application_manager::ApplicationSharedPtr app) { + DCHECK(app); + if (!app) { + return false; + } + + bool res = false; + for (PluginsIterator it = plugins_.begin(); plugins_.end() != it; ++it) { + res = res || it->second->IsAppForPlugin(app); + } + return res; +} + +bool PluginManager::IsAppForPlugin( + application_manager::ApplicationSharedPtr app, ModuleID module_id) const { + Modules::const_iterator i = plugins_.find(module_id); + return i != plugins_.end() ? i->second->IsAppForPlugin(app) : false; +} + +void PluginManager::OnAppHMILevelChanged( + application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType old_level) { + DCHECK(app); + if (!app) { + return; + } + for (PluginsIterator it = plugins_.begin(); plugins_.end() != it; ++it) { + if (it->second->IsAppForPlugin(app)) { + LOG4CXX_DEBUG(logger_, + "Application " << app->name().AsMBString() << " of plugin " + << it->second->GetModuleID() + << " has changed level from " << old_level + << " to " << app->hmi_level()); + it->second->OnAppHMILevelChanged(app, old_level); + } + } +} + +bool PluginManager::CanAppChangeHMILevel( + application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType new_level) { + DCHECK(app); + if (!app) { + return false; + } + bool result = true; + for (PluginsIterator it = plugins_.begin(); plugins_.end() != it; ++it) { + if (it->second->IsAppForPlugin(app)) { + result = result && it->second->CanAppChangeHMILevel(app, new_level); + LOG4CXX_DEBUG(logger_, + "Application " << app->name().AsMBString() << " of plugin " + << it->second->GetModuleID() << " is " + << (result ? "allowed" : "not allowed") + << " to change level to " << new_level); + } + } + return result; +} + +typedef std::map<ModuleID, ModulePtr>::value_type PluginsValueType; +struct HandleDeviceRemoved { + private: + const connection_handler::DeviceHandle& device_; + + public: + explicit HandleDeviceRemoved(const connection_handler::DeviceHandle& device) + : device_(device) {} + void operator()(PluginsValueType& x) { + x.second->OnDeviceRemoved(device_); + } +}; + +void PluginManager::OnDeviceRemoved( + const connection_handler::DeviceHandle& device) { + LOG4CXX_AUTO_TRACE(logger_); + std::for_each(plugins_.begin(), plugins_.end(), HandleDeviceRemoved(device)); +} + +struct HandleApplicationUnregistered { + private: + const uint32_t app_id_; + + public: + explicit HandleApplicationUnregistered(const uint32_t app_id) + : app_id_(app_id) {} + void operator()(PluginsValueType& x) { + x.second->OnUnregisterApplication(app_id_); + } +}; + +void PluginManager::OnUnregisterApplication(const uint32_t app_id) { + LOG4CXX_AUTO_TRACE(logger_); + std::for_each( + plugins_.begin(), plugins_.end(), HandleApplicationUnregistered(app_id)); +} + +PluginManager::Modules& PluginManager::plugins() { + return plugins_; +} + +} // namespace functional_modules diff --git a/src/components/functional_module/src/settings.cc b/src/components/functional_module/src/settings.cc new file mode 100644 index 0000000000..29a96ba63b --- /dev/null +++ b/src/components/functional_module/src/settings.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "functional_module/settings.h" +#include "config_profile/ini_file.h" + +namespace functional_modules { + +Settings::Settings() : kConfigFile_("smartDeviceLink.ini") { + config_file_ = kConfigFile_; +} + +Settings::~Settings() { + config_file_ = ""; +} + +void Settings::ChangeConfigFile(const std::string& new_path) { + config_file_ = new_path; +} + +std::string Settings::ReadParameter(const std::string& section_name, + const std::string& param_name) const { + std::string result; + char param_string[INI_LINE_LEN + 1]; + param_string[0] = '\0'; + if (0 != profile::ini_read_value(config_file_.c_str(), + section_name.c_str(), + param_name.c_str(), + param_string)) { + result = param_string; + } + return result; +} + +} // namespace functional_modules diff --git a/src/components/functional_module/src/timer/timer_director.cc b/src/components/functional_module/src/timer/timer_director.cc new file mode 100644 index 0000000000..51d7408fcd --- /dev/null +++ b/src/components/functional_module/src/timer/timer_director.cc @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <typeinfo> +#include "functional_module/timer/timer_director.h" +#include "remote_control/rc_module_timer.h" +#include "utils/logger.h" + +namespace functional_modules { + +template <class T> +TimerThreadDelegate<T>::TimerThreadDelegate(ModuleTimer<T>& timer) + : timer_(timer), keep_running_(false) {} + +template <class T> +void TimerThreadDelegate<T>::threadMain() { + if (keep_running_) { + this->exitThreadMain(); + } + { + sync_primitives::AutoLock run_lock(keep_running_lock_); + keep_running_ = true; + } + sync_primitives::AutoLock run_lock(keep_running_lock_); + while (keep_running_) { + const TimeUnit msecs_to_wait = timer_.GetSecondsToNearestTimeout() * 1000; + sync_primitives::ConditionalVariable::WaitStatus wait_status = + keep_running_cond_.WaitFor(run_lock, msecs_to_wait); + if (sync_primitives::ConditionalVariable::kTimeout == wait_status && + keep_running_) { + timer_.CheckTimeout(); + } + } +} + +template <class T> +void TimerThreadDelegate<T>::exitThreadMain() { + if (keep_running_) { + sync_primitives::AutoLock run_lock(keep_running_lock_); + keep_running_ = false; + keep_running_cond_.NotifyOne(); + } +} + +template <class T> +void TimerThreadDelegate<T>::ResetTimer() { + if (keep_running_) { + sync_primitives::AutoLock run_lock(keep_running_lock_); + keep_running_cond_.NotifyOne(); + } +} + +TimerDirector::TimerDirector() {} + +TimerDirector::~TimerDirector() { + UnregisterAllTimers(); +} + +template <class T> +void TimerDirector::RegisterTimer(ModuleTimer<T>& timer) { + std::string type_name = typeid(timer).name(); + std::map<std::string, threads::Thread*>::iterator it = + timer_threads_.find(type_name); + if (timer_threads_.end() != it) { + // Attempt to register timer of already existing type fail. + return; + } + TimerThreadDelegate<T>* delegate = new TimerThreadDelegate<T>(timer); + threads::Thread* thread = threads::CreateThread(type_name.c_str(), delegate); + + const size_t kStackSize = 16384; + if (thread->start(threads::ThreadOptions(kStackSize))) { + timer_threads_.insert(std::make_pair(type_name, thread)); + } else { + // Failed to start timer thread for + } +} + +template void TimerDirector::RegisterTimer<remote_control::TrackableMessage>( + ModuleTimer<remote_control::TrackableMessage>& timer); + +template <class T> +void TimerDirector::UnregisterTimer(const ModuleTimer<T>& timer) { + std::string type_name = typeid(timer).name(); + std::map<std::string, threads::Thread*>::iterator it = + timer_threads_.find(type_name); + if (timer_threads_.end() == it) { + /// Failed to unregister timer that was not registered + return; + } + threads::ThreadDelegate* delegate = it->second->delegate(); + DeleteThread(it->second); + delete delegate; + timer_threads_.erase(it); +} + +template void TimerDirector::UnregisterTimer<remote_control::TrackableMessage>( + const ModuleTimer<remote_control::TrackableMessage>& timer); + +template <class T> +void TimerDirector::ResetTimer(ModuleTimer<T>& timer) { + const std::string type_name = typeid(timer).name(); + std::map<std::string, threads::Thread*>::iterator it = + timer_threads_.find(type_name); + if (timer_threads_.end() == it) { + return; + } + TimerThreadDelegate<T>* delegate = + static_cast<TimerThreadDelegate<T>*>(it->second->delegate()); + delegate->ResetTimer(); +} + +template void TimerDirector::ResetTimer<remote_control::TrackableMessage>( + ModuleTimer<remote_control::TrackableMessage>& timer); + +void TimerDirector::UnregisterAllTimers() { + for (std::map<std::string, threads::Thread*>::iterator it = + timer_threads_.begin(); + timer_threads_.end() != it; + ++it) { + threads::ThreadDelegate* delegate = it->second->delegate(); + DeleteThread(it->second); + delete delegate; + } + timer_threads_.clear(); +} + +} // namespace functional_modules diff --git a/src/components/functional_module/test/CMakeLists.txt b/src/components/functional_module/test/CMakeLists.txt new file mode 100644 index 0000000000..e1cb673252 --- /dev/null +++ b/src/components/functional_module/test/CMakeLists.txt @@ -0,0 +1,56 @@ +include_directories ( + ${LOG4CXX_INCLUDE_DIRECTORY} + ${GMOCK_INCLUDE_DIRECTORY} + ${CMAKE_SOURCE_DIR}/src/components/functional_module/include/ + ${CMAKE_SOURCE_DIR}/src/components/include/ + ${CMAKE_SOURCE_DIR}/src/components/application_manager/include + ${CMAKE_SOURCE_DIR}/src/components/connection_handler/include + ${CMAKE_SOURCE_DIR}/src/components/utils/include + ${CMAKE_SOURCE_DIR}/src/components/policy/include + ${CMAKE_SOURCE_DIR}/src/components/smart_objects/include + ${JSONCPP_INCLUDE_DIRECTORY} + ${CMAKE_BINARY_DIR}/src/components/ + include + plugins +) + +set (LIBRARIES + gtest + gmock + gmock_main + FunctionalModule + dl + ApplicationManager + jsoncpp + Utils + ConfigProfile + gcov +) + +set(SOURCES + ./src/generic_module_test.cc + ./src/plugin_manager_test.cc + ./src/module_timer_test.cc + ./src/settings_test.cc +) + +# use, i.e. don't skip the full RPATH for the build tree +SET(CMAKE_SKIP_BUILD_RPATH FALSE) + +# when building, don't use the install RPATH already +# (but later on when installing) +SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + +SET(RPATH_DIRECTORIES + /usr/local/lib + /usr/local + ${CMAKE_BINARY_DIR}/src/components/utils +) + +SET(CMAKE_INSTALL_RPATH "${RPATH_DIRECTORIES}") + +configure_file("test.ini" "test.ini" COPYONLY) + +add_subdirectory(plugins) + +create_test("function_module_test" "${SOURCES}" "${LIBRARIES}") diff --git a/src/components/functional_module/test/include/driver_generic_module_test.h b/src/components/functional_module/test/include/driver_generic_module_test.h new file mode 100644 index 0000000000..f41a274055 --- /dev/null +++ b/src/components/functional_module/test/include/driver_generic_module_test.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_DRIVER_GENERIC_MODULE_TEST_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_DRIVER_GENERIC_MODULE_TEST_H_ + +#include "functional_module/generic_module.h" + +namespace functional_modules { + +class DriverGenericModuleTest : public GenericModule { + public: + explicit DriverGenericModuleTest(ModuleID module_id) + : GenericModule(module_id) {} + virtual ~DriverGenericModuleTest() {} + virtual PluginInfo GetPluginInfo() const { + PluginInfo info; + info.name = "DriverGenericModuleTest"; + info.version = 1; + return info; + } + virtual ProcessResult ProcessMessage(application_manager::MessagePtr msg) { + NotifyObservers(ModuleObserver::FS_FAILURE); + return ProcessResult::FAILED; + } + virtual ProcessResult ProcessHMIMessage(application_manager::MessagePtr msg) { + return ProcessResult::PROCESSED; + } + virtual void RemoveAppExtension(uint32_t app_id) {} + virtual void RemoveAppExtensions() {} + bool IsAppForPlugin(application_manager::ApplicationSharedPtr app) { + return true; + } + + void OnAppHMILevelChanged(application_manager::ApplicationSharedPtr, + mobile_apis::HMILevel::eType) {} + + const Observers& observers() { + return observers_; + } + + void OnDeviceRemoved(const connection_handler::DeviceHandle&) {} + + void OnUnregisterApplication(const uint32_t app_id) {} +}; + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_DRIVER_GENERIC_MODULE_TEST_H_ diff --git a/src/components/functional_module/test/include/mock_application.h b/src/components/functional_module/test/include/mock_application.h new file mode 100644 index 0000000000..e73851094e --- /dev/null +++ b/src/components/functional_module/test/include/mock_application.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_APPLICATION_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_APPLICATION_H_ + +#include "gmock/gmock.h" +#include "application_manager/application.h" +#include "application_manager/usage_statistics.h" +#include "smart_objects/smart_object.h" + +namespace application_manager { + +class MockApplication : public Application { + public: + MOCK_CONST_METHOD0(active_message, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(curHash, const std::string&()); + MOCK_METHOD0(UpdateHash, void()); + MOCK_METHOD0(CloseActiveMessage, void()); + MOCK_CONST_METHOD0(IsFullscreen, bool()); + MOCK_METHOD0(MakeFullscreen, bool()); + MOCK_CONST_METHOD0(IsAudible, bool()); + MOCK_METHOD0(MakeNotAudible, void()); + MOCK_CONST_METHOD0(allowed_support_navigation, bool()); + MOCK_METHOD1(set_allowed_support_navigation, void(bool allow)); + MOCK_CONST_METHOD0(hmi_supports_navi_streaming, bool()); + MOCK_METHOD1(set_hmi_supports_navi_streaming, void(const bool& supports)); + MOCK_CONST_METHOD0(app_allowed, bool()); + MOCK_CONST_METHOD0(has_been_activated, bool()); + MOCK_CONST_METHOD0(version, const Version&()); + MOCK_METHOD1(set_hmi_application_id, void(uint32_t hmi_app_id)); + MOCK_CONST_METHOD0(hmi_app_id, uint32_t()); + MOCK_CONST_METHOD0(app_id, uint32_t()); + MOCK_CONST_METHOD0(name, const std::string&()); + MOCK_CONST_METHOD0(folder_name, const std::string()); + MOCK_CONST_METHOD0(is_media_application, bool()); + MOCK_CONST_METHOD0(hmi_level, const mobile_api::HMILevel::eType&()); + MOCK_CONST_METHOD0(put_file_in_none_count, const uint32_t()); + MOCK_CONST_METHOD0(delete_file_in_none_count, const uint32_t()); + MOCK_CONST_METHOD0(list_files_in_none_count, const uint32_t()); + MOCK_CONST_METHOD0(system_context, const mobile_api::SystemContext::eType&()); + MOCK_CONST_METHOD0(audio_streaming_state, + const mobile_api::AudioStreamingState::eType&()); + MOCK_CONST_METHOD0(app_icon_path, const std::string&()); + MOCK_CONST_METHOD0(device, connection_handler::DeviceHandle()); + MOCK_METHOD1(set_tts_speak_state, void(bool state_tts_speak)); + MOCK_METHOD0(tts_speak_state, bool()); + MOCK_METHOD1(set_tts_properties_in_none, void(bool active)); + MOCK_METHOD0(tts_properties_in_none, bool()); + MOCK_METHOD1(set_tts_properties_in_full, void(bool active)); + MOCK_METHOD0(tts_properties_in_full, bool()); + MOCK_METHOD1(set_version, void(const Version& version)); + MOCK_METHOD1(set_name, void(const std::string& name)); + MOCK_METHOD1(set_is_media_application, void(bool is_media)); + MOCK_METHOD1(set_hmi_level, + void(const mobile_api::HMILevel::eType& hmi_level)); + MOCK_METHOD0(increment_put_file_in_none_count, void()); + MOCK_METHOD0(increment_delete_file_in_none_count, void()); + MOCK_METHOD0(increment_list_files_in_none_count, void()); + MOCK_METHOD1(set_system_context, + void(const mobile_api::SystemContext::eType& system_context)); + MOCK_METHOD1(set_audio_streaming_state, + void(const mobile_api::AudioStreamingState::eType& state)); + MOCK_METHOD1(set_app_icon_path, bool(const std::string& file_name)); + MOCK_METHOD1(set_app_allowed, void(const bool& allowed)); + MOCK_METHOD1(set_device, void(connection_handler::DeviceHandle device)); + MOCK_CONST_METHOD0(get_grammar_id, uint32_t()); + MOCK_METHOD1(set_grammar_id, void(uint32_t value)); + MOCK_METHOD1(set_protocol_version, + void(const ProtocolVersion& protocol_version)); + MOCK_CONST_METHOD0(protocol_version, ProtocolVersion()); + MOCK_METHOD1(AddFile, bool(AppFile& file)); + MOCK_CONST_METHOD0(getAppFiles, const AppFilesMap&()); + MOCK_METHOD1(UpdateFile, bool(AppFile& file)); + MOCK_METHOD1(DeleteFile, bool(const std::string& file_name)); + MOCK_METHOD1(GetFile, const AppFile*(const std::string& file_name)); + MOCK_METHOD1(SubscribeToButton, + bool(mobile_apis::ButtonName::eType btn_name)); + MOCK_METHOD1(IsSubscribedToButton, + bool(mobile_apis::ButtonName::eType btn_name)); + MOCK_METHOD1(UnsubscribeFromButton, + bool(mobile_apis::ButtonName::eType btn_name)); + MOCK_METHOD1(SubscribeToIVI, bool(uint32_t vehicle_info_type_)); + MOCK_METHOD1(IsSubscribedToIVI, bool(uint32_t vehicle_info_type_)); + MOCK_METHOD1(UnsubscribeFromIVI, bool(uint32_t vehicle_info_type_)); + MOCK_METHOD2(IsCommandLimitsExceeded, + bool(mobile_apis::FunctionID::eType cmd_id, + TLimitSource source)); + MOCK_METHOD0(usage_report, UsageStatistics&()); + MOCK_METHOD2(SubscribeToSoftButtons, + void(int32_t cmd_id, const SoftButtonID& softbuttons_id)); + MOCK_METHOD1(IsSubscribedToSoftButton, bool(const uint32_t softbutton_id)); + MOCK_METHOD1(UnsubscribeFromSoftButtons, void(int32_t cmd_id)); + MOCK_METHOD1(QueryInterface, AppExtensionPtr(AppExtensionUID uid)); + MOCK_METHOD1(AddExtension, bool(AppExtensionPtr extention)); + MOCK_METHOD1(RemoveExtension, bool(AppExtensionUID uid)); + MOCK_METHOD0(RemoveExtensions, void()); + MOCK_CONST_METHOD0(help_prompt, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(timeout_prompt, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(vr_help_title, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(vr_help, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(tbt_state, const mobile_api::TBTState::eType&()); + MOCK_CONST_METHOD0(show_command, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(tbt_show_command, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(SubscribedButtons, + const std::set<mobile_apis::ButtonName::eType>&()); + MOCK_CONST_METHOD0(SubscribesIVI, const std::set<uint32_t>&()); + MOCK_CONST_METHOD0(keyboard_props, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(menu_title, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(menu_icon, const smart_objects::SmartObject*()); + MOCK_METHOD1(set_help_prompt, + void(const smart_objects::SmartObject& help_prompt)); + MOCK_METHOD1(set_timeout_prompt, + void(const smart_objects::SmartObject& timeout_prompt)); + MOCK_METHOD1(set_vr_help_title, + void(const smart_objects::SmartObject& vr_help_title)); + MOCK_METHOD0(reset_vr_help_title, void()); + MOCK_METHOD1(set_vr_help, void(const smart_objects::SmartObject& vr_help)); + MOCK_METHOD0(reset_vr_help, void()); + MOCK_METHOD1(set_tbt_state, + void(const mobile_api::TBTState::eType& tbt_state)); + MOCK_METHOD1(set_show_command, + void(const smart_objects::SmartObject& show_command)); + MOCK_METHOD1(set_tbt_show_command, + void(const smart_objects::SmartObject& tbt_show)); + MOCK_METHOD1(set_keyboard_props, + void(const smart_objects::SmartObject& keyboard_props)); + MOCK_METHOD1(set_menu_title, + void(const smart_objects::SmartObject& menu_title)); + MOCK_METHOD1(set_menu_icon, + void(const smart_objects::SmartObject& menu_icon)); + MOCK_METHOD2(AddCommand, + void(uint32_t cmd_id, + const smart_objects::SmartObject& command)); + MOCK_METHOD1(RemoveCommand, void(uint32_t cmd_id)); + MOCK_METHOD1(FindCommand, smart_objects::SmartObject*(uint32_t cmd_id)); + MOCK_METHOD2(AddSubMenu, + void(uint32_t menu_id, const smart_objects::SmartObject& menu)); + MOCK_METHOD1(RemoveSubMenu, void(uint32_t menu_id)); + MOCK_CONST_METHOD1(FindSubMenu, + smart_objects::SmartObject*(uint32_t menu_id)); + MOCK_METHOD1(IsSubMenuNameAlreadyExist, bool(const std::string& name)); + MOCK_METHOD2(AddChoiceSet, + void(uint32_t choice_set_id, + const smart_objects::SmartObject& choice_set)); + MOCK_METHOD1(RemoveChoiceSet, void(uint32_t choice_set_id)); + MOCK_METHOD1(FindChoiceSet, + smart_objects::SmartObject*(uint32_t choice_set_id)); + MOCK_METHOD2(AddPerformInteractionChoiceSet, + void(uint32_t choice_set_id, + const smart_objects::SmartObject& choice_set)); + MOCK_METHOD0(DeletePerformInteractionChoiceSetMap, void()); + MOCK_CONST_METHOD0(performinteraction_choice_set_map, + DataAccessor<PerformChoiceSetMap>()); + MOCK_CONST_METHOD1(FindPerformInteractionChoiceSet, + smart_objects::SmartObject*(uint32_t choice_set_id)); + MOCK_CONST_METHOD0(commands_map, DataAccessor<CommandsMap>()); + MOCK_CONST_METHOD0(sub_menu_map, DataAccessor<SubMenuMap>()); + MOCK_CONST_METHOD0(choice_set_map, DataAccessor<ChoiceSetMap>()); + MOCK_METHOD1(set_perform_interaction_active, void(uint32_t active)); + MOCK_CONST_METHOD0(is_perform_interaction_active, uint32_t()); + MOCK_METHOD1(set_perform_interaction_ui_corrid, void(uint32_t choice)); + MOCK_CONST_METHOD0(perform_interaction_ui_corrid, uint32_t()); + MOCK_METHOD1(set_perform_interaction_mode, void(int32_t mode)); + MOCK_CONST_METHOD0(perform_interaction_mode, int32_t()); + MOCK_METHOD1(set_reset_global_properties_active, void(bool active)); + MOCK_CONST_METHOD0(is_reset_global_properties_active, bool()); + MOCK_CONST_METHOD0(app_types, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(vr_synonyms, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(mobile_app_id, std::string()); + MOCK_CONST_METHOD0(tts_name, const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(ngn_media_screen_name, + const smart_objects::SmartObject*()); + MOCK_CONST_METHOD0(language, const mobile_api::Language::eType&()); + MOCK_CONST_METHOD0(ui_language, const mobile_api::Language::eType&()); + MOCK_METHOD1(set_app_types, + void(const smart_objects::SmartObject& app_types)); + MOCK_METHOD1(set_vr_synonyms, + void(const smart_objects::SmartObject& vr_synonyms)); + MOCK_METHOD1(set_mobile_app_id, + void(const smart_objects::SmartObject& mobile_app_id)); + MOCK_METHOD1(set_tts_name, void(const smart_objects::SmartObject& tts_name)); + MOCK_METHOD1(set_ngn_media_screen_name, + void(const smart_objects::SmartObject& ngn_name)); + MOCK_METHOD1(set_language, void(const mobile_api::Language::eType& language)); + MOCK_METHOD1(set_ui_language, + void(const mobile_api::Language::eType& ui_language)); + MOCK_METHOD1(load_global_properties, + void(const smart_objects::SmartObject& so)); + MOCK_METHOD1(set_mobile_app_id, void(const std::string& mobile_app_id)); + MOCK_METHOD0(ChangeSupportingAppHMIType, void()); + MOCK_CONST_METHOD0(is_navi, bool()); + MOCK_METHOD1(set_is_navi, void(bool allow)); + MOCK_CONST_METHOD0(hmi_supports_navi_video_streaming, bool()); + MOCK_METHOD1(set_hmi_supports_navi_video_streaming, void(bool supports)); + MOCK_CONST_METHOD0(hmi_supports_navi_audio_streaming, bool()); + MOCK_METHOD1(set_hmi_supports_navi_audio_streaming, void(bool supports)); + MOCK_CONST_METHOD0(is_voice_communication_supported, bool()); + MOCK_METHOD1(set_voice_communication_supported, void(bool)); + MOCK_METHOD1(set_activated, bool(bool is_active)); + MOCK_CONST_METHOD0(is_foreground, bool()); + MOCK_METHOD1(set_foreground, void(bool is_foreground)); + MOCK_CONST_METHOD0(IsAudioApplication, bool()); + MOCK_CONST_METHOD0(video_stream_retry_active, bool()); + MOCK_METHOD1(set_video_stream_retry_active, void(bool active)); + MOCK_CONST_METHOD0(audio_stream_retry_active, bool()); + MOCK_METHOD1(set_audio_stream_retry_active, void(bool active)); + MOCK_METHOD0(OnVideoStreamRetry, void()); + MOCK_METHOD0(OnAudioStreamRetry, void()); + MOCK_METHOD1(SubscribeToInteriorVehicleData, + bool(smart_objects::SmartObject module)); + MOCK_METHOD1(IsSubscribedToInteriorVehicleData, + bool(smart_objects::SmartObject module)); + MOCK_METHOD1(UnsubscribeFromInteriorVehicleData, + bool(smart_objects::SmartObject module)); +}; + +} // namespace application_manager + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_APPLICATION_H_ diff --git a/src/components/functional_module/test/include/mock_module_observer.h b/src/components/functional_module/test/include/mock_module_observer.h new file mode 100644 index 0000000000..bfa5117b29 --- /dev/null +++ b/src/components/functional_module/test/include/mock_module_observer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_MODULE_OBSERVER_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_MODULE_OBSERVER_H_ + +#include "gmock/gmock.h" +#include "functional_module/module_observer.h" + +namespace functional_modules { + +class MockModuleObserver : public ModuleObserver { + public: + MOCK_METHOD2(OnError, void(Errors error, ModuleID module_id)); + int ObserverMethod() { + return 13; + } +}; + +} // namespace functional_modules + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_MODULE_OBSERVER_H_ diff --git a/src/components/functional_module/test/include/mock_service.h b/src/components/functional_module/test/include/mock_service.h new file mode 100644 index 0000000000..560fa91359 --- /dev/null +++ b/src/components/functional_module/test/include/mock_service.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_SERVICE_H_ +#define SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_SERVICE_H_ + +#include "gmock/gmock.h" +#include "application_manager/service.h" + +namespace application_manager { + +class MockService : public Service { + public: + MOCK_METHOD1(CheckPolicyPermissions, + mobile_apis::Result::eType(MessagePtr msg)); + MOCK_METHOD1(GetApplication, ApplicationSharedPtr(ApplicationId app_id)); + MOCK_METHOD1(SendMessageToHMI, void(const MessagePtr& message)); + MOCK_METHOD1(SendMessageToMobile, void(const MessagePtr& message)); + MOCK_METHOD0(GetNextCorrelationID, uint32_t()); + MOCK_METHOD1(GetApplications, + std::vector<ApplicationSharedPtr>(AppExtensionUID)); + MOCK_METHOD1(SubscribeToHMINotification, + void(const std::string& hmi_notification)); + MOCK_METHOD2(ChangeNotifyHMILevel, + void(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level)); + MOCK_METHOD2(NotifyHMIAboutHMILevel, + void(ApplicationSharedPtr app, + mobile_apis::HMILevel::eType level)); + MOCK_METHOD4(CheckAccess, + TypeAccess(const ApplicationId& app_id, + const std::string& module, + const std::string& rpc, + const std::vector<std::string>& params)); + MOCK_METHOD2(CheckModule, + bool(const ApplicationId& app_id, const std::string& module)); + MOCK_METHOD3(SetAccess, + void(const ApplicationId& app_id, + const std::string& module, + bool allowed)); + MOCK_METHOD1(ResetAccess, void(const ApplicationId& app_id)); + MOCK_METHOD1(ResetAccess, void(const std::string& module)); + MOCK_METHOD1(GetDeviceHandlerById, uint32_t(const std::string& device_id)); + MOCK_METHOD1(SetPrimaryDevice, void(const uint32_t dev_id)); + MOCK_METHOD0(ResetPrimaryDevice, void()); + MOCK_CONST_METHOD0(PrimaryDevice, uint32_t()); + MOCK_METHOD1(SetRemoteControl, void(bool enabled)); + MOCK_METHOD1(RemoveHMIFakeParameters, + void(application_manager::MessagePtr& message)); + MOCK_CONST_METHOD0(IsRemoteControlAllowed, bool()); + + MOCK_CONST_METHOD1(IsRemoteControlApplication, + bool(ApplicationSharedPtr app)); + MOCK_CONST_METHOD2(GetModuleTypes, + bool(const std::string& application_id, + std::vector<std::string>* modules)); + MOCK_METHOD1(ValidateMessageBySchema, + application_manager::MessageValidationResult( + const application_manager::Message& message)); +}; +} +// namespace application_manager + +#endif // SRC_COMPONENTS_FUNCTIONAL_MODULE_TEST_INCLUDE_MOCK_SERVICE_H_ diff --git a/src/components/functional_module/test/include/module_timer_test.h b/src/components/functional_module/test/include/module_timer_test.h new file mode 100644 index 0000000000..456346b544 --- /dev/null +++ b/src/components/functional_module/test/include/module_timer_test.h @@ -0,0 +1,56 @@ +#include "utils/macro.h" +#include "functional_module/timer/module_timer.h" + +namespace functional_modules { + +class TestTrackable : public Trackable { + public: + explicit TestTrackable(TimeUnit interval = 0) + : Trackable(), custom_interval_(interval) {} + + virtual TimeUnit custom_interval() const { + return custom_interval_; + } + + bool operator==(const TestTrackable& other) const { + return custom_interval_ == other.custom_interval_; + } + + private: + TimeUnit custom_interval_; +}; + +class ModuleTimerTest { + public: + ModuleTimerTest(ModuleTimer<TestTrackable>& timer) : timer_(timer) {} + + TimeUnit period() const { + return timer_.period_; + } + + int observers_size() const { + return timer_.observers_.size(); + } + + int trackables_size() const { + return timer_.trackables_.size(); + } + + TestTrackable trackable(const TestTrackable& track) const { + return *std::find( + timer_.trackables_.begin(), timer_.trackables_.end(), track); + } + + TimeUnit current_time() const { + return timer_.CurrentTime(); + } + + private: + ModuleTimer<TestTrackable>& timer_; +}; + +class MockTimerObserver : public TimerObserver<TestTrackable> { + public: + MOCK_METHOD1(OnTimeoutTriggered, void(const TestTrackable& expired)); +}; +} // namespace functional_modules diff --git a/src/components/functional_module/test/plugins/CMakeLists.txt b/src/components/functional_module/test/plugins/CMakeLists.txt new file mode 100644 index 0000000000..7afe8387b8 --- /dev/null +++ b/src/components/functional_module/test/plugins/CMakeLists.txt @@ -0,0 +1,17 @@ +set(target PluginMock) + +include_directories ( + ${LOG4CXX_INCLUDE_DIRECTORY} + ${GMOCK_INCLUDE_DIRECTORY} + ${CMAKE_SOURCE_DIR}/src/components/functional_module/include/ + ${CMAKE_SOURCE_DIR}/src/components/include/ + ${JSONCPP_INCLUDE_DIRECTORY} +) + +set(SOURCES + ./mock_generic_module.cc +) + +add_library(${target} SHARED ${SOURCES}) +target_link_libraries(${target}) +add_dependencies(${target} MOBILE_API HMI_API) diff --git a/src/components/functional_module/test/plugins/mock_generic_module.cc b/src/components/functional_module/test/plugins/mock_generic_module.cc new file mode 100644 index 0000000000..dcf6d7d4fe --- /dev/null +++ b/src/components/functional_module/test/plugins/mock_generic_module.cc @@ -0,0 +1,23 @@ +#include "mock_generic_module.h" + +using functional_modules::GenericModule; +using functional_modules::RCFunctionID; +using functional_modules::PluginInfo; + +using ::testing::_; +using ::testing::Return; + +MockGenericModule::MockGenericModule() : GenericModule(19) { + PluginInfo info; + info.name = "MockGenericModule"; + info.version = 1; + info.rc_function_list.push_back(static_cast<RCFunctionID>(101)); + info.hmi_function_list.push_back("HMI-Func-1"); + + EXPECT_CALL(*this, GetPluginInfo()).Times(2).WillRepeatedly(Return(info)); + EXPECT_CALL(*this, set_service(_)).Times(1); +} + +extern "C" GenericModule* Create() { + return new MockGenericModule(); +} diff --git a/src/components/functional_module/test/plugins/mock_generic_module.h b/src/components/functional_module/test/plugins/mock_generic_module.h new file mode 100644 index 0000000000..aef0a68f19 --- /dev/null +++ b/src/components/functional_module/test/plugins/mock_generic_module.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEST_COMPONENTS_FUNCTIONAL_MODULE_PLUGINS_MOCK_GENERIC_MODULE_H_ +#define TEST_COMPONENTS_FUNCTIONAL_MODULE_PLUGINS_MOCK_GENERIC_MODULE_H_ + +#include "gmock/gmock.h" +#include "functional_module/generic_module.h" + +using functional_modules::GenericModule; +using functional_modules::PluginInfo; +using functional_modules::ProcessResult; +using functional_modules::ServiceState; + +using ::testing::_; +using ::testing::Return; + +class MockGenericModule : public GenericModule { + public: + MockGenericModule(); + MOCK_CONST_METHOD0(GetPluginInfo, PluginInfo()); + MOCK_METHOD1(set_service, void(application_manager::ServicePtr service)); + MOCK_METHOD0(service, application_manager::ServicePtr()); + MOCK_METHOD1(ProcessMessage, + ProcessResult(application_manager::MessagePtr msg)); + MOCK_METHOD1(ProcessHMIMessage, + ProcessResult(application_manager::MessagePtr msg)); + MOCK_METHOD1(OnServiceStateChanged, void(ServiceState state)); + MOCK_METHOD1(RemoveAppExtension, void(uint32_t app_id)); + MOCK_METHOD1(IsAppForPlugin, + bool(application_manager::ApplicationSharedPtr app)); + MOCK_METHOD2(OnAppHMILevelChanged, + void(application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType old_level)); + MOCK_METHOD1(OnDeviceRemoved, + void(const connection_handler::DeviceHandle& device)); + MOCK_METHOD1(OnUnregisterApplication, void(const uint32_t app_id)); + MOCK_METHOD2(CanAppChangeHMILevel, + bool(application_manager::ApplicationSharedPtr app, + mobile_apis::HMILevel::eType new_level)); + MOCK_METHOD0(RemoveAppExtensions, void()); +}; + +#endif // TEST_COMPONENTS_FUNCTIONAL_MODULE_PLUGINS_MOCK_GENERIC_MODULE_H_ diff --git a/src/components/functional_module/test/src/generic_module_test.cc b/src/components/functional_module/test/src/generic_module_test.cc new file mode 100644 index 0000000000..b052050cdb --- /dev/null +++ b/src/components/functional_module/test/src/generic_module_test.cc @@ -0,0 +1,137 @@ +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "driver_generic_module_test.h" + +#include "mock_module_observer.h" +#include "mock_service.h" + +using application_manager::ServicePtr; +using application_manager::MockService; + +using ::testing::_; + +namespace functional_modules { + +TEST(GenericModuleTest, SetService) { + DriverGenericModuleTest module(18); + MockService* mock_service = new MockService(); + ServicePtr exp_service(mock_service); + + module.set_service(exp_service); + ServicePtr out_service = module.service(); + + EXPECT_EQ(exp_service.get(), out_service.get()); +} + +TEST(GenericModuleTest, OnServiceStateChangedFail) { + DriverGenericModuleTest module(18); + MockService* mock_service = new MockService(); + ServicePtr exp_service(mock_service); + module.set_service(exp_service); + + EXPECT_CALL(*mock_service, SubscribeToHMINotification(_)).Times(0); + + module.OnServiceStateChanged(LOWVOLTAGE); +} + +TEST(GenericModuleTest, OnServiceStateChangedPass) { + DriverGenericModuleTest module(18); + MockService* mock_service = new MockService(); + ServicePtr exp_service(mock_service); + module.set_service(exp_service); + + EXPECT_CALL(*mock_service, SubscribeToHMINotification(_)).Times(2); + + module.OnServiceStateChanged(HMI_ADAPTER_INITIALIZED); +} + +TEST(GenericModuleTest, AddObserver) { + DriverGenericModuleTest module(18); + MockModuleObserver observer; + module.AddObserver(&observer); + const DriverGenericModuleTest::Observers& full = module.observers(); + ASSERT_EQ(1u, full.size()); + EXPECT_EQ(&observer, full[0]); +} + +TEST(GenericModuleTest, RemoveObserver) { + DriverGenericModuleTest module(18); + MockModuleObserver* observer = new MockModuleObserver(); + module.AddObserver(observer); + + module.RemoveObserver(observer); + const DriverGenericModuleTest::Observers& empty = module.observers(); + ASSERT_TRUE(empty.empty()); + delete observer; +} + +TEST(GenericModuleTest, EmptyRemoveObserver) { + DriverGenericModuleTest module(18); + MockModuleObserver* observer = new MockModuleObserver(); + module.RemoveObserver(observer); + const DriverGenericModuleTest::Observers& empty = module.observers(); + ASSERT_TRUE(empty.empty()); + delete observer; +} + +TEST(GenericModuleTest, WrongRemoveObserver) { + DriverGenericModuleTest module(18); + MockModuleObserver observer; + module.AddObserver(&observer); + + MockModuleObserver* wrong_observer = new MockModuleObserver(); + module.RemoveObserver(wrong_observer); + const DriverGenericModuleTest::Observers& empty = module.observers(); + ASSERT_EQ(1u, empty.size()); + EXPECT_EQ(&observer, empty[0]); + delete wrong_observer; +} + +TEST(GenericModuleTest, CrashRemovedObserver) { + DriverGenericModuleTest module(18); + MockModuleObserver* observer = new MockModuleObserver(); + module.AddObserver(observer); + EXPECT_EQ(13, observer->ObserverMethod()); + module.RemoveObserver(observer); + EXPECT_EQ(13, observer->ObserverMethod()); + delete observer; + MockModuleObserver second_observer; + module.AddObserver(&second_observer); + EXPECT_EQ(13, second_observer.ObserverMethod()); + module.RemoveObserver(&second_observer); + EXPECT_EQ(13, second_observer.ObserverMethod()); +} + +TEST(GenericModuleTest, NotifyObservers) { + DriverGenericModuleTest module(3); + MockModuleObserver observer; + module.AddObserver(&observer); + + EXPECT_CALL(observer, OnError(ModuleObserver::FS_FAILURE, 3)).Times(1); + + application_manager::MessagePtr message; + module.ProcessMessage(message); +} + +TEST(GenericModuleTest, NotifyObserversComplex) { + DriverGenericModuleTest module(3); + MockModuleObserver observer_1; + module.AddObserver(&observer_1); + MockModuleObserver observer_2; + module.AddObserver(&observer_2); + + EXPECT_CALL(observer_1, OnError(ModuleObserver::FS_FAILURE, 3)).Times(1); + EXPECT_CALL(observer_2, OnError(ModuleObserver::FS_FAILURE, 3)).Times(1); + + application_manager::MessagePtr message; + module.ProcessMessage(message); + + module.RemoveObserver(&observer_1); + EXPECT_CALL(observer_1, OnError(ModuleObserver::FS_FAILURE, 3)).Times(0); + EXPECT_CALL(observer_2, OnError(ModuleObserver::FS_FAILURE, 3)).Times(1); + + module.ProcessMessage(message); +} + +} // namespace functional_modules diff --git a/src/components/functional_module/test/src/module_timer_test.cc b/src/components/functional_module/test/src/module_timer_test.cc new file mode 100644 index 0000000000..668c3e2955 --- /dev/null +++ b/src/components/functional_module/test/src/module_timer_test.cc @@ -0,0 +1,123 @@ +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "module_timer_test.h" + +namespace functional_modules { + +TEST(ModuleTimerTest, set_period) { + ModuleTimer<TestTrackable> timer; + timer.set_period(10000); + ModuleTimerTest test(timer); + EXPECT_EQ(10000u, test.period()); +} + +TEST(ModuleTimerTest, add_observer) { + ModuleTimer<TestTrackable> timer; + ModuleTimerTest test(timer); + for (size_t i = 0; i < 5; ++i) { + MockTimerObserver observer; + timer.AddObserver(&observer); + } + EXPECT_EQ(5, test.observers_size()); +} + +TEST(ModuleTimerTest, remove_observer) { + ModuleTimer<TestTrackable> timer; + ModuleTimerTest test(timer); + + MockTimerObserver observer; + timer.AddObserver(&observer); + MockTimerObserver observer2; + timer.AddObserver(&observer2); + timer.RemoveObserver(&observer); + EXPECT_EQ(1, test.observers_size()); + MockTimerObserver observer3; + timer.RemoveObserver(&observer3); + EXPECT_EQ(1, test.observers_size()); + timer.RemoveObserver(&observer2); + EXPECT_EQ(0, test.observers_size()); +} + +TEST(ModuleTimerTest, start) { + ModuleTimer<TestTrackable> timer; + ModuleTimerTest test(timer); + timer.set_period(1); + MockTimerObserver observer; + timer.AddObserver(&observer); + TestTrackable track; + timer.AddTrackable(track); + sleep(2); + EXPECT_CALL(observer, OnTimeoutTriggered(track)).Times(1); + timer.CheckTimeout(); + EXPECT_EQ(0, test.trackables_size()); + timer.set_period(4); + timer.AddTrackable(track); + sleep(2); + EXPECT_CALL(observer, OnTimeoutTriggered(track)).Times(0); + timer.CheckTimeout(); + EXPECT_EQ(1, test.trackables_size()); + TestTrackable track2(1); + timer.AddTrackable(track2); + timer.AddTrackable(track); + sleep(2); + EXPECT_CALL(observer, OnTimeoutTriggered(track2)).Times(1); + EXPECT_CALL(observer, OnTimeoutTriggered(track)).Times(0); + timer.CheckTimeout(); + EXPECT_EQ(1, test.trackables_size()); +} + +TEST(ModuleTimerTest, add_trackable) { + ModuleTimer<TestTrackable> timer; + ModuleTimerTest test(timer); + timer.AddTrackable(TestTrackable()); + ASSERT_EQ(1, test.trackables_size()); + // adding the same object twice + timer.AddTrackable(TestTrackable()); + EXPECT_EQ(1, test.trackables_size()); + // adding another object + TestTrackable track(3); + timer.AddTrackable(track); + ASSERT_EQ(2, test.trackables_size()); + EXPECT_TRUE(test.trackable(track).start_time() - test.current_time() < 1); + timer.AddTrackable(track); + sleep(3); + EXPECT_TRUE(test.current_time() - test.trackable(track).start_time() < 4 && + test.current_time() - test.trackable(track).start_time() > 2); +} + +TEST(ModuleTimerTest, remove_trackable) { + ModuleTimer<TestTrackable> timer; + ModuleTimerTest test(timer); + EXPECT_EQ(0, test.trackables_size()); + TestTrackable track1; + TestTrackable track2(1); + timer.AddTrackable(track1); + timer.AddTrackable(track2); + EXPECT_EQ(2, test.trackables_size()); + timer.RemoveTrackable(track2); + ASSERT_EQ(1, test.trackables_size()); + TestTrackable track3(2); + timer.RemoveTrackable(track3); + ASSERT_EQ(1, test.trackables_size()); + timer.RemoveTrackable(track1); + ASSERT_EQ(0, test.trackables_size()); +} + +TEST(ModuleTimerTest, notify) { + ModuleTimer<TestTrackable> timer; + ModuleTimerTest test(timer); + timer.set_period(1); + MockTimerObserver observer; + timer.AddObserver(&observer); + TestTrackable track; + timer.AddTrackable(track); + TestTrackable track2(2); + timer.AddTrackable(track2); + sleep(2); + EXPECT_CALL(observer, OnTimeoutTriggered(track)).Times(1); + EXPECT_CALL(observer, OnTimeoutTriggered(track2)).Times(0); + timer.CheckTimeout(); + EXPECT_EQ(1, test.trackables_size()); +} + +} // namespace functional_modules diff --git a/src/components/functional_module/test/src/plugin_manager_test.cc b/src/components/functional_module/test/src/plugin_manager_test.cc new file mode 100644 index 0000000000..09a44ceb58 --- /dev/null +++ b/src/components/functional_module/test/src/plugin_manager_test.cc @@ -0,0 +1,206 @@ +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "functional_module/plugin_manager.h" +#include "mock_generic_module.h" +#include "mock_service.h" +#include "application_manager/mock_application.h" +#include "utils/shared_ptr.h" +#include "utils/make_shared.h" + +using application_manager::Message; +using application_manager::ProtocolVersion; +using application_manager::MockService; +using ::testing::NiceMock; +using ::testing::Expectation; +using ::testing::ReturnRef; + +namespace functional_modules { + +class PluginManagerTest : public ::testing::Test { + public: + PluginManagerTest() + : manager(utils::MakeShared<PluginManager>()) + , service(utils::MakeShared<MockService>()) {} + + protected: + utils::SharedPtr<PluginManager> manager; + utils::SharedPtr<MockService> service; + MockGenericModule* module; + + void SetUp() OVERRIDE { + manager->SetServiceHandler(service); + + ASSERT_EQ(1, manager->LoadPlugins("./plugins/")); + const PluginManager::Modules& plugins = manager->plugins(); + PluginManager::Modules::const_iterator i = plugins.begin(); + module = static_cast<MockGenericModule*>(i->second.get()); + } +}; + +TEST_F(PluginManagerTest, ChangePluginsState) { + ServiceState kState = ServiceState::SUSPENDED; + EXPECT_CALL(*module, OnServiceStateChanged(kState)); + manager->OnServiceStateChanged(kState); +} + +TEST_F(PluginManagerTest, IsMessageForPluginFail) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + msg->set_protocol_version(ProtocolVersion::kUnknownProtocol); + EXPECT_FALSE(manager->IsMessageForPlugin(msg)); +} + +TEST_F(PluginManagerTest, IsMessageForPluginPass) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + msg->set_protocol_version(ProtocolVersion::kV3); + msg->set_function_id(101); // see MockGenericModule + EXPECT_TRUE(manager->IsMessageForPlugin(msg)); +} + +TEST_F(PluginManagerTest, IsHMIMessageForPluginFail) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + msg->set_protocol_version(ProtocolVersion::kUnknownProtocol); + EXPECT_FALSE(manager->IsHMIMessageForPlugin(msg)); +} + +TEST_F(PluginManagerTest, IsHMIMessageForPluginPass) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + msg->set_protocol_version(ProtocolVersion::kHMI); + std::string json = "{\"method\": \"HMI-Func-1\"}"; // see MockGenericModule + msg->set_json_message(json); + EXPECT_TRUE(manager->IsHMIMessageForPlugin(msg)); +} + +TEST_F(PluginManagerTest, RemoveAppExtension) { + const uint32_t kAppId = 2; + EXPECT_CALL(*module, RemoveAppExtension(kAppId)).Times(1); + manager->RemoveAppExtension(kAppId); +} + +TEST_F(PluginManagerTest, ProcessMessageFail) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + application_manager::MessagePtr message(msg); + msg->set_protocol_version(ProtocolVersion::kUnknownProtocol); + EXPECT_CALL(*module, ProcessMessage(message)).Times(0); + manager->ProcessMessage(message); +} + +TEST_F(PluginManagerTest, ProcessMessagePass) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + application_manager::MessagePtr message(msg); + msg->set_protocol_version(ProtocolVersion::kV3); + msg->set_function_id(101); // see MockGenericModule + EXPECT_CALL(*module, ProcessMessage(message)) + .Times(1) + .WillOnce(Return(ProcessResult::PROCESSED)); + manager->ProcessMessage(message); +} + +TEST_F(PluginManagerTest, ProcessHMIMessageFail) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + application_manager::MessagePtr message(msg); + message->set_protocol_version(ProtocolVersion::kUnknownProtocol); + EXPECT_CALL(*module, ProcessHMIMessage(message)).Times(0); + manager->ProcessHMIMessage(message); +} + +TEST_F(PluginManagerTest, ProcessHMIMessagePass) { + Message* msg = new Message(protocol_handler::MessagePriority::FromServiceType( + protocol_handler::ServiceType::kRpc)); + application_manager::MessagePtr message(msg); + message->set_protocol_version(ProtocolVersion::kHMI); + std::string json = "{\"method\": \"HMI-Func-1\"}"; // see MockGenericModule + message->set_json_message(json); + EXPECT_CALL(*module, ProcessHMIMessage(message)) + .Times(1) + .WillOnce(Return(ProcessResult::PROCESSED)); + manager->ProcessHMIMessage(message); +} + +TEST_F(PluginManagerTest, IsAppForPlugins) { + using test::components::application_manager_test::MockApplication; + MockApplication* app = new MockApplication(); + application_manager::ApplicationSharedPtr app_ptr(app); + EXPECT_CALL(*module, IsAppForPlugin(app_ptr)).Times(1); + manager->IsAppForPlugins(app_ptr); +} + +TEST_F(PluginManagerTest, OnAppHMILevelChanged) { + using test::components::application_manager_test::MockApplication; + NiceMock<MockApplication>* app = new NiceMock<MockApplication>(); + application_manager::ApplicationSharedPtr app_ptr(app); + + const application_manager::custom_str::CustomString name("name"); + ON_CALL(*app, name()).WillByDefault(ReturnRef(name)); + mobile_apis::HMILevel::eType level = mobile_apis::HMILevel::eType::HMI_NONE; + ON_CALL(*app, hmi_level()).WillByDefault(Return(level)); + + Expectation is_for_plugin = + EXPECT_CALL(*module, IsAppForPlugin(app_ptr)).WillOnce(Return(true)); + EXPECT_CALL(*module, OnAppHMILevelChanged(app_ptr, _)) + .Times(1) + .After(is_for_plugin); + manager->OnAppHMILevelChanged(app_ptr, + mobile_apis::HMILevel::eType::HMI_FULL); +} + +TEST_F(PluginManagerTest, CanAppChangeHMILevel) { + using test::components::application_manager_test::MockApplication; + NiceMock<MockApplication>* app = new NiceMock<MockApplication>(); + application_manager::ApplicationSharedPtr app_ptr(app); + + const application_manager::custom_str::CustomString name("name"); + ON_CALL(*app, name()).WillByDefault(ReturnRef(name)); + + Expectation is_for_plugin = + EXPECT_CALL(*module, IsAppForPlugin(app_ptr)).WillOnce(Return(true)); + EXPECT_CALL(*module, CanAppChangeHMILevel(app_ptr, _)) + .Times(1) + .After(is_for_plugin) + .WillOnce(Return(true)); + ASSERT_TRUE(manager->CanAppChangeHMILevel( + app_ptr, mobile_apis::HMILevel::eType::HMI_FULL)); +} + +TEST_F(PluginManagerTest, CanAppChangeHMILevelNegative) { + using test::components::application_manager_test::MockApplication; + NiceMock<MockApplication>* app = new NiceMock<MockApplication>(); + application_manager::ApplicationSharedPtr app_ptr(app); + + const application_manager::custom_str::CustomString name("name"); + ON_CALL(*app, name()).WillByDefault(ReturnRef(name)); + + Expectation is_for_plugin = + EXPECT_CALL(*module, IsAppForPlugin(app_ptr)).WillOnce(Return(true)); + EXPECT_CALL(*module, CanAppChangeHMILevel(app_ptr, _)) + .Times(1) + .After(is_for_plugin) + .WillOnce(Return(false)); + ASSERT_FALSE(manager->CanAppChangeHMILevel( + app_ptr, mobile_apis::HMILevel::eType::HMI_BACKGROUND)); +} + +TEST_F(PluginManagerTest, CanAppChangeHMILevelNotForPlugin) { + using test::components::application_manager_test::MockApplication; + NiceMock<MockApplication>* app = new NiceMock<MockApplication>(); + application_manager::ApplicationSharedPtr app_ptr(app); + + const application_manager::custom_str::CustomString name("name"); + ON_CALL(*app, name()).WillByDefault(ReturnRef(name)); + + Expectation is_for_plugin = + EXPECT_CALL(*module, IsAppForPlugin(app_ptr)).WillOnce(Return(false)); + EXPECT_CALL(*module, CanAppChangeHMILevel(app_ptr, _)) + .Times(0) + .After(is_for_plugin); + ASSERT_TRUE(manager->CanAppChangeHMILevel( + app_ptr, mobile_apis::HMILevel::eType::HMI_BACKGROUND)); +} + +} // namespace functional_modules diff --git a/src/components/functional_module/test/src/settings_test.cc b/src/components/functional_module/test/src/settings_test.cc new file mode 100644 index 0000000000..ad7324c350 --- /dev/null +++ b/src/components/functional_module/test/src/settings_test.cc @@ -0,0 +1,92 @@ +#include "gtest/gtest.h" +#include "functional_module/settings.h" + +namespace functional_modules { + +TEST(Settings, ChangeConfigFile) { + Settings set; + set.ChangeConfigFile("test.ini"); + int port = 0; + bool result = set.ReadParameter("HMI", "ServerPort", &port); + ASSERT_TRUE(result); + ASSERT_EQ(8087, port); + set.ChangeConfigFile("not_existing_file.ini"); + result = set.ReadParameter("HMI", "ServerPort", &port); + ASSERT_FALSE(result); +} + +TEST(Settings, ReadParamIntWithSectionSuccess) { + Settings set; + set.ChangeConfigFile("test.ini"); + int port = 0; + bool result = set.ReadParameter<int>("HMI", "ServerPort", &port); + ASSERT_TRUE(result); + ASSERT_EQ(8087, port); +} + +TEST(Settings, ReadParamIntWithSectionFail) { + Settings set; + set.ChangeConfigFile("test.ini"); + int port = 0; + bool result = set.ReadParameter<int>("HMI", "ServerPo", &port); + ASSERT_FALSE(result); + ASSERT_EQ(0, port); +} + +TEST(Settings, ReadParamBoolWithSectionSuccess) { + Settings set; + set.ChangeConfigFile("test.ini"); + bool launch = true; + bool result = set.ReadParameter<bool>("HMI", "LaunchHMI", &launch); + ASSERT_TRUE(result); + ASSERT_FALSE(launch); +} + +TEST(Settings, ReadParamBoolWithSectionFail) { + Settings set; + set.ChangeConfigFile("test.ini"); + bool launch = true; + bool result = set.ReadParameter<bool>("HMI", "LaunchH", &launch); + ASSERT_FALSE(result); + ASSERT_TRUE(launch); +} + +TEST(Settings, ReadParamStringWithSectionSuccess) { + Settings set; + set.ChangeConfigFile("test.ini"); + std::string file_path; + bool result = set.ReadParameter<std::string>( + "Remote Control", "InteriorVDCapabilitiesFile", &file_path); + ASSERT_TRUE(result); + ASSERT_EQ("./plugins/InteriorVehicleDataCapabilities.json", file_path); +} + +TEST(Settings, ReadParamStringWithSectionFail) { + Settings set; + set.ChangeConfigFile("test.ini"); + std::string file_path; + bool result = + set.ReadParameter("Remote Control", "InteriorVDCFile", &file_path); + ASSERT_FALSE(result); + ASSERT_EQ("", file_path); +} + +TEST(Settings, ReadParamStringNoSectionSuccess) { + Settings set; + set.ChangeConfigFile("test.ini"); + std::string caps; + bool result = set.ReadParameter<std::string>("HMICapabilities", &caps); + ASSERT_TRUE(result); + ASSERT_EQ("hmi_capabilities.json", caps); +} + +TEST(Settings, ReadParamStringNoSectionFail) { + Settings set; + set.ChangeConfigFile("test.ini"); + std::string caps; + bool result = set.ReadParameter("HMICaps", &caps); + ASSERT_FALSE(result); + ASSERT_EQ("", caps); +} + +} // namespace functional_modules diff --git a/src/components/functional_module/test/test.ini b/src/components/functional_module/test/test.ini new file mode 100644 index 0000000000..211b7edc78 --- /dev/null +++ b/src/components/functional_module/test/test.ini @@ -0,0 +1,36 @@ + ; The INI-file consists of different chapters. +; Each chapter begins with the line containing +; the name in square brackets. Syntax: +; [chapter] +; The chapters consists of a set of items with a +; assinged value. The syntax is: +; item=value +; All white spaces an second encounters of chapters +; or items will be ignored. +; Remarks start with semicolon or star as first character. +; It is alowed for names of chapters and items to +; contain semicolon and star. Possible syntax is: +; [ chapter ] ;Remark +; item = value ;Remark + +[HMI] +LaunchHMI = false +ServerAddress = 127.0.0.1 +ServerPort = 8087 + +[MAIN] + +;The value of a variable ThreadStackSize used only if its realy needed, other way stack size will be PTHREAD_STACK_MIN +; +ThreadStackSize = 20480 +MixingAudioSupported = true +HMICapabilities = hmi_capabilities.json +MaxCmdID = 2000000000 +; Default request timeout in milliseconds +DefaultTimeout = 10000 + +SystemFilesPath = /tmp/fs/mp/images/ivsu_cache + + +[Remote Control] +InteriorVDCapabilitiesFile = ./plugins/InteriorVehicleDataCapabilities.json diff --git a/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_adapter_impl.h b/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_adapter_impl.h index bd118032d6..1a28c89bda 100644 --- a/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_adapter_impl.h +++ b/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_adapter_impl.h @@ -51,8 +51,15 @@ class HMIMessageAdapterImpl : public HMIMessageAdapter { /** * \brief Destructor */ - virtual ~HMIMessageAdapterImpl(); + ~HMIMessageAdapterImpl(); +#ifdef SDL_REMOTE_CONTROL + /** + * @brief Subscribes to notification from HMI + * @param hmi_notification string with notification name + */ + void SubscribeToHMINotification(const std::string& hmi_notification) OVERRIDE; +#endif // SDL_REMOTE_CONTROL protected: virtual HMIMessageHandler* handler() const { return handler_; diff --git a/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_handler_impl.h b/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_handler_impl.h index 8b238b4aa8..daba87e738 100644 --- a/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_handler_impl.h +++ b/src/components/hmi_message_handler/include/hmi_message_handler/hmi_message_handler_impl.h @@ -89,14 +89,21 @@ class HMIMessageHandlerImpl : public HMIMessageHandler, explicit HMIMessageHandlerImpl(const HMIMessageHandlerSettings& settings); ~HMIMessageHandlerImpl(); - void OnMessageReceived(MessageSharedPointer message); - void SendMessageToHMI(MessageSharedPointer message); + void OnMessageReceived(MessageSharedPointer message) OVERRIDE; + void SendMessageToHMI(MessageSharedPointer message) OVERRIDE; void set_message_observer(HMIMessageObserver* observer); - void OnErrorSending(MessageSharedPointer message); - void AddHMIMessageAdapter(HMIMessageAdapter* adapter); - void RemoveHMIMessageAdapter(HMIMessageAdapter* adapter); - - virtual const HMIMessageHandlerSettings& get_settings() const OVERRIDE; + void OnErrorSending(MessageSharedPointer message) OVERRIDE; + void AddHMIMessageAdapter(HMIMessageAdapter* adapter) OVERRIDE; + void RemoveHMIMessageAdapter(HMIMessageAdapter* adapter) OVERRIDE; + +#ifdef SDL_REMOTE_CONTROL + /** + * @brief Subscribes to notification from HMI + * @param hmi_notification string with notification name + */ + void SubscribeToHMINotification(const std::string& hmi_notification) OVERRIDE; +#endif // SDL_REMOTE_CONTROL + const HMIMessageHandlerSettings& get_settings() const OVERRIDE; #ifdef BUILD_TESTS std::set<HMIMessageAdapter*> message_adapters() const { @@ -120,15 +127,16 @@ class HMIMessageHandlerImpl : public HMIMessageHandler, // threads::MessageLoopThread<*>::Handler implementations // CALLED ON messages_from_hmi_ THREAD! - virtual void Handle(const impl::MessageFromHmi message) OVERRIDE; + void Handle(const impl::MessageFromHmi message) OVERRIDE; // CALLED ON messages_to_hmi_ THREAD! - virtual void Handle(const impl::MessageToHmi message) OVERRIDE; + void Handle(const impl::MessageToHmi message) OVERRIDE; private: const HMIMessageHandlerSettings& settings_; HMIMessageObserver* observer_; - mutable sync_primitives::Lock observer_locker_; std::set<HMIMessageAdapter*> message_adapters_; + mutable sync_primitives::Lock observer_locker_; + mutable sync_primitives::Lock message_adapters_locker_; // Construct message threads when everything is already created diff --git a/src/components/hmi_message_handler/include/hmi_message_handler/messagebroker_adapter.h b/src/components/hmi_message_handler/include/hmi_message_handler/messagebroker_adapter.h index f582cb2b81..8acc8fb207 100644 --- a/src/components/hmi_message_handler/include/hmi_message_handler/messagebroker_adapter.h +++ b/src/components/hmi_message_handler/include/hmi_message_handler/messagebroker_adapter.h @@ -76,6 +76,13 @@ class MessageBrokerAdapter : public HMIMessageAdapterImpl, void* SubscribeAndBeginReceiverThread(void* param); +#ifdef SDL_REMOTE_CONTROL + /** + * @brief Subscribes to notification from HMI + * @param hmi_notification string with notification name + */ + void SubscribeToHMINotification(const std::string& hmi_notification) FINAL; +#endif // SDL_REMOTE_CONTROL protected: void ProcessRecievedFromMB(Json::Value& root); diff --git a/src/components/hmi_message_handler/src/hmi_message_adapter_impl.cc b/src/components/hmi_message_handler/src/hmi_message_adapter_impl.cc index 48874618a0..e58c5a8fb6 100644 --- a/src/components/hmi_message_handler/src/hmi_message_adapter_impl.cc +++ b/src/components/hmi_message_handler/src/hmi_message_adapter_impl.cc @@ -40,4 +40,10 @@ HMIMessageAdapterImpl::~HMIMessageAdapterImpl() { handler_ = 0; } +#ifdef SDL_REMOTE_CONTROL +void HMIMessageAdapterImpl::SubscribeToHMINotification( + const std::string& hmi_notification) { + // TODO(SL): Find an immplementation +} +#endif // SDL_REMOTE_CONTROL } // namespace hmi_message_handler diff --git a/src/components/hmi_message_handler/src/hmi_message_handler_impl.cc b/src/components/hmi_message_handler/src/hmi_message_handler_impl.cc index 1c774b9efe..654b67de7f 100644 --- a/src/components/hmi_message_handler/src/hmi_message_handler_impl.cc +++ b/src/components/hmi_message_handler/src/hmi_message_handler_impl.cc @@ -94,6 +94,7 @@ void HMIMessageHandlerImpl::AddHMIMessageAdapter(HMIMessageAdapter* adapter) { LOG4CXX_WARN(logger_, "HMIMessageAdapter is not valid!"); return; } + sync_primitives::AutoLock lock(message_adapters_locker_); message_adapters_.insert(adapter); } @@ -104,6 +105,7 @@ void HMIMessageHandlerImpl::RemoveHMIMessageAdapter( LOG4CXX_WARN(logger_, "HMIMessageAdapter is not valid!"); return; } + sync_primitives::AutoLock lock(message_adapters_locker_); message_adapters_.erase(adapter); } @@ -123,11 +125,23 @@ void HMIMessageHandlerImpl::Handle(const impl::MessageFromHmi message) { LOG4CXX_INFO(logger_, "Message from hmi given away."); } void HMIMessageHandlerImpl::Handle(const impl::MessageToHmi message) { + sync_primitives::AutoLock lock(message_adapters_locker_); for (std::set<HMIMessageAdapter*>::iterator it = message_adapters_.begin(); it != message_adapters_.end(); ++it) { (*it)->SendMessageToHMI(message); } } +#ifdef SDL_REMOTE_CONTROL +void HMIMessageHandlerImpl::SubscribeToHMINotification( + const std::string& hmi_notification) { + sync_primitives::AutoLock lock(message_adapters_locker_); + for (std::set<HMIMessageAdapter*>::iterator it = message_adapters_.begin(); + it != message_adapters_.end(); + ++it) { + (*it)->SubscribeToHMINotification(hmi_notification); + } +} +#endif // SDL_REMOTE_CONTROL } // namespace hmi_message_handler diff --git a/src/components/include/test/application_manager/mock_application_manager.h b/src/components/include/test/application_manager/mock_application_manager.h index 8d1bb756c2..e4500fb602 100644 --- a/src/components/include/test/application_manager/mock_application_manager.h +++ b/src/components/include/test/application_manager/mock_application_manager.h @@ -45,6 +45,7 @@ #include "application_manager/hmi_capabilities.h" #include "application_manager/vehicle_info_data.h" #include "application_manager/state_controller.h" +#include "application_manager/message.h" #include "resumption/last_state.h" #include "interfaces/MOBILE_API.h" #include "application_manager/app_launch/app_launch_ctrl.h" @@ -74,6 +75,28 @@ class MockApplicationManager : public application_manager::ApplicationManager { application, application_manager::ApplicationSharedPtr(uint32_t app_id)); MOCK_CONST_METHOD0(active_application, application_manager::ApplicationSharedPtr()); + +#ifdef SDL_REMOTE_CONTROL + MOCK_CONST_METHOD2(application, + application_manager::ApplicationSharedPtr( + const std::string& device_id, + const std::string& policy_app_id)); + MOCK_METHOD1(SubscribeToHMINotification, + void(const std::string& hmi_notification)); + MOCK_METHOD1(GetDeviceHandle, uint32_t(uint32_t connection_key)); + MOCK_CONST_METHOD1(IsAudioStreamingAllowed, bool(uint32_t connection_key)); + MOCK_CONST_METHOD1(IsVideoStreamingAllowed, bool(uint32_t connection_key)); + MOCK_METHOD2(ChangeAppsHMILevel, + void(uint32_t app_id, mobile_apis::HMILevel::eType level)); + MOCK_METHOD0(GetPluginManager, functional_modules::PluginManager&()); + MOCK_CONST_METHOD1( + devices, std::vector<std::string>(const std::string& policy_app_id)); + MOCK_METHOD1(SendPostMessageToMobile, + void(const application_manager::MessagePtr& message)); + MOCK_METHOD1(SendPostMessageToHMI, + void(const application_manager::MessagePtr& message)); +#endif // SDL_REMOTE_CONTROL + MOCK_CONST_METHOD1( application_by_hmi_app, application_manager::ApplicationSharedPtr(uint32_t hmi_app_id)); @@ -110,6 +133,8 @@ class MockApplicationManager : public application_manager::ApplicationManager { MOCK_METHOD1( SendMessageToHMI, void(const application_manager::commands::MessageSharedPtr message)); + MOCK_METHOD1(RemoveHMIFakeParameters, + void(application_manager::MessagePtr& message)); MOCK_METHOD1( ManageHMICommand, bool(const application_manager::commands::MessageSharedPtr message)); diff --git a/src/components/include/test/application_manager/mock_application_manager_settings.h b/src/components/include/test/application_manager/mock_application_manager_settings.h index fd9e2aa8a3..c09e79a52f 100644 --- a/src/components/include/test/application_manager/mock_application_manager_settings.h +++ b/src/components/include/test/application_manager/mock_application_manager_settings.h @@ -101,6 +101,7 @@ class MockApplicationManagerSettings MOCK_CONST_METHOD0(start_stream_retry_amount, const std::pair<uint32_t, int32_t>&()); MOCK_CONST_METHOD0(app_icons_folder, const std::string&()); + MOCK_CONST_METHOD0(plugins_folder, const std::string&()); MOCK_CONST_METHOD0(app_icons_folder_max_size, const uint32_t&()); MOCK_CONST_METHOD0(app_icons_amount_to_remove, const uint32_t&()); MOCK_CONST_METHOD0(list_files_response_size, const uint32_t&()); diff --git a/src/components/include/utils/macro.h b/src/components/include/utils/macro.h index 0e029e4b06..4cf76fe022 100644 --- a/src/components/include/utils/macro.h +++ b/src/components/include/utils/macro.h @@ -113,6 +113,13 @@ return; \ } +#define EXPORT_FUNCTION(TypeName) extern "C" TypeName* Create(); + +#define EXPORT_FUNCTION_IMPL(TypeName) \ + extern "C" TypeName* Create() { \ + return new TypeName(); \ + } + #define NOTREACHED() DCHECK(!"Unreachable code") // Allows to perform static check that virtual function from base class is @@ -134,6 +141,8 @@ #ifdef BUILD_TESTS #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test -#endif +#else // BUILD_TESTS +#define FRIEND_TEST(test_case_name, test_name) +#endif // BUILD_TESTS #endif // SRC_COMPONENTS_INCLUDE_UTILS_MACRO_H_ |