diff options
author | Kramchaninov Pavel <pkramchaninov@luxoft.com> | 2015-04-23 17:33:59 +0300 |
---|---|---|
committer | Kramchaninov Pavel <pkramchaninov@luxoft.com> | 2015-04-23 17:33:59 +0300 |
commit | 1b93d911e1fa1d6fc95e0988c478cff6a85584c4 (patch) | |
tree | 8e8727f8a76fe3d5e18d5ea78dc2e4712c4475a7 | |
parent | 21999852e8e9e8bc46f1681cac6384d0160254d8 (diff) | |
parent | 5d9da1aedf9f19b9914b9ebf76961e30769d3f83 (diff) | |
download | sdl_core-1b93d911e1fa1d6fc95e0988c478cff6a85584c4.tar.gz |
Merge pull request #91 from LuxoftSDL/Bug_fix_anosach
SDL bug fixes
46 files changed, 1493 insertions, 596 deletions
diff --git a/customer-specific/pasa/src/appMain/smartDeviceLink.ini b/customer-specific/pasa/src/appMain/smartDeviceLink.ini index bde0a5eaea..d292c042d2 100644 --- a/customer-specific/pasa/src/appMain/smartDeviceLink.ini +++ b/customer-specific/pasa/src/appMain/smartDeviceLink.ini @@ -81,6 +81,10 @@ RecordingFileSource = audio.8bit.wav ; Recording file for audio pass thru RecordingFileName = audio.wav MQAudioPath = /dev/mqueue/AppLinkAudioPass +; Defines time in milliseconds for SDL to wait for the next package of raw data over audio service +AudioDataStoppedTimeout = 1000 +; Defines time in milliseconds for SDL to wait for the next package of raw data over video service +VideoDataStoppedTimeout = 1000 ; HelpPromt and TimeOutPrompt is a vector of strings separated by comma diff --git a/src/appMain/smartDeviceLink.ini b/src/appMain/smartDeviceLink.ini index eef038e09c..f6f66cb0fa 100644 --- a/src/appMain/smartDeviceLink.ini +++ b/src/appMain/smartDeviceLink.ini @@ -81,7 +81,11 @@ RecordingFileSource = audio.8bit.wav ; Recording file for audio pass thru RecordingFileName = audio.wav ; The timeout in seconds for mobile to stop streaming or end up sessions. -StopStreamingTimeout = 1 +StopStreamingTimeout = 1
+; The timeout in miliseconds to suspend audio data streaming if no data received from mobile
+AudioDataStoppedTimeout = 1000
+; The timeout in miliseconds to suspend video data streaming if no data received from mobile
+VideoDataStoppedTimeout = 1000 ; HelpPromt and TimeOutPrompt is a vector of strings separated by comma [GLOBAL PROPERTIES] @@ -185,7 +189,7 @@ HashStringSize = 32 [SDL4] ; Enables SDL 4.0 support -EnableProtocol4 = true +EnableProtocol4 = false ; Path where apps icons must be stored AppIconsFolder = storage ; Max size of the folder in bytes diff --git a/src/components/application_manager/CMakeLists.txt b/src/components/application_manager/CMakeLists.txt index dcc5a74570..bef3cdd8fe 100644 --- a/src/components/application_manager/CMakeLists.txt +++ b/src/components/application_manager/CMakeLists.txt @@ -115,6 +115,8 @@ file (GLOB MOBILE_COMMANDS_SOURCES ${AM_SOURCE_DIR}/src/commands/hmi/on_update_device_list.cc ${AM_SOURCE_DIR}/src/commands/hmi/update_device_list_request.cc ${AM_SOURCE_DIR}/src/commands/hmi/update_device_list_response.cc + ${AM_SOURCE_DIR}/src/commands/hmi/on_audio_data_streaming_notification.cc + ${AM_SOURCE_DIR}/src/commands/hmi/on_video_data_streaming_notification.cc ${AM_SOURCE_DIR}/src/commands/hmi/on_sdl_consent_needed_notification.cc ${AM_SOURCE_DIR}/src/commands/hmi/on_sdl_persistence_complete_notification.cc ${AM_SOURCE_DIR}/src/commands/hmi/on_exit_all_applications_notification.cc diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index 62d268bd3f..d18ca599fb 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -43,9 +43,11 @@ #include "connection_handler/device.h" #include "application_manager/message.h" #include "application_manager/hmi_state.h" +#include "protocol_handler/protocol_handler.h" namespace NsSmartDeviceLink { namespace NsSmartObjects { + class SmartObject; } } @@ -400,18 +402,47 @@ class Application : public virtual InitialApplicationData, virtual void CloseActiveMessage() = 0; virtual bool IsFullscreen() const = 0; virtual void ChangeSupportingAppHMIType() = 0; + virtual bool is_navi() const = 0; virtual void set_is_navi(bool allow) = 0; - virtual bool hmi_supports_navi_video_streaming() const = 0; - virtual void set_hmi_supports_navi_video_streaming(bool supports) = 0; - virtual bool hmi_supports_navi_audio_streaming() const = 0; - virtual void set_hmi_supports_navi_audio_streaming(bool supports) = 0; - bool is_streaming_allowed() const { return can_stream_;} - void set_streaming_allowed(bool can_stream) { can_stream_ = can_stream;} - bool streaming() const {return streaming_;} - void set_streaming(bool can_stream) { streaming_ = can_stream;} + virtual bool video_streaming_started() const = 0; + virtual void set_video_streaming_started(bool state) = 0; + virtual bool audio_streaming_started() const = 0; + virtual void set_audio_streaming_started(bool state) = 0; + + virtual bool video_streaming_allowed() const = 0; + virtual void set_video_streaming_allowed(bool state) = 0; + virtual bool audio_streaming_allowed() const = 0; + virtual void set_audio_streaming_allowed(bool state) = 0; + /** + * @brief Starts streaming service for application + * @param service_type Type of streaming service + */ + virtual void StartStreaming( + protocol_handler::ServiceType service_type) = 0; + + /** + * @brief Stops streaming service for application + * @param service_type Type of streaming service + */ + virtual void StopStreaming( + protocol_handler::ServiceType service_type) = 0; + + /** + * @brief Suspends streaming process for application + * @param service_type Type of streaming service + */ + virtual void SuspendStreaming( + protocol_handler::ServiceType service_type) = 0; + + /** + * @brief Wakes up streaming process for application + * @param service_type Type of streaming service + */ + virtual void WakeUpStreaming( + protocol_handler::ServiceType service_type) = 0; virtual bool is_voice_communication_supported() const = 0; virtual void set_voice_communication_supported( @@ -671,16 +702,6 @@ class Application : public virtual InitialApplicationData, protected: - // interfaces for NAVI retry sequence - virtual bool video_stream_retry_active() const = 0; - virtual void set_video_stream_retry_active(bool active) = 0; - virtual bool audio_stream_retry_active() const = 0; - virtual void set_audio_stream_retry_active(bool active) = 0; - virtual void OnVideoStreamRetry() = 0; - virtual void OnAudioStreamRetry() = 0; - - protected: - /** * @brief Active states of application */ @@ -691,8 +712,6 @@ class Application : public virtual InitialApplicationData, std::string url_; std::string package_name_; std::string device_id_; - bool can_stream_; - bool streaming_; ssize_t connection_id_; bool is_greyed_out_; }; diff --git a/src/components/application_manager/include/application_manager/application_impl.h b/src/components/application_manager/include/application_manager/application_impl.h index 7c2c20a9ef..974cd2a155 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -43,15 +43,20 @@ #include "application_manager/application_data_impl.h" #include "application_manager/usage_statistics.h" #include "application_manager/hmi_state.h" +#include "protocol_handler/protocol_handler.h" #include "connection_handler/device.h" #include "utils/timer_thread.h" #include "utils/lock.h" + namespace usage_statistics { + class StatisticsManager; } // namespace usage_statistics namespace application_manager { +using namespace utils; +using namespace timer; namespace mobile_api = mobile_apis; @@ -79,13 +84,28 @@ class ApplicationImpl : public virtual InitialApplicationDataImpl, */ virtual void ChangeSupportingAppHMIType(); - // navi inline bool is_navi() const { return is_navi_; } void set_is_navi(bool allow); - bool hmi_supports_navi_video_streaming() const; - void set_hmi_supports_navi_video_streaming(bool supports); - bool hmi_supports_navi_audio_streaming() const; - void set_hmi_supports_navi_audio_streaming(bool supports); + + bool video_streaming_started() const; + void set_video_streaming_started(bool state); + bool audio_streaming_started() const; + void set_audio_streaming_started(bool state); + + bool video_streaming_allowed() const; + void set_video_streaming_allowed(bool state); + bool audio_streaming_allowed() const; + void set_audio_streaming_allowed(bool state); + + void StartStreaming( + protocol_handler::ServiceType service_type); + void StopStreaming( + protocol_handler::ServiceType service_type); + + void SuspendStreaming( + protocol_handler::ServiceType service_type); + void WakeUpStreaming( + protocol_handler::ServiceType service_type); virtual bool is_voice_communication_supported() const; virtual void set_voice_communication_supported( @@ -232,19 +252,35 @@ class ApplicationImpl : public virtual InitialApplicationDataImpl, void LoadPersistentFiles(); private: + typedef SharedPtr<TimerThread<ApplicationImpl>> ApplicationTimerPtr; + + /** + * @brief Callback for video start stream retry timer. + * Sends start video stream request to HMI + */ + void OnVideoStartStreamRetry(); + + /** + * @brief Callback for audio start stream retry timer. + * Sends start audio stream request to HMI + */ + void OnAudioStartStreamRetry(); + + /** + * @brief Callback for video streaming suspend timer. + * Suspends video streaming process for application + */ + void OnVideoStreamSuspend(); - // interfaces for NAVI retry sequence - bool video_stream_retry_active() const; - void set_video_stream_retry_active(bool active); - bool audio_stream_retry_active() const; - void set_audio_stream_retry_active(bool active); - void OnVideoStreamRetry(); - void OnAudioStreamRetry(); + /** + * @brief Callback for audio streaming suspend timer. + * Suspends audio streaming process for application + */ + void OnAudioStreamSuspend(); std::string hash_val_; uint32_t grammar_id_; - Version version_; std::string app_name_; uint32_t hmi_app_id_; @@ -252,8 +288,16 @@ class ApplicationImpl : public virtual InitialApplicationDataImpl, smart_objects::SmartObject* active_message_; bool is_media_; bool is_navi_; - bool hmi_supports_navi_video_streaming_; - bool hmi_supports_navi_audio_streaming_; + + bool video_streaming_started_; + bool audio_streaming_started_; + bool video_streaming_allowed_; + bool audio_streaming_allowed_; + bool video_streaming_suspended_; + bool audio_streaming_suspended_; + sync_primitives::Lock video_streaming_suspended_lock_; + sync_primitives::Lock audio_streaming_suspended_lock_; + bool is_app_allowed_; bool has_been_activated_; bool tts_properties_in_none_; @@ -271,14 +315,15 @@ class ApplicationImpl : public virtual InitialApplicationDataImpl, UsageStatistics usage_report_; ProtocolVersion protocol_version_; bool is_voice_communication_application_; - // NAVI retry stream - volatile bool is_video_stream_retry_active_; - volatile bool is_audio_stream_retry_active_; + uint32_t video_stream_retry_number_; uint32_t audio_stream_retry_number_; - utils::SharedPtr<timer::TimerThread<ApplicationImpl>> video_stream_retry_timer_; - utils::SharedPtr<timer::TimerThread<ApplicationImpl>> audio_stream_retry_timer_; - + uint32_t video_stream_suspend_timeout_; + uint32_t audio_stream_suspend_timeout_; + ApplicationTimerPtr video_stream_retry_timer_; + ApplicationTimerPtr audio_stream_retry_timer_; + ApplicationTimerPtr video_stream_suspend_timer_; + ApplicationTimerPtr audio_stream_suspend_timer_; /** * @brief Defines number per time in seconds limits diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h index 1b1e1600cd..6bcac4abc3 100644 --- a/src/components/application_manager/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/include/application_manager/application_manager_impl.h @@ -37,6 +37,7 @@ #include <vector> #include <map> #include <set> +#include <deque> #include <algorithm> #include "application_manager/hmi_command_factory.h" @@ -49,6 +50,7 @@ #include "application_manager/vehicle_info_data.h" #include "application_manager/state_controller.h" #include "protocol_handler/protocol_observer.h" +#include "protocol_handler/protocol_handler.h" #include "hmi_message_handler/hmi_message_observer.h" #include "hmi_message_handler/hmi_message_sender.h" #include "application_manager/policies/policy_handler_observer.h" @@ -77,8 +79,6 @@ #include "utils/singleton.h" #include "utils/data_accessor.h" - - namespace NsSmartDeviceLink { namespace NsSmartObjects { class SmartObject; @@ -93,6 +93,8 @@ class CommandNotificationImpl; namespace application_manager { namespace mobile_api = mobile_apis; +using namespace utils; +using namespace timer; class ApplicationManagerImpl; @@ -654,43 +656,57 @@ class ApplicationManagerImpl : public ApplicationManager, */ void RemovePolicyObserver(PolicyHandlerObserver* listener); - /* - * @brief Checks HMI level and returns true if audio streaming is allowed - */ - bool IsAudioStreamingAllowed(uint32_t connection_key) const; - - /* - * @brief Checks HMI level and returns true if video streaming is allowed + /** + * @brief Checks HMI level and returns true if streaming is allowed + * @param app_id Application id + * @param service_type Service type to check + * @return True if streaming is allowed, false in other case */ - bool IsVideoStreamingAllowed(uint32_t connection_key) const; + bool IsStreamingAllowed( + uint32_t app_id, protocol_handler::ServiceType service_type) const; /** - * @brief CanAppStream allows to check whether application is permited for - * data streaming. - * - * In case streaming for app is disallowed the method will send EndService to mobile. - * - * @param app_id the application id which should be checked. - * - * @return true in case streaming is allowed, false otherwise. + * @brief Checks if application can stream (streaming service is started and + * streaming is enabled in application) + * @param app_id Application id + * @param service_type Service type to check + * @return True if streaming is allowed, false in other case */ - bool CanAppStream(uint32_t app_id) const; + bool CanAppStream( + uint32_t app_id, protocol_handler::ServiceType service_type) const; /** - * @brief StreamingEnded Callback called from MediaManager when it decide that - * streaming has been ended - * - * @param app_id the id of application that stops stream. + * @brief Ends opened navi services (audio/video) for application + * @param app_id Application id */ - void StreamingEnded(uint32_t app_id); + void EndNaviServices(uint32_t app_id); /** * @brief ForbidStreaming forbid the stream over the certain application. - * * @param app_id the application's id which should stop streaming. */ void ForbidStreaming(uint32_t app_id); + /** + * @brief Callback calls when application starts/stops data streaming + * @param app_id Streaming application id + * @param state Shows if streaming started or stopped + */ + void OnAppStreaming(uint32_t app_id, bool state); + + /** + * @brief OnHMILevelChanged the callback that allows SDL to react when + * application's HMILeval has been changed. + * + * @param app_id application identifier for which HMILevel has been chaned. + * + * @param from previous HMILevel. + * @param to current HMILevel. + */ + void OnHMILevelChanged(uint32_t app_id, + mobile_apis::HMILevel::eType from, + mobile_apis::HMILevel::eType to); + mobile_api::HMILevel::eType GetDefaultHmiLevel( ApplicationSharedPtr application) const; @@ -1139,79 +1155,63 @@ class ApplicationManagerImpl : public ApplicationManager, bool IsLowVoltage(); private: - /** - - * @brief OnHMILevelChanged the callback that allows SDL to react when - * application's HMILeval has been changed. - * - * @param app_id application identifier for which HMILevel has been chaned. - * - * @param from previous HMILevel. - * @param to current HMILevel. + /* + * NaviServiceStatusMap shows which navi service (audio/video) is opened + * for specified application. Two bool values in std::pair mean: + * 1st value - is video service opened or not + * 2nd value - is audio service opened or not */ - void OnHMILevelChanged(uint32_t app_id, - mobile_apis::HMILevel::eType from, - mobile_apis::HMILevel::eType to); + typedef std::map<uint32_t, std::pair<bool, bool> > NaviServiceStatusMap; + + typedef SharedPtr<TimerThread<ApplicationManagerImpl> > ApplicationManagerTimerPtr; /** - * @brief EndNaviServices either send EndService to mobile or proceed - * unregister application procedure. + * @brief Removes suspended and stopped timers from timer pool */ - void EndNaviServices(); + void ClearTimerPool(); /** * @brief CloseNaviApp allows to unregister application in case the EndServiceEndedAck - * didn't come for at least one of services(audio or video). + * didn't come for at least one of services(audio or video) */ void CloseNaviApp(); /** - * @brief AckReceived allows to distinguish if ack for appropriate service - * has been received (means EndServiceAck). - * - * @param type service type. - * - * @return in case EndService has been sent and appropriate ack has been - * received it returns true. In case no EndService for appropriate serevice type - * has been sent and no ack has been received it returns true as well. - * Otherwise it will return false. - * + * @brief Suspends streaming ability of application in case application's HMI level + * has been changed to not allowed for streaming */ - bool AckReceived(protocol_handler::ServiceType type); + void EndNaviStreaming(); /** - * @brief NaviAppChangeLevel the callback which reacts on case when applications - * hmi level has been changed. + * @brief Starts specified navi service for application + * @param app_id Application to proceed + * @param service_type Type of service to start + * @return True on success, false on fail */ - void NaviAppChangeLevel(mobile_apis::HMILevel::eType new_level); + bool StartNaviService( + uint32_t app_id, protocol_handler::ServiceType service_type); /** - * @brief ChangeStreamStatus allows to process streaming state. - * - * @param app_id id of application whose stream state has been changed. - * - * @param can_stream streaming state if true - streaming active, if false - * streaming is not active. + * @brief Stops specified navi service for application + * @param app_id Application to proceed + * @param service_type Type of service to stop */ - void ChangeStreamStatus(uint32_t app_id, bool can_stream); + void StopNaviService( + uint32_t app_id, protocol_handler::ServiceType service_type); /** - * @brief ProcessNaviService allows to start navi service - * - * @param type service type. - * - * @param connection_key the application id. + * @brief Allows streaming for application if it was disallowed by + * DisallowStreaming() + * @param app_id Application to proceed */ - bool ProcessNaviService(protocol_handler::ServiceType type, uint32_t connection_key); + void AllowStreaming(uint32_t app_id); /** - * @brief NaviAppStreamStatus allows to handle case when navi streaming state - * has ben changed from streaming to non streaming and vise versa. - * - * @param stream_active the stream's state - is it streams or not. + * @brief Disallows streaming for application, but doesn't close + * opened services. Streaming ability could be restored by AllowStreaming(); + * @param app_id Application to proceed */ - void NaviAppStreamStatus(bool stream_active); - + void DisallowStreaming(uint32_t app_id); /** * @brief Function returns supported SDL Protocol Version @@ -1263,7 +1263,6 @@ class ApplicationManagerImpl : public ApplicationManager, const connection_handler::DeviceHandle handle); private: - /** * @brief List of applications */ @@ -1331,15 +1330,15 @@ class ApplicationManagerImpl : public ApplicationManager, */ ResumeCtrl resume_ctrl_; - // The map contains service type as a key and pair as a value. - // The pair meaning is: first item shows if EndService has been sent and - // the second one shows if appropriate ACK has been received. - std::map<protocol_handler::ServiceType, std::pair<bool, bool> > service_status_; + NaviServiceStatusMap navi_service_status_; + std::deque<uint32_t> navi_app_to_stop_; + std::deque<uint32_t> navi_app_to_end_stream_; + uint32_t navi_close_app_timeout_; + uint32_t navi_end_stream_timeout_; + + std::vector<ApplicationManagerTimerPtr> timer_pool_; + sync_primitives::Lock timer_pool_lock_; - timer::TimerThread<ApplicationManagerImpl> end_services_timer; - uint32_t wait_end_service_timeout_; - uint32_t navi_app_to_stop_; - StateController state_ctrl_; #ifdef TIME_TESTER diff --git a/src/components/application_manager/include/application_manager/commands/hmi/navi_audio_start_stream_request.h b/src/components/application_manager/include/application_manager/commands/hmi/navi_audio_start_stream_request.h index 97de7102f7..30b5e2165b 100644 --- a/src/components/application_manager/include/application_manager/commands/hmi/navi_audio_start_stream_request.h +++ b/src/components/application_manager/include/application_manager/commands/hmi/navi_audio_start_stream_request.h @@ -42,7 +42,8 @@ namespace commands { /** * @brief AudioStartStreamRequest command class **/ -class AudioStartStreamRequest : public RequestToHMI { +class AudioStartStreamRequest : public RequestToHMI, + public event_engine::EventObserver { public: /** * @brief AudioStartStreamRequest class constructor @@ -61,6 +62,11 @@ class AudioStartStreamRequest : public RequestToHMI { **/ virtual void Run(); + /** + * @brief On event callback + **/ + virtual void on_event(const event_engine::Event& event); + private: DISALLOW_COPY_AND_ASSIGN(AudioStartStreamRequest); }; diff --git a/src/components/application_manager/include/application_manager/commands/hmi/navi_start_stream_request.h b/src/components/application_manager/include/application_manager/commands/hmi/navi_start_stream_request.h index 5b73e2dbab..07a6de7f69 100644 --- a/src/components/application_manager/include/application_manager/commands/hmi/navi_start_stream_request.h +++ b/src/components/application_manager/include/application_manager/commands/hmi/navi_start_stream_request.h @@ -42,7 +42,8 @@ namespace commands { /** * @brief NaviStartStreamRequest command class **/ -class NaviStartStreamRequest : public RequestToHMI { +class NaviStartStreamRequest : public RequestToHMI, + public event_engine::EventObserver { public: /** * @brief NaviStartStreamRequest class constructor @@ -61,6 +62,11 @@ class NaviStartStreamRequest : public RequestToHMI { **/ virtual void Run(); + /** + * @brief On event callback + **/ + virtual void on_event(const event_engine::Event& event); + private: DISALLOW_COPY_AND_ASSIGN(NaviStartStreamRequest); }; diff --git a/src/components/application_manager/include/application_manager/commands/hmi/on_audio_data_streaming_notification.h b/src/components/application_manager/include/application_manager/commands/hmi/on_audio_data_streaming_notification.h new file mode 100644 index 0000000000..97a979065e --- /dev/null +++ b/src/components/application_manager/include/application_manager/commands/hmi/on_audio_data_streaming_notification.h @@ -0,0 +1,73 @@ +/* + * 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_AUDIO_DATA_STREAMING_NOTIFICATION_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_AUDIO_DATA_STREAMING_NOTIFICATION_H_ + +#include "application_manager/commands/hmi/notification_to_hmi.h" + +namespace application_manager { + +namespace commands { + +/** + * @brief OnAudioDataStreamingNotification command class + **/ +class OnAudioDataStreamingNotification : public NotificationToHMI { + public: + /** + * @brief OnAudioDataStreamingNotification class constructor + * + * @param message Incoming SmartObject message + **/ + explicit OnAudioDataStreamingNotification(const MessageSharedPtr& message); + + /** + * @brief OnAudioDataStreamingNotification class destructor + **/ + virtual ~OnAudioDataStreamingNotification(); + + /** + * @brief Execute command + **/ + virtual void Run(); + + private: + DISALLOW_COPY_AND_ASSIGN(OnAudioDataStreamingNotification); +}; + +} // namespace commands + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_AUDIO_DATA_STREAMING_NOTIFICATION_H_ + diff --git a/src/components/application_manager/include/application_manager/commands/hmi/on_video_data_streaming_notification.h b/src/components/application_manager/include/application_manager/commands/hmi/on_video_data_streaming_notification.h new file mode 100644 index 0000000000..38749ba8f8 --- /dev/null +++ b/src/components/application_manager/include/application_manager/commands/hmi/on_video_data_streaming_notification.h @@ -0,0 +1,73 @@ +/* + * 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_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_VIDEO_DATA_STREAMING_NOTIFICATION_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_VIDEO_DATA_STREAMING_NOTIFICATION_H_ + +#include "application_manager/commands/hmi/notification_to_hmi.h" + +namespace application_manager { + +namespace commands { + +/** + * @brief OnVideoDataStreamingNotification command class + **/ +class OnVideoDataStreamingNotification : public NotificationToHMI { + public: + /** + * @brief OnVideoDataStreamingNotification class constructor + * + * @param message Incoming SmartObject message + **/ + explicit OnVideoDataStreamingNotification(const MessageSharedPtr& message); + + /** + * @brief OnVideoDataStreamingNotification class destructor + **/ + virtual ~OnVideoDataStreamingNotification(); + + /** + * @brief Execute command + **/ + virtual void Run(); + + private: + DISALLOW_COPY_AND_ASSIGN(OnVideoDataStreamingNotification); +}; + +} // namespace commands + +} // namespace application_manager + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_COMMANDS_HMI_ON_VIDEO_DATA_STREAMING_NOTIFICATION_H_ + diff --git a/src/components/application_manager/include/application_manager/commands/mobile/subscribe_button_request.h b/src/components/application_manager/include/application_manager/commands/mobile/subscribe_button_request.h index 1f02e503a3..12168e2473 100644 --- a/src/components/application_manager/include/application_manager/commands/mobile/subscribe_button_request.h +++ b/src/components/application_manager/include/application_manager/commands/mobile/subscribe_button_request.h @@ -76,7 +76,7 @@ class SubscribeButtonRequest : public CommandRequestImpl { * * @return TRUE on success, otherwise false **/ - bool IsSubscribtionAllowed(ApplicationSharedPtr app, + bool IsSubscriptionAllowed(ApplicationSharedPtr app, const mobile_apis::ButtonName::eType btn_id); /** @@ -85,6 +85,12 @@ class SubscribeButtonRequest : public CommandRequestImpl { */ void SendSubscribeButtonNotification(); + /** + * @brief Checks HMI capabilities for specified button support + * @param button Button to check + */ + bool CheckHMICapabilities(mobile_apis::ButtonName::eType button); + DISALLOW_COPY_AND_ASSIGN(SubscribeButtonRequest); }; diff --git a/src/components/application_manager/include/application_manager/hmi_state.h b/src/components/application_manager/include/application_manager/hmi_state.h index 5a715dc099..4451fb6857 100644 --- a/src/components/application_manager/include/application_manager/hmi_state.h +++ b/src/components/application_manager/include/application_manager/hmi_state.h @@ -31,6 +31,7 @@ class HmiState { STATE_ID_SAFETY_MODE, STATE_ID_VR_SESSION, STATE_ID_TTS_SESSION, + STATE_ID_NAVI_STREAMING, }; HmiState(uint32_t app_id, const StateContext& state_context_); @@ -150,6 +151,15 @@ class TTSHmiState : public HmiState { }; /** + * @brief The NaviStreamingState class impement logic of NaviStreaming temporary state + */ +class NaviStreamingHmiState : public HmiState { + public: + NaviStreamingHmiState(uint32_t app_id, StateContext& state_context); + virtual mobile_apis::AudioStreamingState::eType audio_streaming_state() const; +}; + +/** * @brief The PhoneCallHmiState class impement logic of PhoneCall temporary state */ class PhoneCallHmiState : public HmiState { diff --git a/src/components/application_manager/include/application_manager/message_helper.h b/src/components/application_manager/include/application_manager/message_helper.h index a2d51da416..12705c619a 100644 --- a/src/components/application_manager/include/application_manager/message_helper.h +++ b/src/components/application_manager/include/application_manager/message_helper.h @@ -402,6 +402,9 @@ class MessageHelper { */ static void SendAudioStopStream(int32_t connection_key); + static void SendOnDataStreaming(protocol_handler::ServiceType service, + bool available); + /* * @brief Sends notification to HMI to stop audioPathThru * diff --git a/src/components/application_manager/include/application_manager/state_controller.h b/src/components/application_manager/include/application_manager/state_controller.h index 79fbaf1da0..b57070c35e 100644 --- a/src/components/application_manager/include/application_manager/state_controller.h +++ b/src/components/application_manager/include/application_manager/state_controller.h @@ -189,6 +189,17 @@ class StateController : public event_engine::EventObserver { * @param app application to apply states */ void ApplyStatesForApp(ApplicationSharedPtr app); + + /** + * @brief OnNaviStreamingStarted process Navi streaming started + */ + void OnNaviStreamingStarted(); + + /** + * @brief OnNaviStreamingStopped process Navi streaming stopped + */ + void OnNaviStreamingStopped(); + private: /** * Execute Unary punction for each application diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index e36b36c89e..2d848ad2c3 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -35,6 +35,7 @@ #include "application_manager/application_impl.h" #include "application_manager/message_helper.h" #include "application_manager/application_manager_impl.h" +#include "protocol_handler/protocol_handler.h" #include "config_profile/profile.h" #include "interfaces/MOBILE_API.h" #include "utils/file_system.h" @@ -85,8 +86,12 @@ ApplicationImpl::ApplicationImpl(uint32_t application_id, active_message_(NULL), is_media_(false), is_navi_(false), - hmi_supports_navi_video_streaming_(false), - hmi_supports_navi_audio_streaming_(false), + video_streaming_started_(false), + audio_streaming_started_(false), + video_streaming_allowed_(false), + audio_streaming_allowed_(false), + video_streaming_suspended_(true), + audio_streaming_suspended_(true), is_app_allowed_(true), has_been_activated_(false), tts_properties_in_none_(false), @@ -98,8 +103,6 @@ ApplicationImpl::ApplicationImpl(uint32_t application_id, usage_report_(mobile_app_id, statistics_manager), protocol_version_(ProtocolVersion::kV3), is_voice_communication_application_(false), - is_video_stream_retry_active_(false), - is_audio_stream_retry_active_(false), video_stream_retry_number_(0), audio_stream_retry_number_(0) { @@ -108,7 +111,6 @@ ApplicationImpl::ApplicationImpl(uint32_t application_id, cmd_number_to_time_limits_[mobile_apis::FunctionID::GetVehicleDataID] = {date_time::DateTime::getCurrentTime(), 0}; - set_mobile_app_id(mobile_app_id); set_name(app_name); @@ -124,6 +126,29 @@ ApplicationImpl::ApplicationImpl(uint32_t application_id, mobile_apis::AudioStreamingState::INVALID_ENUM, mobile_api::SystemContext::SYSCTXT_MAIN); hmi_states_.push_back(initial_state); + + video_stream_suspend_timeout_ = + profile::Profile::instance()->video_data_stopped_timeout() / 1000; + audio_stream_suspend_timeout_ = + profile::Profile::instance()->audio_data_stopped_timeout() / 1000; + + video_stream_retry_timer_ = ApplicationTimerPtr( + new timer::TimerThread<ApplicationImpl>( + "VideoStartStreamRetry", this, + &ApplicationImpl::OnVideoStartStreamRetry, true)); + audio_stream_retry_timer_ = ApplicationTimerPtr( + new timer::TimerThread<ApplicationImpl>( + "AudioStartStreamRetry", this, + &ApplicationImpl::OnAudioStartStreamRetry, true)); + + video_stream_suspend_timer_ = ApplicationTimerPtr( + new timer::TimerThread<ApplicationImpl>( + "VideoStreamSuspend", this, + &ApplicationImpl::OnVideoStreamSuspend, true)); + audio_stream_suspend_timer_ = ApplicationTimerPtr( + new timer::TimerThread<ApplicationImpl>( + "AudioStreamSuspend", this, + &ApplicationImpl::OnAudioStreamSuspend, true)); } ApplicationImpl::~ApplicationImpl() { @@ -364,102 +389,188 @@ bool ApplicationImpl::tts_properties_in_full() { return tts_properties_in_full_; } -void ApplicationImpl::set_hmi_supports_navi_video_streaming(bool supports) { - hmi_supports_navi_video_streaming_ = supports; - - if ((!supports) && (!video_stream_retry_active())) { - std::pair<uint32_t, int32_t> stream_retry = - profile::Profile::instance()->start_stream_retry_amount(); - set_video_stream_retry_active(true); - video_stream_retry_number_ = stream_retry.first; - video_stream_retry_timer_ = - utils::SharedPtr<timer::TimerThread<ApplicationImpl>>( - new timer::TimerThread<ApplicationImpl>( - "VideoStreamRetry", this, &ApplicationImpl::OnVideoStreamRetry, true)); - // start separate pthread for timer without delays - video_stream_retry_timer_->start(0); +void ApplicationImpl::set_video_streaming_started(bool state) { + if (state) { + if (video_stream_retry_timer_->isRunning()) { + video_stream_retry_timer_->stop(); + video_streaming_started_ = state; + set_video_streaming_allowed(state); + } + } else { + video_streaming_started_ = state; + set_video_streaming_allowed(state); } } -bool ApplicationImpl::hmi_supports_navi_video_streaming() const { - return hmi_supports_navi_video_streaming_; +bool ApplicationImpl::video_streaming_started() const { + return video_streaming_started_; } -void ApplicationImpl::set_hmi_supports_navi_audio_streaming(bool supports) { - hmi_supports_navi_audio_streaming_ = supports; - - if ((!supports) && (!audio_stream_retry_active())) { - std::pair<uint32_t, int32_t> stream_retry = - profile::Profile::instance()->start_stream_retry_amount(); - set_audio_stream_retry_active(true); - audio_stream_retry_number_ = stream_retry.first; - audio_stream_retry_timer_ = - utils::SharedPtr<timer::TimerThread<ApplicationImpl>>( - new timer::TimerThread<ApplicationImpl>( - "AudioStreamRetry", this, &ApplicationImpl::OnAudioStreamRetry, true)); - // start separate pthread for timer without delays - audio_stream_retry_timer_->start(0); +void ApplicationImpl::set_audio_streaming_started(bool state) { + if (state) { + if (audio_stream_retry_timer_->isRunning()) { + audio_stream_retry_timer_->stop(); + audio_streaming_started_ = state; + set_audio_streaming_allowed(state); + } + } else { + audio_streaming_started_ = state; + set_audio_streaming_allowed(state); } } -bool ApplicationImpl::hmi_supports_navi_audio_streaming() const { - return hmi_supports_navi_audio_streaming_; +bool ApplicationImpl::audio_streaming_started() const { + return audio_streaming_started_; +} + +void ApplicationImpl::set_video_streaming_allowed(bool state) { + video_streaming_allowed_ = state; +} + +bool ApplicationImpl::video_streaming_allowed() const { + return video_streaming_allowed_; +} + +void ApplicationImpl::set_audio_streaming_allowed(bool state) { + audio_streaming_allowed_ = state; +} + +bool ApplicationImpl::audio_streaming_allowed() const { + return audio_streaming_allowed_; } -bool ApplicationImpl::video_stream_retry_active() const { - return is_video_stream_retry_active_; +void ApplicationImpl::StartStreaming( + protocol_handler::ServiceType service_type) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + + std::pair<uint32_t, int32_t> stream_retry = + profile::Profile::instance()->start_stream_retry_amount(); + + if (ServiceType::kMobileNav == service_type) { + if (!video_streaming_started()) { + MessageHelper::SendNaviStartStream(app_id()); + video_stream_retry_number_ = stream_retry.first; + video_stream_retry_timer_->start(stream_retry.second); + } + } else if (ServiceType::kAudio == service_type) { + if (!audio_streaming_started()) { + MessageHelper::SendAudioStartStream(app_id()); + audio_stream_retry_number_ = stream_retry.first; + audio_stream_retry_timer_->start(stream_retry.second); + } + } } -void ApplicationImpl::set_video_stream_retry_active(bool active) { - is_video_stream_retry_active_ = active; +void ApplicationImpl::StopStreaming( + protocol_handler::ServiceType service_type) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + + if (ServiceType::kMobileNav == service_type) { + video_stream_retry_timer_->stop(); + if (video_streaming_started()) { + video_stream_suspend_timer_->stop(); + MessageHelper::SendNaviStopStream(app_id()); + set_video_streaming_started(false); + } + } else if (ServiceType::kAudio == service_type) { + audio_stream_retry_timer_->stop(); + if (audio_streaming_started()) { + audio_stream_suspend_timer_->stop(); + MessageHelper::SendAudioStopStream(app_id()); + set_audio_streaming_started(false); + } + } } -bool ApplicationImpl::audio_stream_retry_active() const { - return is_audio_stream_retry_active_; +void ApplicationImpl::SuspendStreaming( + protocol_handler::ServiceType service_type) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + + if (ServiceType::kMobileNav == service_type) { + video_stream_suspend_timer_->suspend(); + ApplicationManagerImpl::instance()->OnAppStreaming(app_id(), false); + sync_primitives::AutoLock lock(video_streaming_suspended_lock_); + video_streaming_suspended_ = true; + } else if (ServiceType::kAudio == service_type) { + audio_stream_suspend_timer_->suspend(); + ApplicationManagerImpl::instance()->OnAppStreaming(app_id(), false); + sync_primitives::AutoLock lock(audio_streaming_suspended_lock_); + audio_streaming_suspended_ = true; + } + MessageHelper::SendOnDataStreaming(service_type, false); } -void ApplicationImpl::set_audio_stream_retry_active(bool active) { - is_audio_stream_retry_active_ = active; +void ApplicationImpl::WakeUpStreaming( + protocol_handler::ServiceType service_type) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + + if (ServiceType::kMobileNav == service_type) { + sync_primitives::AutoLock lock(video_streaming_suspended_lock_); + if (video_streaming_suspended_) { + ApplicationManagerImpl::instance()->OnAppStreaming(app_id(), true); + MessageHelper::SendOnDataStreaming(ServiceType::kMobileNav, true); + video_streaming_suspended_ = false; + } + video_stream_suspend_timer_->start(video_stream_suspend_timeout_); + } else if (ServiceType::kAudio == service_type) { + sync_primitives::AutoLock lock(audio_streaming_suspended_lock_); + if (audio_streaming_suspended_) { + ApplicationManagerImpl::instance()->OnAppStreaming(app_id(), true); + MessageHelper::SendOnDataStreaming(ServiceType::kAudio, true); + audio_streaming_suspended_ = false; + } + audio_stream_suspend_timer_->start(audio_stream_suspend_timeout_); + } } -void ApplicationImpl::OnVideoStreamRetry() { +void ApplicationImpl::OnVideoStartStreamRetry() { + LOG4CXX_AUTO_TRACE(logger_); if (video_stream_retry_number_) { - LOG4CXX_INFO(logger_, "Send video stream retry " + LOG4CXX_INFO(logger_, "Send video start stream retry " << video_stream_retry_number_); - application_manager::MessageHelper::SendNaviStartStream(app_id()); + MessageHelper::SendNaviStartStream(app_id()); --video_stream_retry_number_; - - std::pair<uint32_t, int32_t> stream_retry = - profile::Profile::instance()->start_stream_retry_amount(); - int32_t time_out = stream_retry.second; - video_stream_retry_timer_->updateTimeOut(time_out); } else { - LOG4CXX_INFO(logger_, "Stop video streaming retry"); - video_stream_retry_timer_->stop(); - set_video_stream_retry_active(false); + video_stream_retry_timer_->suspend(); + ApplicationManagerImpl::instance()->EndNaviServices(app_id()); + LOG4CXX_INFO(logger_, "Video start stream retry timer stopped"); } } -void ApplicationImpl::OnAudioStreamRetry() { +void ApplicationImpl::OnAudioStartStreamRetry() { + LOG4CXX_AUTO_TRACE(logger_); if (audio_stream_retry_number_) { - LOG4CXX_INFO(logger_, "Send audio streaming retry " + LOG4CXX_INFO(logger_, "Send audio start stream retry " << audio_stream_retry_number_); - application_manager::MessageHelper::SendAudioStartStream(app_id()); + MessageHelper::SendAudioStartStream(app_id()); --audio_stream_retry_number_; - - std::pair<uint32_t, int32_t> stream_retry = - profile::Profile::instance()->start_stream_retry_amount(); - int32_t time_out = stream_retry.second; - audio_stream_retry_timer_->updateTimeOut(time_out); } else { - LOG4CXX_INFO(logger_, "Stop audio streaming retry"); - audio_stream_retry_timer_->stop(); - set_audio_stream_retry_active(false); + audio_stream_retry_timer_->suspend(); + ApplicationManagerImpl::instance()->EndNaviServices(app_id()); + LOG4CXX_INFO(logger_, "Audio start stream retry timer stopped"); } } +void ApplicationImpl::OnVideoStreamSuspend() { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_INFO(logger_, "Suspend video streaming by timer"); + SuspendStreaming(ServiceType::kMobileNav); +} + +void ApplicationImpl::OnAudioStreamSuspend() { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_INFO(logger_, "Suspend audio streaming by timer"); + SuspendStreaming(ServiceType::kAudio); +} + void ApplicationImpl::increment_put_file_in_none_count() { ++put_file_in_none_count_; } diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 44b02c7d79..f1537c8f35 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -44,6 +44,7 @@ #include "application_manager/message_helper.h" #include "application_manager/mobile_message_handler.h" #include "application_manager/policies/policy_handler.h" +#include "protocol_handler/protocol_handler.h" #include "hmi_message_handler/hmi_message_handler.h" #include "connection_handler/connection_handler_impl.h" #include "formatters/formatter_json_rpc.h" @@ -99,8 +100,8 @@ ApplicationManagerImpl::ApplicationManagerImpl() hmi_capabilities_(this), unregister_reason_(mobile_api::AppInterfaceUnregisteredReason::INVALID_ENUM), resume_ctrl_(this), - end_services_timer("EndServiceTimer", this, &ApplicationManagerImpl::EndNaviServices), - wait_end_service_timeout_(profile::Profile::instance()->stop_streaming_timeout()), + navi_close_app_timeout_(profile::Profile::instance()->stop_streaming_timeout()), + navi_end_stream_timeout_(profile::Profile::instance()->stop_streaming_timeout()), #ifdef TIME_TESTER metric_observer_(NULL), #endif // TIME_TESTER @@ -118,6 +119,12 @@ ApplicationManagerImpl::ApplicationManagerImpl() {TYPE_SYSTEM, "System"}, {TYPE_ICONS, "Icons"} }; + + sync_primitives::AutoLock lock(timer_pool_lock_); + ApplicationManagerTimerPtr clearTimerPoolTimer(new TimerThread<ApplicationManagerImpl>( + "ClearTimerPoolTimer", this, &ApplicationManagerImpl::ClearTimerPool, true)); + clearTimerPoolTimer->start(10); + timer_pool_.push_back(clearTimerPoolTimer); } ApplicationManagerImpl::~ApplicationManagerImpl() { @@ -140,6 +147,12 @@ ApplicationManagerImpl::~ApplicationManagerImpl() { LOG4CXX_INFO(logger_, "Destroying Policy Handler"); RemovePolicyObserver(this); policy::PolicyHandler::destroy(); + + sync_primitives::AutoLock lock(timer_pool_lock_); + timer_pool_.clear(); + + navi_app_to_stop_.clear(); + navi_app_to_end_stream_.clear(); } bool ApplicationManagerImpl::Stop() { @@ -284,7 +297,7 @@ bool ApplicationManagerImpl::IsAppTypeExistsInFullOrLimited( ApplicationSharedPtr app) const { bool voice_state = app->is_voice_communication_supported(); bool media_state = app->is_media_application(); - bool navi_state = app->hmi_supports_navi_video_streaming(); + bool navi_state = app->is_navi(); ApplicationSharedPtr active_app = active_application(); // Check app in FULL level if (active_app.valid()) { @@ -302,7 +315,7 @@ bool ApplicationManagerImpl::IsAppTypeExistsInFullOrLimited( return true; } - if (navi_state && active_app->hmi_supports_navi_video_streaming()) { + if (navi_state && active_app->is_navi()) { return true; } } @@ -831,34 +844,6 @@ void ApplicationManagerImpl::RemoveDevice( LOG4CXX_INFO(logger_, "device_handle " << device_handle); } -bool ApplicationManagerImpl::IsAudioStreamingAllowed(uint32_t application_key) const { - ApplicationSharedPtr app = application(application_key); - - using namespace mobile_apis::HMILevel; - using namespace helpers; - if (!app) { - LOG4CXX_WARN(logger_, "An application is not registered."); - return false; - } - - return Compare<eType, EQ, ONE>( - app->hmi_level(), HMI_FULL, HMI_LIMITED); -} - -bool ApplicationManagerImpl::IsVideoStreamingAllowed(uint32_t application_key) const { - ApplicationSharedPtr app = application(application_key); - using namespace mobile_apis::HMILevel; - using namespace helpers; - - if (!app) { - LOG4CXX_WARN(logger_, "An application is not registered."); - return false; - } - - LOG4CXX_DEBUG(logger_, "HMILevel: " << app->hmi_level()); - return Compare<eType, EQ, ONE>(app->hmi_level(), HMI_FULL, HMI_LIMITED); -} - mobile_apis::HMILevel::eType ApplicationManagerImpl::GetDefaultHmiLevel( ApplicationSharedPtr application) const { using namespace mobile_apis; @@ -983,8 +968,9 @@ void ApplicationManagerImpl::ReplaceHMIByMobileAppId( } } -bool ApplicationManagerImpl::ProcessNaviService(protocol_handler::ServiceType type, - uint32_t connection_key) { +bool ApplicationManagerImpl::StartNaviService( + uint32_t app_id, protocol_handler::ServiceType service_type) { + using namespace protocol_handler; LOG4CXX_AUTO_TRACE(logger_); if (!media_manager_) { @@ -992,37 +978,70 @@ bool ApplicationManagerImpl::ProcessNaviService(protocol_handler::ServiceType ty return false; } - bool result = false; - switch (type) { - case protocol_handler::kMobileNav: - LOG4CXX_DEBUG(logger_, "Video service is about to be started."); - if (IsVideoStreamingAllowed(connection_key)) { - media_manager_->StartVideoStreaming(connection_key); - result = true; - } - break; - case protocol_handler::kAudio: - LOG4CXX_DEBUG(logger_, "Audio service is about to be started."); - if (IsAudioStreamingAllowed(connection_key)) { - media_manager_->StartAudioStreaming(connection_key); - result = true; + if (IsStreamingAllowed(app_id, service_type)) { + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() == it) { + std::pair<NaviServiceStatusMap::iterator, bool> res = + navi_service_status_.insert(std::pair<uint32_t, std::pair<bool, bool> >( + app_id, std::make_pair(false, false))); + if (!res.second) { + return false; } - break; - default: - LOG4CXX_DEBUG(logger_, "Unknown type of service to be started."); - break; + it = res.first; + } + // Fill NaviServices map. Set true to first value of pair if + // we've started video service or to second value if we've + // started audio service + service_type == ServiceType::kMobileNav ? it->second.first = + true : it->second.second = true; + + application(app_id)->StartStreaming(service_type); + media_manager_->StartStreaming(app_id, service_type); + + return true; } + return false; +} - service_status_[type] = std::make_pair(result, false); - return result; +void ApplicationManagerImpl::StopNaviService( + uint32_t app_id, protocol_handler::ServiceType service_type) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() == it) { + LOG4CXX_WARN(logger_, "No Information about navi service " + << service_type); + } else { + // Fill NaviServices map. Set false to first value of pair if + // we've stopped video service or to second value if we've + // stopped audio service + service_type == ServiceType::kMobileNav ? it->second.first = + false : it->second.second = false; + } + + if (!media_manager_) { + LOG4CXX_DEBUG(logger_, "The media manager is not initialized."); + return; + } + media_manager_->StopStreaming(app_id, service_type); + + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_WARN(logger_, "An application is not registered."); + return; + } + app->StopStreaming(service_type); } bool ApplicationManagerImpl::OnServiceStartedCallback( const connection_handler::DeviceHandle& device_handle, const int32_t& session_key, const protocol_handler::ServiceType& type) { - using namespace protocol_handler; using namespace helpers; + using namespace protocol_handler; LOG4CXX_DEBUG(logger_, "OnServiceStartedCallback " << type @@ -1037,22 +1056,25 @@ bool ApplicationManagerImpl::OnServiceStartedCallback( " doesn't exists."); return false; } - bool result = false; - if (Compare<ServiceType, EQ, ONE>(type, kMobileNav, kAudio)) { + + if (Compare<ServiceType, EQ, ONE>(type, + ServiceType::kMobileNav, ServiceType::kAudio)) { if (app->is_navi()) { - result = ProcessNaviService(type, session_key); - app->set_streaming_allowed(result); + return StartNaviService(session_key, type); } } - return result; + return false; } void ApplicationManagerImpl::OnServiceEndedCallback(const int32_t& session_key, const protocol_handler::ServiceType& type) { + using namespace helpers; using namespace protocol_handler; - LOG4CXX_DEBUG(logger_, - "OnServiceEndedCallback " << type - << " in session 0x" << std::hex << session_key); + + LOG4CXX_DEBUG( + logger_, + "OnServiceEndedCallback " << type << " in session 0x" + << std::hex << session_key); if (type == kRpc) { LOG4CXX_INFO(logger_, "Remove application."); @@ -1065,25 +1087,9 @@ void ApplicationManagerImpl::OnServiceEndedCallback(const int32_t& session_key, return; } - if (media_manager_) { - switch (type) { - case protocol_handler::kMobileNav: { - LOG4CXX_INFO(logger_, "Stop video streaming."); - media_manager_->StopVideoStreaming(session_key); - break; - } - case protocol_handler::kAudio: { - LOG4CXX_INFO(logger_, "Stop audio service."); - media_manager_->StopAudioStreaming(session_key); - break; - } - default: - LOG4CXX_WARN(logger_, "Unknown type of service to be ended." << type); - break; - } - service_status_[type].second = true; - LOG4CXX_DEBUG(logger_, "Ack status: " << service_status_[type].first <<" : " - << service_status_[type].second); + if (Compare<ServiceType, EQ, ONE>(type, + ServiceType::kMobileNav, ServiceType::kAudio)) { + StopNaviService(session_key, type); } } @@ -2206,6 +2212,13 @@ void ApplicationManagerImpl::UnregisterApplication( << "; reason = " << reason << "; is_resuming = " << is_resuming << "; is_unexpected_disconnect = " << is_unexpected_disconnect); + + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() != it) { + navi_service_status_.erase(it); + } + //remove appID from tts_global_properties_app_list_ MessageHelper::SendOnAppInterfaceUnregisteredNotificationToMobile( app_id, unregister_reason_); @@ -2467,76 +2480,118 @@ bool ApplicationManagerImpl::IsLowVoltage() { return is_low_voltage_; } -void ApplicationManagerImpl::NaviAppStreamStatus(bool stream_active) { - ApplicationSharedPtr active_app = active_application(); - using namespace mobile_apis; - if(active_app && active_app->is_media_application()) { - LOG4CXX_DEBUG(logger_, "Stream status: " << active_app->app_id()); - SetState(active_app->app_id(), - stream_active ? AudioStreamingState::ATTENUATED : - AudioStreamingState::AUDIBLE); +bool ApplicationManagerImpl::IsStreamingAllowed( + uint32_t app_id, protocol_handler::ServiceType service_type) const { + using namespace mobile_apis::HMILevel; + using namespace helpers; + + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_WARN(logger_, "An application is not registered."); + return false; } + return Compare<eType, EQ, ONE>( + app->hmi_level(), HMI_FULL, HMI_LIMITED); +} + +bool ApplicationManagerImpl::CanAppStream( + uint32_t app_id, protocol_handler::ServiceType service_type) const { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + + ApplicationSharedPtr app = application(app_id); + if (!app) { + LOG4CXX_WARN(logger_, "An application is not registered."); + return false; + } + + bool is_started = false; + if (ServiceType::kMobileNav == service_type) { + is_started = app->video_streaming_started() && + app->video_streaming_allowed(); + } else if (ServiceType::kAudio == service_type) { + is_started = app->audio_streaming_started() && + app->audio_streaming_allowed(); + } + return IsStreamingAllowed(app_id, service_type) && is_started; } void ApplicationManagerImpl::ForbidStreaming(uint32_t app_id) { + using namespace mobile_apis::AppInterfaceUnregisteredReason; + using namespace mobile_apis::Result; + LOG4CXX_AUTO_TRACE(logger_); - using namespace protocol_handler; + ApplicationSharedPtr app = application(app_id); - if (!(app && app->is_navi())) { - LOG4CXX_DEBUG(logger_, " There is no application with id: " << app_id); + if (!app || !app->is_navi()) { + LOG4CXX_DEBUG(logger_, "There is no navi application with id: " << app_id); return; } - if (connection_handler_) { - const bool send_end_service = true; - const bool ack_received = false; - if (app->hmi_supports_navi_video_streaming()) { - LOG4CXX_DEBUG(logger_, "Going to end video service"); - connection_handler_->SendEndService(navi_app_to_stop_, kMobileNav); - service_status_[kMobileNav] = std::make_pair(send_end_service, ack_received); - } - if (app->hmi_supports_navi_audio_streaming()) { - LOG4CXX_DEBUG(logger_, "Going to end audio service"); - connection_handler_->SendEndService(navi_app_to_stop_, kAudio); - service_status_[kAudio] = std::make_pair(send_end_service, ack_received); - } + if (navi_app_to_stop_.end() != std::find(navi_app_to_stop_.begin(), + navi_app_to_stop_.end(), app_id) || + navi_app_to_end_stream_.end() != std::find(navi_app_to_end_stream_.begin(), + navi_app_to_end_stream_.end(), app_id)) { + return; + } + + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() == it || + (!it->second.first && !it->second.second)) { + SetUnregisterAllApplicationsReason(PROTOCOL_VIOLATION); + UnregisterApplication(app_id, ABORTED); + return; } - // this timer will check if appropriate acks from mobile were received. - // in case no acks, the application will be unregistered. - end_services_timer.start(wait_end_service_timeout_, this, &ApplicationManagerImpl::CloseNaviApp); - bool const allow_streaming = false; - ChangeStreamStatus(app_id, allow_streaming); + EndNaviServices(app_id); } -bool ApplicationManagerImpl::CanAppStream(uint32_t app_id) const { +void ApplicationManagerImpl::OnAppStreaming(uint32_t app_id, bool state) { LOG4CXX_AUTO_TRACE(logger_); ApplicationSharedPtr app = application(app_id); - if (!(app && app->is_navi())) { - LOG4CXX_DEBUG(logger_, " There is no application with id: " << app_id); - return false; + if (!app || !app->is_navi()) { + LOG4CXX_DEBUG(logger_, " There is no navi application with id: " << app_id); + return; } - - return app->is_streaming_allowed(); + state ? state_ctrl_.OnNaviStreamingStarted() : + state_ctrl_.OnNaviStreamingStopped(); } -void ApplicationManagerImpl::ChangeStreamStatus(uint32_t app_id, bool can_stream) { +void ApplicationManagerImpl::EndNaviServices(uint32_t app_id) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); + ApplicationSharedPtr app = application(app_id); - if (!app) { - LOG4CXX_DEBUG(logger_, " There is no application with id: " << app_id); + if (!app || !app->is_navi()) { + LOG4CXX_DEBUG(logger_, "There is no navi application with id: " << app_id); return; } - // Change streaming status only in case incoming value is different. - if (can_stream != app->streaming()) { - NaviAppStreamStatus(can_stream); - app->set_streaming(can_stream); + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() == it) { + return; } -} -void ApplicationManagerImpl::StreamingEnded(uint32_t app_id) { - LOG4CXX_DEBUG(logger_, "Streaming has been stoped."); - ChangeStreamStatus(app_id, false); + if (connection_handler_) { + if (it->second.first) { + LOG4CXX_DEBUG(logger_, "Going to end video service"); + connection_handler_->SendEndService(app_id, ServiceType::kMobileNav); + } + if (it->second.second) { + LOG4CXX_DEBUG(logger_, "Going to end audio service"); + connection_handler_->SendEndService(app_id, ServiceType::kAudio); + } + navi_app_to_stop_.push_back(app_id); + + ApplicationManagerTimerPtr closeTimer(new TimerThread<ApplicationManagerImpl>( + "CloseAppTimer", this, &ApplicationManagerImpl::CloseNaviApp)); + closeTimer->start(navi_close_app_timeout_); + + sync_primitives::AutoLock lock(timer_pool_lock_); + timer_pool_.push_back(closeTimer); + } } void ApplicationManagerImpl::OnHMILevelChanged(uint32_t app_id, @@ -2545,68 +2600,142 @@ void ApplicationManagerImpl::OnHMILevelChanged(uint32_t app_id, using namespace mobile_apis::HMILevel; using namespace helpers; + if (from == to) { + return; + } + ApplicationSharedPtr app = application(app_id); - if (!(app && app->is_navi())) { + if (!app || !app->is_navi()) { + LOG4CXX_ERROR(logger_, "Navi application not found"); return; } - if (Compare<eType, EQ, ONE>(from, HMI_FULL, HMI_LIMITED)) { - navi_app_to_stop_ = app_id; - NaviAppChangeLevel(to); - } else if (Compare<eType, EQ, ONE>(to, HMI_FULL, HMI_LIMITED)) { - LOG4CXX_DEBUG(logger_, "Restore streaming ability"); - app->set_streaming_allowed(true); + if (to == HMI_FULL || to == HMI_LIMITED) { + if (from == HMI_BACKGROUND) { + AllowStreaming(app_id); + } + } else if (to == HMI_BACKGROUND) { + if (from == HMI_FULL || from == HMI_LIMITED) { + navi_app_to_end_stream_.push_back(app_id); + + ApplicationManagerTimerPtr endStreamTimer(new TimerThread<ApplicationManagerImpl>( + "EndStreamTimer", this, &ApplicationManagerImpl::EndNaviStreaming)); + endStreamTimer->start(navi_end_stream_timeout_); + + sync_primitives::AutoLock lock(timer_pool_lock_); + timer_pool_.push_back(endStreamTimer); + } + } else if (to == HMI_NONE) { + if (from == HMI_FULL || from == HMI_LIMITED || + from == HMI_BACKGROUND) { + EndNaviServices(app_id); + } } } -void ApplicationManagerImpl::EndNaviServices() { +void ApplicationManagerImpl::ClearTimerPool() { LOG4CXX_AUTO_TRACE(logger_); - ApplicationSharedPtr app = application(navi_app_to_stop_); - if (!app) { - LOG4CXX_DEBUG(logger_, "The application doesn't exists anymore."); - return; + + std::vector<ApplicationManagerTimerPtr> new_timer_pool; + + sync_primitives::AutoLock lock(timer_pool_lock_); + new_timer_pool.push_back(timer_pool_[0]); + + for (size_t i = 1; i < timer_pool_.size(); i++) { + if (timer_pool_[i]->isRunning()) { + new_timer_pool.push_back(timer_pool_[i]); + } } - app->set_streaming_allowed(false); + + timer_pool_.swap(new_timer_pool); + new_timer_pool.clear(); } void ApplicationManagerImpl::CloseNaviApp() { LOG4CXX_AUTO_TRACE(logger_); using namespace mobile_apis::AppInterfaceUnregisteredReason; using namespace mobile_apis::Result; - using namespace protocol_handler; - const bool is_ack_received = AckReceived(kAudio) && AckReceived(kMobileNav); - if (!is_ack_received) { - SetUnregisterAllApplicationsReason(PROTOCOL_VIOLATION); - UnregisterApplication(navi_app_to_stop_, ABORTED); + + uint32_t app_id = navi_app_to_stop_.front(); + navi_app_to_stop_.pop_front(); + + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() != it) { + if (it->second.first || it->second.second) { + SetUnregisterAllApplicationsReason(PROTOCOL_VIOLATION); + UnregisterApplication(app_id, ABORTED); + } } } -bool ApplicationManagerImpl::AckReceived(protocol_handler::ServiceType type) { +void ApplicationManagerImpl::EndNaviStreaming() { LOG4CXX_AUTO_TRACE(logger_); - using namespace protocol_handler; + using namespace mobile_apis::AppInterfaceUnregisteredReason; + using namespace mobile_apis::Result; + + uint32_t app_id = navi_app_to_end_stream_.front(); + navi_app_to_end_stream_.pop_front(); + + if (navi_app_to_stop_.end() == std::find(navi_app_to_stop_.begin(), + navi_app_to_stop_.end(), app_id)) { + DisallowStreaming(app_id); + } +} - const bool sent = service_status_[type].first; - const bool received = service_status_[type].second; +void ApplicationManagerImpl::DisallowStreaming(uint32_t app_id) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); - LOG4CXX_DEBUG(logger_, "Ack for services type " << type - << " is send: " << sent - << " is received: " << received); + ApplicationSharedPtr app = application(app_id); + if (!app || !app->is_navi()) { + LOG4CXX_ERROR(logger_, "Navi application not found"); + return; + } - return sent == received; + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() != it) { + if (it->second.first) { + if (media_manager_) { + media_manager_->StopStreaming(app_id, ServiceType::kMobileNav); + } + app->set_video_streaming_allowed(false); + } + if (it->second.second) { + if (media_manager_) { + media_manager_->StopStreaming(app_id, ServiceType::kAudio); + } + app->set_audio_streaming_allowed(false); + } + } } -void ApplicationManagerImpl::NaviAppChangeLevel(mobile_apis::HMILevel::eType new_level) { +void ApplicationManagerImpl::AllowStreaming(uint32_t app_id) { + using namespace protocol_handler; LOG4CXX_AUTO_TRACE(logger_); - using namespace mobile_apis; - if (new_level == HMILevel::HMI_BACKGROUND) { - end_services_timer.start(wait_end_service_timeout_, this, &ApplicationManagerImpl::EndNaviServices); - } else if (new_level == HMILevel::HMI_NONE) { - EndNaviServices(); - LOG4CXX_DEBUG(logger_, "Send end services start close app timer"); - end_services_timer.start(wait_end_service_timeout_, this, &ApplicationManagerImpl::CloseNaviApp); - } else { - LOG4CXX_DEBUG(logger_, "There is no defined behavior for hmi " << - "levels that are differen from NONE or BACKGROUND"); + + ApplicationSharedPtr app = application(app_id); + if (!app || !app->is_navi()) { + LOG4CXX_ERROR(logger_, "Navi application not found"); + return; + } + + NaviServiceStatusMap::iterator it = + navi_service_status_.find(app_id); + if (navi_service_status_.end() != it) { + if (it->second.first) { + if (media_manager_) { + media_manager_->StartStreaming(app_id, ServiceType::kMobileNav); + } + app->set_video_streaming_allowed(true); + } + if (it->second.second) { + if (media_manager_) { + media_manager_->StartStreaming(app_id, ServiceType::kAudio); + } + app->set_audio_streaming_allowed(true); + } } } @@ -2758,7 +2887,7 @@ void ApplicationManagerImpl::RemoveAppFromTTSGlobalPropertiesList( LOG4CXX_INFO(logger_, "Stop tts_global_properties_timer_"); // if container is empty need to stop timer tts_global_properties_app_list_lock_.Release(); - tts_global_properties_timer_.pause(); + tts_global_properties_timer_.suspend(); return; } } diff --git a/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_request.cc b/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_request.cc index 3908238ada..0f7a2a475f 100644 --- a/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_request.cc +++ b/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_request.cc @@ -31,6 +31,8 @@ */ #include "application_manager/commands/hmi/navi_audio_start_stream_request.h" +#include "application_manager/application_manager_impl.h" +#include "protocol_handler/protocol_handler.h" namespace application_manager { @@ -47,11 +49,55 @@ AudioStartStreamRequest::~AudioStartStreamRequest() { void AudioStartStreamRequest::Run() { LOG4CXX_AUTO_TRACE(logger_); + subscribe_on_event(hmi_apis::FunctionID::Navigation_StartAudioStream, + correlation_id()); SendRequest(); } -} // namespace commands +void AudioStartStreamRequest::on_event(const event_engine::Event& event) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); -} // namespace application_manager + ApplicationManagerImpl* app_mgr = ApplicationManagerImpl::instance(); + if (!app_mgr) { + LOG4CXX_ERROR_EXT(logger_, "Application manager not found"); + return; + } + + ApplicationSharedPtr app = app_mgr->application_by_hmi_app(application_id()); + if (!app) { + LOG4CXX_ERROR_EXT(logger_, + "StartAudioStreamRequest aborted. Application not found"); + return; + } + + const smart_objects::SmartObject& message = event.smart_object(); + switch (event.id()) { + case hmi_apis::FunctionID::Navigation_StartAudioStream: { + LOG4CXX_DEBUG(logger_, "Received StartStream event"); + const hmi_apis::Common_Result::eType code = + static_cast<hmi_apis::Common_Result::eType>( + message[strings::params][hmi_response::code].asInt()); + if (hmi_apis::Common_Result::SUCCESS == code) { + LOG4CXX_DEBUG(logger_, "StartAudioStreamResponse SUCCESS"); + if (app_mgr->IsStreamingAllowed(app->app_id(), ServiceType::kAudio)) { + app->set_audio_streaming_started(true); + } else { + LOG4CXX_DEBUG(logger_, + "StartAudioStreamRequest aborted. Application can not stream"); + } + } + break; + } + default: { + LOG4CXX_ERROR(logger_,"Received unknown event" << event.id()); + return; + } + } +} + +} // namespace commands + +} // namespace application_manager diff --git a/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_response.cc b/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_response.cc index 0509028a94..5547057a1f 100644 --- a/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_response.cc +++ b/src/components/application_manager/src/commands/hmi/navi_audio_start_stream_response.cc @@ -30,8 +30,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include "application_manager/commands/hmi/navi_audio_start_stream_response.h" -#include "application_manager/application_manager_impl.h" -#include "application_manager/application_impl.h" namespace application_manager { @@ -46,25 +44,10 @@ AudioStartStreamResponse::~AudioStartStreamResponse() { void AudioStartStreamResponse::Run() { LOG4CXX_AUTO_TRACE(logger_); - ApplicationSharedPtr app = - ApplicationManagerImpl::instance()->active_application(); - if (!app) { - LOG4CXX_ERROR_EXT(logger_, "NaviStartStreamResponse no active app!"); - return; - } - - const hmi_apis::Common_Result::eType code = - static_cast<hmi_apis::Common_Result::eType>( - (*message_)[strings::params][hmi_response::code].asInt()); - - if (hmi_apis::Common_Result::SUCCESS == code) { - LOG4CXX_INFO(logger_, "AudioStartStreamResponse SUCCESS"); - app->set_hmi_supports_navi_audio_streaming(true); - } else { - LOG4CXX_INFO(logger_, "AudioStartStreamResponse NOT SUCCESS"); - app->set_hmi_supports_navi_audio_streaming(false); - } + event_engine::Event event(hmi_apis::FunctionID::Navigation_StartAudioStream); + event.set_smart_object(*message_); + event.raise(); } } // namespace commands diff --git a/src/components/application_manager/src/commands/hmi/navi_start_stream_request.cc b/src/components/application_manager/src/commands/hmi/navi_start_stream_request.cc index 7ee3733e51..328e6a5481 100644 --- a/src/components/application_manager/src/commands/hmi/navi_start_stream_request.cc +++ b/src/components/application_manager/src/commands/hmi/navi_start_stream_request.cc @@ -31,6 +31,8 @@ */ #include "application_manager/commands/hmi/navi_start_stream_request.h" +#include "application_manager/application_manager_impl.h" +#include "protocol_handler/protocol_handler.h" namespace application_manager { @@ -42,16 +44,61 @@ NaviStartStreamRequest::NaviStartStreamRequest( } NaviStartStreamRequest::~NaviStartStreamRequest() { + LOG4CXX_AUTO_TRACE(logger_); } void NaviStartStreamRequest::Run() { LOG4CXX_AUTO_TRACE(logger_); + subscribe_on_event(hmi_apis::FunctionID::Navigation_StartStream, + correlation_id()); SendRequest(); } -} // namespace commands +void NaviStartStreamRequest::on_event(const event_engine::Event& event) { + using namespace protocol_handler; + LOG4CXX_AUTO_TRACE(logger_); -} // namespace application_manager + ApplicationManagerImpl* app_mgr = ApplicationManagerImpl::instance(); + if (!app_mgr) { + LOG4CXX_ERROR_EXT(logger_, "Application manager not found"); + return; + } + + ApplicationSharedPtr app = app_mgr->application_by_hmi_app(application_id()); + if (!app) { + LOG4CXX_ERROR_EXT(logger_, + "NaviStartStreamRequest aborted. Application not found"); + return; + } + + const smart_objects::SmartObject& message = event.smart_object(); + switch (event.id()) { + case hmi_apis::FunctionID::Navigation_StartStream: { + LOG4CXX_DEBUG(logger_, "Received StartStream event"); + const hmi_apis::Common_Result::eType code = + static_cast<hmi_apis::Common_Result::eType>( + message[strings::params][hmi_response::code].asInt()); + if (hmi_apis::Common_Result::SUCCESS == code) { + LOG4CXX_DEBUG(logger_, "NaviStartStreamResponse SUCCESS"); + if (app_mgr->IsStreamingAllowed(app->app_id(), ServiceType::kMobileNav)) { + app->set_video_streaming_started(true); + } else { + LOG4CXX_DEBUG(logger_, + "NaviStartStreamRequest aborted. Application can not stream"); + } + } + break; + } + default: { + LOG4CXX_ERROR(logger_,"Received unknown event" << event.id()); + return; + } + } +} + +} // namespace commands + +} // namespace application_manager diff --git a/src/components/application_manager/src/commands/hmi/navi_start_stream_response.cc b/src/components/application_manager/src/commands/hmi/navi_start_stream_response.cc index c2de690d63..a283891054 100644 --- a/src/components/application_manager/src/commands/hmi/navi_start_stream_response.cc +++ b/src/components/application_manager/src/commands/hmi/navi_start_stream_response.cc @@ -30,8 +30,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include "application_manager/commands/hmi/navi_start_stream_response.h" -#include "application_manager/application_manager_impl.h" -#include "application_manager/application_impl.h" namespace application_manager { @@ -47,25 +45,9 @@ NaviStartStreamResponse::~NaviStartStreamResponse() { void NaviStartStreamResponse::Run() { LOG4CXX_AUTO_TRACE(logger_); - ApplicationSharedPtr app = - ApplicationManagerImpl::instance()->active_application(); - - if (!app) { - LOG4CXX_ERROR_EXT(logger_, "NaviStartStreamResponse no active app!"); - return; - } - - const hmi_apis::Common_Result::eType code = - static_cast<hmi_apis::Common_Result::eType>( - (*message_)[strings::params][hmi_response::code].asInt()); - - if (hmi_apis::Common_Result::SUCCESS == code) { - LOG4CXX_INFO(logger_, "NaviStartStreamResponse SUCCESS"); - app->set_hmi_supports_navi_video_streaming(true); - } else { - LOG4CXX_INFO(logger_, "NaviStartStreamResponse NOT SUCCESS"); - app->set_hmi_supports_navi_video_streaming(false); - } + event_engine::Event event(hmi_apis::FunctionID::Navigation_StartStream); + event.set_smart_object(*message_); + event.raise(); } } // namespace commands diff --git a/src/components/application_manager/src/commands/hmi/on_audio_data_streaming_notification.cc b/src/components/application_manager/src/commands/hmi/on_audio_data_streaming_notification.cc new file mode 100644 index 0000000000..d94d298509 --- /dev/null +++ b/src/components/application_manager/src/commands/hmi/on_audio_data_streaming_notification.cc @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include "application_manager/commands/hmi/on_audio_data_streaming_notification.h" + +namespace application_manager { + +namespace commands { + +OnAudioDataStreamingNotification::OnAudioDataStreamingNotification( + const MessageSharedPtr& message) + : NotificationToHMI(message) { +} + +OnAudioDataStreamingNotification::~OnAudioDataStreamingNotification() { +} + +void OnAudioDataStreamingNotification::Run() { + LOG4CXX_AUTO_TRACE(logger_); + SendNotification(); +} + +} // namespace commands + +} // namespace application_manager + diff --git a/src/components/application_manager/src/commands/hmi/on_video_data_streaming_notification.cc b/src/components/application_manager/src/commands/hmi/on_video_data_streaming_notification.cc new file mode 100644 index 0000000000..12642a75f2 --- /dev/null +++ b/src/components/application_manager/src/commands/hmi/on_video_data_streaming_notification.cc @@ -0,0 +1,55 @@ + +/* + * 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. + */ + +#include "application_manager/commands/hmi/on_video_data_streaming_notification.h" + +namespace application_manager { + +namespace commands { + +OnVideoDataStreamingNotification::OnVideoDataStreamingNotification( + const MessageSharedPtr& message) + : NotificationToHMI(message) { +} + +OnVideoDataStreamingNotification::~OnVideoDataStreamingNotification() { +} + +void OnVideoDataStreamingNotification::Run() { + LOG4CXX_AUTO_TRACE(logger_); + SendNotification(); +} + +} // namespace commands + +} // namespace application_manager diff --git a/src/components/application_manager/src/commands/hmi/on_vr_language_change_notification.cc b/src/components/application_manager/src/commands/hmi/on_vr_language_change_notification.cc index b75cbe33bb..9a146c19e7 100644 --- a/src/components/application_manager/src/commands/hmi/on_vr_language_change_notification.cc +++ b/src/components/application_manager/src/commands/hmi/on_vr_language_change_notification.cc @@ -67,8 +67,8 @@ void OnVRLanguageChangeNotification::Run() { ApplicationManagerImpl::ApplicationListAccessor accessor; ApplicationManagerImpl::ApplictionSetIt it = accessor.begin(); - for (;accessor.end() != it; ++it) { - ApplicationSharedPtr app = (*it); + for (; accessor.end() != it;) { + ApplicationSharedPtr app = *it++; (*message_)[strings::params][strings::connection_key] = app->app_id(); SendNotificationToMobile(message_); if (static_cast<int32_t>(app->language()) diff --git a/src/components/application_manager/src/commands/mobile/perform_audio_pass_thru_request.cc b/src/components/application_manager/src/commands/mobile/perform_audio_pass_thru_request.cc index b3d57d6be0..02d7520ea0 100644 --- a/src/components/application_manager/src/commands/mobile/perform_audio_pass_thru_request.cc +++ b/src/components/application_manager/src/commands/mobile/perform_audio_pass_thru_request.cc @@ -153,12 +153,16 @@ void PerformAudioPassThruRequest::on_event(const event_engine::Event& event) { result_tts_speak_ = GetMobileResultCode(static_cast<hmi_apis::Common_Result::eType>( message[strings::params][hmi_response::code].asUInt())); is_active_tts_speak_ = false; - SendRecordStartNotification(); - StartMicrophoneRecording(); - ApplicationManagerImpl::instance()-> - updateRequestTimeout(connection_key(), - correlation_id(), - default_timeout()); + if (mobile_apis::Result::SUCCESS == result_tts_speak_) { + SendRecordStartNotification(); + StartMicrophoneRecording(); + + // update request timeout to get time for perform audio recording + ApplicationManagerImpl::instance()-> + updateRequestTimeout(connection_key(), + correlation_id(), + default_timeout()); + } break; } case hmi_apis::FunctionID::TTS_OnResetTimeout: { diff --git a/src/components/application_manager/src/commands/mobile/perform_interaction_request.cc b/src/components/application_manager/src/commands/mobile/perform_interaction_request.cc index 949fcab015..a80c5df964 100644 --- a/src/components/application_manager/src/commands/mobile/perform_interaction_request.cc +++ b/src/components/application_manager/src/commands/mobile/perform_interaction_request.cc @@ -393,10 +393,10 @@ void PerformInteractionRequest::ProcessPerformInteractionResponse( } else { msg_params = message[strings::msg_params]; msg_params[strings::trigger_source] = mobile_apis::TriggerSource::TS_MENU; - if (message[strings::msg_params].keyExists(strings::manual_text_entry)) { - msg_params[strings::trigger_source] = mobile_apis::TriggerSource::TS_KEYBOARD; - } } + } else if (message[strings::msg_params].keyExists(strings::manual_text_entry)) { + msg_params = message[strings::msg_params]; + msg_params[strings::trigger_source] = mobile_apis::TriggerSource::TS_KEYBOARD; } } diff --git a/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc b/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc index b2c08b66bd..2f8ac29aa0 100644 --- a/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc +++ b/src/components/application_manager/src/commands/mobile/register_app_interface_request.cc @@ -155,15 +155,14 @@ void RegisterAppInterfaceRequest::Run() { // Flag conditional compilation specific to customer is used in order to exclude hit code // to RTC // FIXME(EZamakhov): on shutdown - get freez - if (true == profile::Profile::instance()->launch_hmi()) { - // wait till HMI started - while (!ApplicationManagerImpl::instance()->IsHMICooperating()) { - sleep(1); - // TODO(DK): timer_->StartWait(1); - ApplicationManagerImpl::instance()->updateRequestTimeout(connection_key(), - correlation_id(), - default_timeout()); - } + + // wait till HMI started + while (!ApplicationManagerImpl::instance()->IsHMICooperating()) { + sleep(1); + // TODO(DK): timer_->StartWait(1); + ApplicationManagerImpl::instance()->updateRequestTimeout(connection_key(), + correlation_id(), + default_timeout()); } const std::string mobile_app_id = (*message_)[strings::msg_params][strings::app_id] diff --git a/src/components/application_manager/src/commands/mobile/send_location_request.cc b/src/components/application_manager/src/commands/mobile/send_location_request.cc index 8b889e2263..b1c96ebb98 100644 --- a/src/components/application_manager/src/commands/mobile/send_location_request.cc +++ b/src/components/application_manager/src/commands/mobile/send_location_request.cc @@ -195,13 +195,17 @@ bool SendLocationRequest::CheckHMICapabilities(std::list<hmi_apis::Common_TextFi using namespace smart_objects; using namespace hmi_apis; + if (fields_names.empty()) { + return true; + } + ApplicationManagerImpl* instance = ApplicationManagerImpl::instance(); const HMICapabilities& hmi_capabilities = instance->hmi_capabilities(); if (!hmi_capabilities.is_ui_cooperating()) { LOG4CXX_ERROR_EXT(logger_, "UI is not supported."); return false; } - const size_t size_before = fields_names.size(); + if (hmi_capabilities.display_capabilities()) { const SmartObject disp_cap = (*hmi_capabilities.display_capabilities()); const SmartObject& text_fields = disp_cap.getElement(hmi_response::text_fields); @@ -217,7 +221,8 @@ bool SendLocationRequest::CheckHMICapabilities(std::list<hmi_apis::Common_TextFi } } } - if (fields_names.size() == size_before) { + + if (!fields_names.empty()) { LOG4CXX_ERROR_EXT(logger_, "Some fields are not supported by capabilities"); return false; } diff --git a/src/components/application_manager/src/commands/mobile/subscribe_button_request.cc b/src/components/application_manager/src/commands/mobile/subscribe_button_request.cc index 2ba09abe9a..ece7c8332e 100644 --- a/src/components/application_manager/src/commands/mobile/subscribe_button_request.cc +++ b/src/components/application_manager/src/commands/mobile/subscribe_button_request.cc @@ -63,13 +63,20 @@ void SubscribeButtonRequest::Run() { static_cast<mobile_apis::ButtonName::eType>( (*message_)[str::msg_params][str::button_name].asUInt()); - if (!IsSubscribtionAllowed(app, btn_id)) { + if (!IsSubscriptionAllowed(app, btn_id)) { LOG4CXX_ERROR_EXT(logger_, "Subscribe on button " << btn_id << " isn't allowed"); SendResponse(false, mobile_apis::Result::REJECTED); return; } + if (!CheckHMICapabilities(btn_id)) { + LOG4CXX_ERROR_EXT(logger_, "Subscribe on button " << btn_id + << " isn't allowed by HMI capabilities"); + SendResponse(false, mobile_apis::Result::UNSUPPORTED_RESOURCE); + return; + } + if (app->IsSubscribedToButton(btn_id)) { LOG4CXX_ERROR_EXT(logger_, "Already subscribed to button " << btn_id); SendResponse(false, mobile_apis::Result::IGNORED); @@ -83,7 +90,7 @@ void SubscribeButtonRequest::Run() { app->UpdateHash(); } -bool SubscribeButtonRequest::IsSubscribtionAllowed( +bool SubscribeButtonRequest::IsSubscriptionAllowed( ApplicationSharedPtr app, mobile_apis::ButtonName::eType btn_id) { if (!app->is_media_application() && @@ -97,6 +104,37 @@ bool SubscribeButtonRequest::IsSubscribtionAllowed( return true; } +bool SubscribeButtonRequest::CheckHMICapabilities( + mobile_apis::ButtonName::eType button) { + using namespace smart_objects; + using namespace mobile_apis; + LOG4CXX_AUTO_TRACE(logger_); + + ApplicationManagerImpl* app_mgr = ApplicationManagerImpl::instance(); + DCHECK_OR_RETURN(app_mgr, false); + + const HMICapabilities& hmi_caps = app_mgr->hmi_capabilities(); + if (!hmi_caps.is_ui_cooperating()) { + LOG4CXX_ERROR_EXT(logger_, "UI is not supported by HMI."); + return false; + } + + const SmartObject* button_caps_ptr = hmi_caps.button_capabilities(); + if (button_caps_ptr) { + const SmartObject& button_caps = *button_caps_ptr; + const size_t length = button_caps.length(); + for (size_t i = 0; i < length; ++i) { + const SmartObject& caps = button_caps[i]; + const ButtonName::eType name = + static_cast<ButtonName::eType>(caps.getElement(hmi_response::button_name).asInt()); + if (name == button) { + return true; + } + } + } + return false; +} + void SubscribeButtonRequest::SendSubscribeButtonNotification() { using namespace smart_objects; using namespace hmi_apis; diff --git a/src/components/application_manager/src/hmi_command_factory.cc b/src/components/application_manager/src/hmi_command_factory.cc index 67e7ab6956..f8bf47bb71 100644 --- a/src/components/application_manager/src/hmi_command_factory.cc +++ b/src/components/application_manager/src/hmi_command_factory.cc @@ -63,6 +63,8 @@ #include "application_manager/commands/hmi/on_app_permission_changed_notification.h" #include "application_manager/commands/hmi/on_app_permission_consent_notification.h" #include "application_manager/commands/hmi/on_app_activated_notification.h" +#include "application_manager/commands/hmi/on_audio_data_streaming_notification.h" +#include "application_manager/commands/hmi/on_video_data_streaming_notification.h" #include "application_manager/commands/hmi/on_sdl_consent_needed_notification.h" #include "application_manager/commands/hmi/on_exit_all_applications_notification.h" #include "application_manager/commands/hmi/on_exit_application_notification.h" @@ -1962,6 +1964,14 @@ CommandSharedPtr HMICommandFactory::CreateCommand( } break; } + case hmi_apis::FunctionID::Navigation_OnAudioDataStreaming: { + command.reset(new commands::OnAudioDataStreamingNotification(message)); + break; + } + case hmi_apis::FunctionID::Navigation_OnVideoDataStreaming: { + command.reset(new commands::OnVideoDataStreamingNotification(message)); + break; + } case hmi_apis::FunctionID::VR_PerformInteraction: { if (is_response) { command.reset(new commands::VRPerformInteractionResponse(message)); diff --git a/src/components/application_manager/src/hmi_state.cc b/src/components/application_manager/src/hmi_state.cc index 4b4d09581e..16c0c09af2 100644 --- a/src/components/application_manager/src/hmi_state.cc +++ b/src/components/application_manager/src/hmi_state.cc @@ -30,15 +30,8 @@ void HmiState::set_parent(HmiStatePtr parent) { mobile_apis::AudioStreamingState::eType VRHmiState::audio_streaming_state() const { - using namespace helpers; using namespace mobile_apis; - AudioStreamingState::eType expected_state = AudioStreamingState::NOT_AUDIBLE; - if (state_context_.is_attenuated_supported() && - Compare<HMILevel::eType, EQ, ONE> (hmi_level(), HMILevel::HMI_FULL, - HMILevel::HMI_LIMITED)) { - expected_state = AudioStreamingState::ATTENUATED; - } - return expected_state; + return AudioStreamingState::NOT_AUDIBLE; } VRHmiState::VRHmiState(uint32_t app_id, StateContext& state_context): @@ -62,6 +55,26 @@ TTSHmiState::audio_streaming_state() const { return expected_state; } +NaviStreamingHmiState::NaviStreamingHmiState(uint32_t app_id, StateContext& state_context): + HmiState(app_id, state_context, STATE_ID_NAVI_STREAMING) { +} + +mobile_apis::AudioStreamingState::eType +NaviStreamingHmiState::audio_streaming_state() const { + using namespace helpers; + using namespace mobile_apis; + AudioStreamingState::eType expected_state = parent()->audio_streaming_state(); + if (Compare<HMILevel::eType, EQ, ONE> (hmi_level(), HMILevel::HMI_FULL) && + !state_context_.is_navi_app(app_id_)) { + if (state_context_.is_attenuated_supported()) { + expected_state = AudioStreamingState::ATTENUATED; + } else { + expected_state = AudioStreamingState::NOT_AUDIBLE; + } + } + return expected_state; +} + PhoneCallHmiState::PhoneCallHmiState(uint32_t app_id, StateContext& state_context): HmiState(app_id, state_context, STATE_ID_PHONE_CALL) { } diff --git a/src/components/application_manager/src/message_helper.cc b/src/components/application_manager/src/message_helper.cc index e578be23ee..461c2d169a 100644 --- a/src/components/application_manager/src/message_helper.cc +++ b/src/components/application_manager/src/message_helper.cc @@ -1842,6 +1842,36 @@ void MessageHelper::SendAudioStopStream(int32_t connection_key) { ApplicationManagerImpl::instance()->ManageHMICommand(stop_stream); } +void MessageHelper::SendOnDataStreaming(protocol_handler::ServiceType service, + bool available) { + using namespace protocol_handler; + smart_objects::SmartObjectSPtr notification = new smart_objects::SmartObject( + smart_objects::SmartType_Map); + + if (!notification) { + return; + } + + if (ServiceType::kAudio != service && ServiceType::kMobileNav != service) { + return; + } + + (*notification)[strings::params][strings::function_id] = + ServiceType::kAudio == service + ? hmi_apis::FunctionID::Navigation_OnAudioDataStreaming + : hmi_apis::FunctionID::Navigation_OnVideoDataStreaming; + (*notification)[strings::params][strings::message_type] = + hmi_apis::messageType::notification; + (*notification)[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + (*notification)[strings::params][strings::protocol_type] = + commands::CommandImpl::hmi_protocol_type_; + + (*notification)[strings::msg_params]["available"] = available; + + ApplicationManagerImpl::instance()->ManageHMICommand(notification); +} + bool MessageHelper::SendStopAudioPathThru() { LOG4CXX_INFO(logger_, "MessageHelper::SendAudioStopAudioPathThru"); diff --git a/src/components/application_manager/src/state_context.cc b/src/components/application_manager/src/state_context.cc index 37f53977df..ae3b40e094 100644 --- a/src/components/application_manager/src/state_context.cc +++ b/src/components/application_manager/src/state_context.cc @@ -31,6 +31,8 @@ */ #include "application_manager/state_context.h" #include "application_manager/application_manager_impl.h" +#include "config_profile/profile.h" + namespace application_manager { @@ -53,7 +55,8 @@ bool StateContext::is_voice_comunication_app(const uint32_t app_id) const { bool StateContext::is_attenuated_supported() const{ const HMICapabilities& hmi_capabilities = ApplicationManagerImpl::instance()->hmi_capabilities(); - return hmi_capabilities.attenuated_supported(); + return hmi_capabilities.attenuated_supported() && + profile::Profile::instance()->is_mixing_audio_supported(); } } diff --git a/src/components/application_manager/src/state_controller.cc b/src/components/application_manager/src/state_controller.cc index a6733503d8..c0efe01895 100644 --- a/src/components/application_manager/src/state_controller.cc +++ b/src/components/application_manager/src/state_controller.cc @@ -214,6 +214,8 @@ void StateController::OnStateChanged(ApplicationSharedPtr app, if (new_state->hmi_level() == mobile_apis::HMILevel::HMI_NONE) { app->ResetDataInNone(); } + ApplicationManagerImpl::instance()->OnHMILevelChanged(app->app_id(), + old_state->hmi_level(), new_state->hmi_level()); } else { LOG4CXX_ERROR(logger_, "Status not changed"); } @@ -356,6 +358,26 @@ void StateController::OnTTSStopped() { TempStateStopped(HmiState::STATE_ID_TTS_SESSION); } +void StateController::OnNaviStreamingStarted() { + LOG4CXX_AUTO_TRACE(logger_); + ForEachApplication(std::bind1st( + std::mem_fun( + &StateController::HMIStateStarted<HmiState::STATE_ID_NAVI_STREAMING>), + this) + ); + TempStateStarted(HmiState::STATE_ID_NAVI_STREAMING); +} + +void StateController::OnNaviStreamingStopped() { + LOG4CXX_AUTO_TRACE(logger_); + ForEachApplication(std::bind1st( + std::mem_fun( + &StateController::HMIStateStopped<HmiState::STATE_ID_NAVI_STREAMING>), + this) + ); + TempStateStopped(HmiState::STATE_ID_NAVI_STREAMING); +} + HmiStatePtr StateController::CreateHmiState(uint32_t app_id, HmiState::StateID state_id) { LOG4CXX_AUTO_TRACE(logger_); HmiStatePtr new_state; @@ -376,6 +398,10 @@ HmiStatePtr StateController::CreateHmiState(uint32_t app_id, HmiState::StateID s new_state.reset(new TTSHmiState(app_id, state_context_)); break; } + case HmiState::STATE_ID_NAVI_STREAMING: { + new_state.reset(new NaviStreamingHmiState(app_id, state_context_)); + break; + } case HmiState::STATE_ID_REGULAR: { new_state.reset(new HmiState(app_id, state_context_)); break; diff --git a/src/components/application_manager/test/mock/include/application_manager/application_manager_impl.h b/src/components/application_manager/test/mock/include/application_manager/application_manager_impl.h index 3d9e9103a5..8ef18a4d09 100644 --- a/src/components/application_manager/test/mock/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/test/mock/include/application_manager/application_manager_impl.h @@ -48,6 +48,7 @@ #include "application_manager/vehicle_info_data.h" #include "application_manager/state_controller.h" #include "protocol_handler/protocol_observer.h" +#include "protocol_handler/protocol_handler.h" #include "hmi_message_handler/hmi_message_observer.h" #include "hmi_message_handler/hmi_message_sender.h" @@ -243,10 +244,14 @@ class ApplicationManagerImpl : public ApplicationManager, MOCK_METHOD1(ReplaceHMIByMobileAppId, void(smart_objects::SmartObject&)); MOCK_METHOD1(ReplaceMobileByHMIAppId, void(smart_objects::SmartObject&)); MOCK_METHOD0(resume_controller, ResumeCtrl&()); - MOCK_METHOD1(IsVideoStreamingAllowed, bool(uint32_t)); MOCK_METHOD1(GetDefaultHmiLevel, mobile_api::HMILevel::eType (ApplicationSharedPtr)); - MOCK_METHOD1(IsAudioStreamingAllowed, bool(uint32_t)); + MOCK_METHOD2(IsStreamingAllowed, bool(uint32_t, protocol_handler::ServiceType)); + MOCK_METHOD2(CanAppStream, bool(uint32_t, protocol_handler::ServiceType)); + MOCK_METHOD1(EndNaviServices, void(int32_t)); + MOCK_METHOD1(ForbidStreaming, void(int32_t)); + MOCK_METHOD2(OnAppStreaming, void(int32_t, bool)); + MOCK_METHOD1(Unmute, void(VRTTSSessionChanging)); MOCK_METHOD1(Mute, void(VRTTSSessionChanging)); MOCK_METHOD2(set_application_id, void(const int32_t, const uint32_t)); diff --git a/src/components/config_profile/include/config_profile/profile.h b/src/components/config_profile/include/config_profile/profile.h index e81bda6fb9..c372109c29 100644 --- a/src/components/config_profile/include/config_profile/profile.h +++ b/src/components/config_profile/include/config_profile/profile.h @@ -240,6 +240,19 @@ class Profile : public utils::Singleton<Profile> { * @brief Returns path to testing file to which redirects audio stream */ const std::string& audio_stream_file() const; + + /** + * @brief Returns timeout for SDL to wait for the next package of raw data + * over audio service + */ + const std::uint32_t audio_data_stopped_timeout() const; + + /** + * @brief Returns timeout for SDL to wait for the next package of raw data + * over video service + */ + const std::uint32_t video_data_stopped_timeout() const; + /** * @brief Returns allowable max amount of requests per time scale for * application in hmi level none @@ -661,6 +674,8 @@ private: std::string system_files_path_; uint16_t transport_manager_tcp_adapter_port_; std::string tts_delimiter_; + std::uint32_t audio_data_stopped_timeout_; + std::uint32_t video_data_stopped_timeout_; std::string mme_db_name_; std::string event_mq_name_; std::string ack_mq_name_; diff --git a/src/components/config_profile/src/profile.cc b/src/components/config_profile/src/profile.cc index 449c94b9a3..1522228d2a 100644 --- a/src/components/config_profile/src/profile.cc +++ b/src/components/config_profile/src/profile.cc @@ -99,8 +99,8 @@ const char* kNamedVideoPipePathKey = "NamedVideoPipePath"; const char* kNamedAudioPipePathKey = "NamedAudioPipePath"; const char* kVideoStreamFileKey = "VideoStreamFile"; const char* kAudioStreamFileKey = "AudioStreamFile"; - - +const char* kAudioDataStoppedTimeoutKey = "AudioDataStoppedTimeout"; +const char* kVideoDataStoppedTimeoutKey = "VideoDataStoppedTimeout"; const char* kMixingAudioSupportedKey = "MixingAudioSupported"; const char* kHelpPromptKey = "HelpPromt"; const char* kTimeoutPromptKey = "TimeOutPromt"; @@ -172,6 +172,8 @@ const char* kDefaultServerAddress = "127.0.0.1"; const char* kDefaultAppInfoFileName = "app_info.dat"; const char* kDefaultSystemFilesPath = "/tmp/fs/mp/images/ivsu_cache"; const char* kDefaultTtsDelimiter = ","; +const uint32_t kDefaultAudioDataStoppedTimeout = 1000; +const uint32_t kDefaultVideoDataStoppedTimeout = 1000; const char* kDefaultMmeDatabaseName = "/dev/qdb/mediaservice_db"; const char* kDefaultEventMQ = "/dev/mqueue/ToSDLCoreUSBAdapter"; const char* kDefaultAckMQ = "/dev/mqueue/FromSDLCoreUSBAdapter"; @@ -285,23 +287,25 @@ Profile::Profile() system_files_path_(kDefaultSystemFilesPath), transport_manager_tcp_adapter_port_(kDefautTransportManagerTCPPort), tts_delimiter_(kDefaultTtsDelimiter), - mme_db_name_(kDefaultMmeDatabaseName), - event_mq_name_(kDefaultEventMQ), - ack_mq_name_(kDefaultAckMQ), - recording_file_source_(kDefaultRecordingFileSourceName), - recording_file_name_(kDefaultRecordingFileName), - application_list_update_timeout_(kDefaultApplicationListUpdateTimeout), - iap_legacy_protocol_mask_(kDefaultLegacyProtocolMask), - iap_hub_protocol_mask_(kDefaultHubProtocolMask), - iap_pool_protocol_mask_(kDefaultPoolProtocolMask), - iap_system_config_(kDefaultIAPSystemConfig), - iap2_system_config_(kDefaultIAP2SystemConfig), - iap2_hub_connect_attempts_(kDefaultIAP2HubConnectAttempts), - iap_hub_connection_wait_timeout_(kDefaultIAPHubConnectionWaitTimeout), - tts_global_properties_timeout_(kDefaultTTSGlobalPropertiesTimeout), - attempts_to_open_policy_db_(kDefaultAttemptsToOpenPolicyDB), - open_attempt_timeout_ms_(kDefaultAttemptsToOpenPolicyDB), - hash_string_size_(kDefaultHashStringSize) { + audio_data_stopped_timeout_(kDefaultAudioDataStoppedTimeout), + video_data_stopped_timeout_(kDefaultVideoDataStoppedTimeout), + mme_db_name_(kDefaultMmeDatabaseName), + event_mq_name_(kDefaultEventMQ), + ack_mq_name_(kDefaultAckMQ), + recording_file_source_(kDefaultRecordingFileSourceName), + recording_file_name_(kDefaultRecordingFileName), + application_list_update_timeout_(kDefaultApplicationListUpdateTimeout), + iap_legacy_protocol_mask_(kDefaultLegacyProtocolMask), + iap_hub_protocol_mask_(kDefaultHubProtocolMask), + iap_pool_protocol_mask_(kDefaultPoolProtocolMask), + iap_system_config_(kDefaultIAPSystemConfig), + iap2_system_config_(kDefaultIAP2SystemConfig), + iap2_hub_connect_attempts_(kDefaultIAP2HubConnectAttempts), + iap_hub_connection_wait_timeout_(kDefaultIAPHubConnectionWaitTimeout), + tts_global_properties_timeout_(kDefaultTTSGlobalPropertiesTimeout), + attempts_to_open_policy_db_(kDefaultAttemptsToOpenPolicyDB), + open_attempt_timeout_ms_(kDefaultAttemptsToOpenPolicyDB), + hash_string_size_(kDefaultHashStringSize) { } Profile::~Profile() { @@ -464,6 +468,13 @@ const std::string& Profile::audio_stream_file() const { return audio_stream_file_; } +const std::uint32_t Profile::audio_data_stopped_timeout() const { + return audio_data_stopped_timeout_; +} + +const std::uint32_t Profile::video_data_stopped_timeout() const { + return video_data_stopped_timeout_; +} const uint32_t& Profile::app_time_scale() const { return app_requests_time_scale_; @@ -813,7 +824,7 @@ void Profile::UpdateValues() { // Streaming timeout ReadUIntValue(&stop_streaming_timeout_, kDefaultStopStreamingTimeout, - kHmiSection, kStopStreamingTimeout); + kMediaManagerSection, kStopStreamingTimeout); stop_streaming_timeout_ = std::max(kDefaultStopStreamingTimeout, stop_streaming_timeout_); @@ -902,6 +913,17 @@ void Profile::UpdateValues() { LOG_UPDATED_VALUE(audio_stream_file_, kAudioStreamFileKey, kMediaManagerSection); + ReadUIntValue(&audio_data_stopped_timeout_, kDefaultAudioDataStoppedTimeout, + kMediaManagerSection, kAudioDataStoppedTimeoutKey); + + LOG_UPDATED_VALUE(audio_data_stopped_timeout_, kAudioDataStoppedTimeoutKey, + kMediaManagerSection); + + ReadUIntValue(&video_data_stopped_timeout_, kDefaultVideoDataStoppedTimeout, + kMediaManagerSection, kVideoDataStoppedTimeoutKey); + + LOG_UPDATED_VALUE(video_data_stopped_timeout_, kVideoDataStoppedTimeoutKey, + kMediaManagerSection); // Mixing audio parameter std::string mixing_audio_value; diff --git a/src/components/include/utils/timer_thread.h b/src/components/include/utils/timer_thread.h index eaa67effe2..4236c4e46f 100644 --- a/src/components/include/utils/timer_thread.h +++ b/src/components/include/utils/timer_thread.h @@ -134,9 +134,9 @@ class TimerThread { virtual bool isRunning(); /** - * @brief method suspends timer execution + * @brief Suspends timer execution after next loop. */ - virtual void pause(); + virtual void suspend(); /** * @brief Stop timer update timeout and start timer again @@ -187,12 +187,24 @@ class TimerThread { */ virtual void setTimeOut(const uint32_t timeout_seconds); + /** + * @brief Quits threadMain function after next loop. + */ + virtual void shouldBeStoped(); + + /** + * @brief Restarts non-loop timer after current iteration. + */ + virtual void shouldBeRestarted(); + protected: TimerThread* timer_thread_; uint32_t timeout_seconds_; sync_primitives::Lock state_lock_; sync_primitives::ConditionalVariable termination_condition_; volatile bool stop_flag_; + sync_primitives::Lock restart_flag_lock_; + volatile bool restart_flag_; int32_t calculateMillisecondsLeft(); private: @@ -261,11 +273,13 @@ template<class T> void TimerThread<T>::start(uint32_t timeout_seconds) { LOG4CXX_AUTO_TRACE(logger_); if (isRunning()) { - LOG4CXX_INFO(logger_, "TimerThread start needs stop " << name_); - stop(); + LOG4CXX_INFO(logger_, "Restart timer in thread " << name_); + delegate_->shouldBeRestarted(); + updateTimeOut(timeout_seconds); + } else { + updateTimeOut(timeout_seconds); + thread_->start(); } - updateTimeOut(timeout_seconds); - thread_->start(); } template<class T> @@ -291,10 +305,9 @@ bool TimerThread<T>::isRunning() { } template<class T> -void TimerThread<T>::pause() { - LOG4CXX_DEBUG(logger_, "Suspension of timer " << name_); - const uint32_t wait_seconds = std::numeric_limits<uint32_t>::max(); - updateTimeOut(wait_seconds); +void TimerThread<T>::suspend() { + LOG4CXX_DEBUG(logger_, "Suspend timer " << name_ << " after next loop"); + delegate_->shouldBeStoped(); } template<class T> @@ -313,7 +326,8 @@ TimerThread<T>::TimerDelegate::TimerDelegate(TimerThread* timer_thread) : timer_thread_(timer_thread), timeout_seconds_(0), state_lock_(true), - stop_flag_(false) { + stop_flag_(false), + restart_flag_(false) { DCHECK(timer_thread_); } @@ -344,11 +358,16 @@ void TimerThread<T>::TimerDelegate::threadMain() { LOG4CXX_TRACE(logger_, "Timer timeout " << wait_milliseconds_left << " ms"); timer_thread_->onTimeOut(); - return; } else { LOG4CXX_DEBUG(logger_, "Timeout reset force: " << TimerDelegate::timeout_seconds_); - return; + } + { + sync_primitives::AutoLock auto_lock(restart_flag_lock_); + if (!restart_flag_) { + return; + } + restart_flag_ = false; } } } @@ -378,8 +397,7 @@ void TimerThread<T>::TimerLooperDelegate::threadMain() { template<class T> void TimerThread<T>::TimerDelegate::exitThreadMain() { - sync_primitives::AutoLock auto_lock(state_lock_); - stop_flag_ = true; + shouldBeStoped(); termination_condition_.NotifyOne(); } @@ -390,6 +408,24 @@ void TimerThread<T>::TimerDelegate::setTimeOut(const uint32_t timeout_seconds) { } template<class T> +void TimerThread<T>::TimerDelegate::shouldBeStoped() { + { + sync_primitives::AutoLock auto_lock(state_lock_); + stop_flag_ = true; + } + { + sync_primitives::AutoLock auto_lock(restart_flag_lock_); + restart_flag_ = false; + } +} + +template<class T> +void TimerThread<T>::TimerDelegate::shouldBeRestarted() { + sync_primitives::AutoLock auto_lock(restart_flag_lock_); + restart_flag_ = true; +} + +template<class T> int32_t TimerThread<T>::TimerThread::TimerDelegate::calculateMillisecondsLeft() { time_t cur_time = time(NULL); time_t end_time = std::numeric_limits<time_t>::max(); diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index 77e3a0d382..8652c8e414 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -3201,6 +3201,18 @@ </function> <function name="StopAudioStream" messagetype="response"> </function> + <function name="OnAudioDataStreaming" messagetype="notification"> + <description>Sender: SDL->HMI. Purpose: notify about raw audio data presence over the URL provided via StartAudioStream SDL's request.</description> + <param name="available" type="Boolean" mandatory="true"> + <description>If "true" - audio data started. If "false" - audio data stopped.</description> + </param> + </function> + <function name="OnVideoDataStreaming" messagetype="notification"> + <description>Sender: SDL->HMI. Purpose: notify about raw video data presence over the URL provided via StartStream SDL's request.</description> + <param name="available" type="Boolean" mandatory="true"> + <description>If "true" - video data started. If "false" - video data stopped.</description> + </param> + </function> </interface> diff --git a/src/components/interfaces/QT_HMI_API.xml b/src/components/interfaces/QT_HMI_API.xml index aa6990e69a..5b13cf020f 100644 --- a/src/components/interfaces/QT_HMI_API.xml +++ b/src/components/interfaces/QT_HMI_API.xml @@ -3074,7 +3074,21 @@ </function> <function name="StopAudioStream" messagetype="response"> </function> + <function name="OnAudioDataStreaming" messagetype="notification"> + <description>Sender: SDL->HMI. Purpose: notify about raw audio data presence over the URL provided via StartAudioStream SDL's request.</description> + <param name="available" type="Boolean" mandatory="true"> + <description>If "true" - audio data started. If "false" - audio data stopped.</description> + </param> + </function> + <function name="OnVideoDataStreaming" messagetype="notification"> + <description>Sender: SDL->HMI. Purpose: notify about raw video data presence over the URL provided via StartStream SDL's request.</description> + <param name="available" type="Boolean" mandatory="true"> + <description>If "true" - video data started. If "false" - video data stopped.</description> + </param> + </function> + </interface> + <interface name="VehicleInfo" version="1.0" date="2013-04-21"> <function name="IsReady" messagetype="request" provider="hmi"> <description>Method is invoked at system startup. Response should provide information about presence of any of vehicle information modules (ECU, GPS, etc) and their readiness to cooperate with SDL.</description> diff --git a/src/components/media_manager/include/media_manager/media_adapter_impl.h b/src/components/media_manager/include/media_manager/media_adapter_impl.h index aad814224a..a3a296150b 100644 --- a/src/components/media_manager/include/media_manager/media_adapter_impl.h +++ b/src/components/media_manager/include/media_manager/media_adapter_impl.h @@ -56,6 +56,9 @@ class MediaAdapterImpl : public MediaAdapter { private: DISALLOW_COPY_AND_ASSIGN(MediaAdapterImpl); }; + +typedef utils::SharedPtr<MediaAdapterImpl> MediaAdapterImplPtr; + } // namespace media_manager #endif // SRC_COMPONENTS_MEDIA_MANAGER_INCLUDE_MEDIA_MANAGER_MEDIA_ADAPTER_IMPL_H_ diff --git a/src/components/media_manager/include/media_manager/media_manager.h b/src/components/media_manager/include/media_manager/media_manager.h index b879b7546e..b4f5c9c28b 100644 --- a/src/components/media_manager/include/media_manager/media_manager.h +++ b/src/components/media_manager/include/media_manager/media_manager.h @@ -34,22 +34,28 @@ #define SRC_COMPONENTS_MEDIA_MANAGER_INCLUDE_MEDIA_MANAGER_MEDIA_MANAGER_H_ #include <string> +#include "protocol_handler/protocol_handler.h" namespace media_manager { + class MediaManager { public: virtual void PlayA2DPSource(int32_t application_key) = 0; virtual void StopA2DPSource(int32_t application_key) = 0; + virtual void StartMicrophoneRecording(int32_t application_key, const std::string& outputFileName, int32_t duration) = 0; virtual void StopMicrophoneRecording(int32_t application_key) = 0; - virtual void StartVideoStreaming(int32_t application_key) = 0; - virtual void StopVideoStreaming(int32_t application_key) = 0; - virtual void StartAudioStreaming(int32_t application_key) = 0; - virtual void StopAudioStreaming(int32_t application_key) = 0; + + virtual void StartStreaming( + int32_t application_key, protocol_handler::ServiceType service_type) = 0; + virtual void StopStreaming( + int32_t application_key, protocol_handler::ServiceType service_type) = 0; virtual ~MediaManager(){} }; + } // namespace media_manager + #endif // SRC_COMPONENTS_MEDIA_MANAGER_INCLUDE_MEDIA_MANAGER_MEDIA_MANAGER_H_ diff --git a/src/components/media_manager/include/media_manager/media_manager_impl.h b/src/components/media_manager/include/media_manager/media_manager_impl.h index ad9af091bb..153ef42050 100644 --- a/src/components/media_manager/include/media_manager/media_manager_impl.h +++ b/src/components/media_manager/include/media_manager/media_manager_impl.h @@ -35,10 +35,8 @@ #include <string> #include "utils/singleton.h" -#include "utils/timer_thread.h" #include "protocol_handler/protocol_observer.h" #include "protocol_handler/protocol_handler.h" -#include "protocol/service_type.h" #include "media_manager/media_manager.h" #include "media_manager/media_adapter_impl.h" #include "media_manager/media_adapter_listener.h" @@ -50,18 +48,22 @@ class MediaManagerImpl : public MediaManager, public utils::Singleton<MediaManagerImpl> { public: virtual ~MediaManagerImpl(); - virtual void SetProtocolHandler( - protocol_handler::ProtocolHandler* protocol_handler); + virtual void PlayA2DPSource(int32_t application_key); virtual void StopA2DPSource(int32_t application_key); + virtual void StartMicrophoneRecording(int32_t application_key, const std::string& outputFileName, int32_t duration); virtual void StopMicrophoneRecording(int32_t application_key); - virtual void StartVideoStreaming(int32_t application_key); - virtual void StopVideoStreaming(int32_t application_key); - virtual void StartAudioStreaming(int32_t application_key); - virtual void StopAudioStreaming(int32_t application_key); + + virtual void StartStreaming( + int32_t application_key, protocol_handler::ServiceType service_type); + virtual void StopStreaming( + int32_t application_key, protocol_handler::ServiceType service_type); + + virtual void SetProtocolHandler( + protocol_handler::ProtocolHandler* protocol_handler); virtual void OnMessageReceived( const ::protocol_handler::RawMessagePtr message); virtual void OnMobileMessageSent( @@ -71,25 +73,21 @@ class MediaManagerImpl : public MediaManager, protected: MediaManagerImpl(); virtual void Init(); + protocol_handler::ProtocolHandler* protocol_handler_; MediaAdapter* a2dp_player_; + MediaAdapterImpl* from_mic_recorder_; MediaListenerPtr from_mic_listener_; - MediaAdapterImpl* video_streamer_; - MediaAdapterImpl* audio_streamer_; - uint32_t stop_streaming_timeout_; - MediaListenerPtr video_streamer_listener_; - MediaListenerPtr audio_streamer_listener_; - bool video_stream_active_; - bool audio_stream_active_; + + std::map<protocol_handler::ServiceType, MediaAdapterImplPtr> streamer_; + std::map<protocol_handler::ServiceType, MediaListenerPtr> streamer_listener_; private: - void OnStreamingEnded(); - timer::TimerThread<MediaManagerImpl> streaming_timer_; - uint32_t streaming_app_id_; DISALLOW_COPY_AND_ASSIGN(MediaManagerImpl); FRIEND_BASE_SINGLETON_CLASS(MediaManagerImpl); }; } // namespace media_manager + #endif // SRC_COMPONENTS_MEDIA_MANAGER_INCLUDE_MEDIA_MANAGER_MEDIA_MANAGER_IMPL_H_ diff --git a/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc b/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc index 1060f06a27..ef9d5b8de6 100644 --- a/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc +++ b/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc @@ -90,7 +90,10 @@ void FromMicRecorderAdapter::StopActivity(int32_t application_key) { } if (recorder_thread_) { - recorder_thread_->stop(); + recorder_thread_->join(); + delete recorder_thread_->delegate(); + threads::DeleteThread(recorder_thread_); + recorder_thread_ = NULL; } current_application_ = 0; } diff --git a/src/components/media_manager/src/audio/from_mic_recorder_listener.cc b/src/components/media_manager/src/audio/from_mic_recorder_listener.cc index 4073758db2..3718e82c60 100644 --- a/src/components/media_manager/src/audio/from_mic_recorder_listener.cc +++ b/src/components/media_manager/src/audio/from_mic_recorder_listener.cc @@ -90,7 +90,10 @@ void FromMicRecorderListener::OnActivityEnded(int32_t application_key) { return; } if (reader_) { - reader_->stop(); + reader_->join(); + delete reader_->delegate(); + threads::DeleteThread(reader_); + reader_ = NULL; } current_application_ = 0; } diff --git a/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc b/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc index a18299750f..88c358a494 100644 --- a/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc +++ b/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc @@ -45,6 +45,7 @@ FromMicToFileRecorderThread::FromMicToFileRecorderThread( const std::string& output_file, int32_t duration) : threads::ThreadDelegate(), argc_(5), + argv_(NULL), oKey_("-o"), tKey_("-t"), sleepThread_(NULL), @@ -185,8 +186,6 @@ void FromMicToFileRecorderThread::threadMain() { LOG4CXX_TRACE(logger_, "Initializing pipeline ..."); while (GST_STATE(pipeline) != GST_STATE_PLAYING) { - LOG4CXX_TRACE(logger_, "GST_STATE(pipeline) != GST_STATE_PLAYING"); - bool shouldBeStoped; { // FIXME(dchmerev@luxoft.com): @@ -195,10 +194,17 @@ void FromMicToFileRecorderThread::threadMain() { } if (shouldBeStoped) { + gst_element_set_state(pipeline, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(pipeline)); + g_option_context_free(context); + + if (argv_) { + delete [] argv_; + argv_ = NULL; + } return; } } - LOG4CXX_TRACE(logger_, "Pipeline started ...\n"); // Start up a timer for the pipeline @@ -220,6 +226,12 @@ void FromMicToFileRecorderThread::threadMain() { LOG4CXX_TRACE(logger_, "Deleting pipeline\n"); gst_object_unref(GST_OBJECT(pipeline)); g_main_loop_unref(loop); + g_option_context_free(context); + + if (argv_) { + delete [] argv_; + argv_ = NULL; + } loop = NULL; } diff --git a/src/components/media_manager/src/media_manager_impl.cc b/src/components/media_manager/src/media_manager_impl.cc index f5f6c97aec..cb9d5c4ff8 100644 --- a/src/components/media_manager/src/media_manager_impl.cc +++ b/src/components/media_manager/src/media_manager_impl.cc @@ -38,8 +38,10 @@ #include "application_manager/application.h" #include "application_manager/application_manager_impl.h" #include "application_manager/application_impl.h" +#include "protocol_handler/protocol_handler.h" #include "utils/file_system.h" #include "utils/logger.h" +#include "utils/helpers.h" #if defined(EXTENDED_MEDIA_MODE) #include "media_manager/audio/a2dp_source_player_adapter.h" #include "media_manager/audio/from_mic_recorder_adapter.h" @@ -50,23 +52,17 @@ #include "media_manager/audio/pipe_audio_streamer_adapter.h" #include "media_manager/video/video_stream_to_file_adapter.h" - namespace media_manager { using profile::Profile; +using timer::TimerThread; CREATE_LOGGERPTR_GLOBAL(logger_, "MediaManagerImpl") MediaManagerImpl::MediaManagerImpl() : protocol_handler_(NULL) , a2dp_player_(NULL) - , from_mic_recorder_(NULL) - , video_streamer_(NULL) - , audio_streamer_(NULL) - , video_stream_active_(false) - , audio_stream_active_(false) - , streaming_timer_("Streaming timer", this, &MediaManagerImpl::OnStreamingEnded) - , streaming_app_id_(0) { + , from_mic_recorder_(NULL) { Init(); } @@ -80,24 +76,10 @@ MediaManagerImpl::~MediaManagerImpl() { delete from_mic_recorder_; from_mic_recorder_ = NULL; } - - if (video_streamer_) { - delete video_streamer_; - video_streamer_ = NULL; - } - - if (audio_streamer_) { - delete audio_streamer_; - audio_streamer_ = NULL; - } -} - -void MediaManagerImpl::SetProtocolHandler( - protocol_handler::ProtocolHandler* protocol_handler) { - protocol_handler_ = protocol_handler; } void MediaManagerImpl::Init() { + using namespace protocol_handler; LOG4CXX_INFO(logger_, "MediaManagerImpl::Init()"); #if defined(EXTENDED_MEDIA_MODE) @@ -107,41 +89,37 @@ void MediaManagerImpl::Init() { #endif if ("socket" == profile::Profile::instance()->video_server_type()) { - video_streamer_ = new SocketVideoStreamerAdapter(); + streamer_[ServiceType::kMobileNav] = new SocketVideoStreamerAdapter(); } else if ("pipe" == profile::Profile::instance()->video_server_type()) { - video_streamer_ = new PipeVideoStreamerAdapter(); + streamer_[ServiceType::kMobileNav] = new PipeVideoStreamerAdapter(); } else if ("file" == profile::Profile::instance()->video_server_type()) { - video_streamer_ = new VideoStreamToFileAdapter( + streamer_[ServiceType::kMobileNav] = new VideoStreamToFileAdapter( profile::Profile::instance()->video_stream_file()); } if ("socket" == profile::Profile::instance()->audio_server_type()) { - audio_streamer_ = new SocketAudioStreamerAdapter(); + streamer_[ServiceType::kAudio] = new SocketAudioStreamerAdapter(); } else if ("pipe" == profile::Profile::instance()->audio_server_type()) { - audio_streamer_ = new PipeAudioStreamerAdapter(); + streamer_[ServiceType::kAudio] = new PipeAudioStreamerAdapter(); } else if ("file" == profile::Profile::instance()->audio_server_type()) { - audio_streamer_ = new VideoStreamToFileAdapter( + streamer_[ServiceType::kAudio] = new VideoStreamToFileAdapter( profile::Profile::instance()->audio_stream_file()); } - stop_streaming_timeout_ = profile::Profile::instance()->stop_streaming_timeout(); - - video_streamer_listener_ = new StreamerListener(); - audio_streamer_listener_ = new StreamerListener(); + streamer_listener_[ServiceType::kMobileNav] = new StreamerListener(); + streamer_listener_[ServiceType::kAudio] = new StreamerListener(); - if (NULL != video_streamer_) { - video_streamer_->AddListener(video_streamer_listener_); + if (streamer_[ServiceType::kMobileNav]) { + streamer_[ServiceType::kMobileNav]->AddListener( + streamer_listener_[ServiceType::kMobileNav]); } - if (NULL != audio_streamer_) { - audio_streamer_->AddListener(audio_streamer_listener_); + if (streamer_[ServiceType::kAudio]) { + streamer_[ServiceType::kAudio]->AddListener( + streamer_listener_[ServiceType::kAudio]); } } -void MediaManagerImpl::OnStreamingEnded() { - application_manager::ApplicationManagerImpl::instance()->StreamingEnded(streaming_app_id_); -} - void MediaManagerImpl::PlayA2DPSource(int32_t application_key) { LOG4CXX_AUTO_TRACE(logger_); if (a2dp_player_) { @@ -219,78 +197,71 @@ void MediaManagerImpl::StopMicrophoneRecording(int32_t application_key) { if (from_mic_listener_) { from_mic_listener_->OnActivityEnded(application_key); } +#if defined(EXTENDED_MEDIA_MODE) + if (from_mic_recorder_) { + from_mic_recorder_->RemoveListener(from_mic_listener_); + } +#endif } -void MediaManagerImpl::StartVideoStreaming(int32_t application_key) { +void MediaManagerImpl::StartStreaming( + int32_t application_key, protocol_handler::ServiceType service_type) { LOG4CXX_AUTO_TRACE(logger_); - if (video_streamer_) { - if (!video_stream_active_) { - video_stream_active_ = true; - video_streamer_->StartActivity(application_key); - application_manager::MessageHelper::SendNaviStartStream(application_key); - } + if (streamer_[service_type]) { + streamer_[service_type]->StartActivity(application_key); } -} - -void MediaManagerImpl::StopVideoStreaming(int32_t application_key) { - LOG4CXX_AUTO_TRACE(logger_); - if (video_streamer_) { - video_stream_active_ = false; - application_manager::MessageHelper::SendNaviStopStream(application_key); - video_streamer_->StopActivity(application_key); + if (streamer_listener_[service_type]) { + streamer_listener_[service_type]->OnActivityStarted(application_key); } } -void MediaManagerImpl::StartAudioStreaming(int32_t application_key) { +void MediaManagerImpl::StopStreaming( + int32_t application_key, protocol_handler::ServiceType service_type) { LOG4CXX_AUTO_TRACE(logger_); - if (audio_streamer_) { - if (!audio_stream_active_) { - audio_stream_active_ = true; - audio_streamer_->StartActivity(application_key); - application_manager::MessageHelper::SendAudioStartStream(application_key); - } + if (streamer_listener_[service_type]) { + streamer_listener_[service_type]->OnActivityEnded(application_key); + } + if (streamer_[service_type]) { + streamer_[service_type]->StopActivity(application_key); } } -void MediaManagerImpl::StopAudioStreaming(int32_t application_key) { - LOG4CXX_AUTO_TRACE(logger_); - if (audio_streamer_) { - audio_stream_active_ = false; - application_manager::MessageHelper::SendAudioStopStream(application_key); - audio_streamer_->StopActivity(application_key); - } +void MediaManagerImpl::SetProtocolHandler( + protocol_handler::ProtocolHandler* protocol_handler) { + protocol_handler_ = protocol_handler; } void MediaManagerImpl::OnMessageReceived( - const ::protocol_handler::RawMessagePtr message) { - using namespace application_manager; + const ::protocol_handler::RawMessagePtr message) { using namespace protocol_handler; + using namespace application_manager; + using namespace helpers; + LOG4CXX_AUTO_TRACE(logger_); - streaming_app_id_ = message->connection_key(); - const bool can_stream = - ApplicationManagerImpl::instance()->CanAppStream(streaming_app_id_); - if (!can_stream) { - ApplicationManagerImpl::instance()->ForbidStreaming(streaming_app_id_); - LOG4CXX_DEBUG(logger_, "The application trying to stream when it should not."); + const uint32_t streaming_app_id = message->connection_key(); + const ServiceType service_type = message->service_type(); + + if (Compare<ServiceType, NEQ, ALL>( + service_type, ServiceType::kMobileNav, ServiceType::kAudio)) { + LOG4CXX_DEBUG(logger_, "Unsupported service type in MediaManager"); return; } - if (message->service_type() == kMobileNav) { - if ((ApplicationManagerImpl::instance()-> IsVideoStreamingAllowed(streaming_app_id_))) { - if (video_streamer_) { - video_streamer_->SendData(message->connection_key(), message); - streaming_timer_.start(stop_streaming_timeout_); - } - } - } else if (message->service_type() == kAudio) { - if ((ApplicationManagerImpl::instance()-> IsAudioStreamingAllowed(streaming_app_id_))) { - if (audio_streamer_) { - audio_streamer_->SendData(message->connection_key(), message); - streaming_timer_.start(stop_streaming_timeout_); - } - } + ApplicationManagerImpl* app_mgr = ApplicationManagerImpl::instance(); + DCHECK_OR_RETURN_VOID(app_mgr); + + if (!app_mgr->CanAppStream(streaming_app_id, service_type)) { + app_mgr->ForbidStreaming(streaming_app_id); + LOG4CXX_ERROR(logger_, "The application trying to stream when it should not."); + return; + } + + ApplicationSharedPtr app = app_mgr->application(streaming_app_id); + if (app) { + app->WakeUpStreaming(service_type); + streamer_[service_type]->SendData(streaming_app_id, message); } } |