diff options
author | Jacob Keeler <jacob.keeler@livioradio.com> | 2018-07-16 14:36:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-16 14:36:35 -0700 |
commit | 4dde9552b3d9ab5fa29502810be48bdf0f793cd7 (patch) | |
tree | 4870b3b1721cd9595a7118f789c610fa1b44f83e /src/components/application_manager/src | |
parent | 5cff788119f1e62344b94aebb7ca23cf63dc39f8 (diff) | |
parent | 2f05a630fe5f35bc46f3003d9fc35d3451c130c4 (diff) | |
download | sdl_core-4dde9552b3d9ab5fa29502810be48bdf0f793cd7.tar.gz |
Merge pull request #2199 from smartdevicelink/feature/handling_VR_help_requests
Feature/handling vr help requests
Diffstat (limited to 'src/components/application_manager/src')
5 files changed, 426 insertions, 3 deletions
diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index 2a2e13fc0d..717fbeba1b 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -126,6 +126,7 @@ ApplicationImpl::ApplicationImpl( , device_id_(device_id) , secondary_device_id_(0) , usage_report_(mobile_app_id, statistics_manager) + , help_prompt_manager_impl_(*this, application_manager) , protocol_version_( protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_3) , is_voice_communication_application_(false) @@ -797,6 +798,10 @@ UsageStatistics& ApplicationImpl::usage_report() { return usage_report_; } +HelpPromptManager& ApplicationImpl::help_prompt_manager() { + return help_prompt_manager_impl_; +} + bool ApplicationImpl::AreCommandLimitsExceeded( mobile_apis::FunctionID::eType cmd_id, TLimitSource source) { TimevalStruct current = date_time::DateTime::getCurrentTime(); diff --git a/src/components/application_manager/src/help_prompt_manager_impl.cc b/src/components/application_manager/src/help_prompt_manager_impl.cc new file mode 100644 index 0000000000..0587327791 --- /dev/null +++ b/src/components/application_manager/src/help_prompt_manager_impl.cc @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2018, 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/help_prompt_manager_impl.h" +#include "application_manager/application.h" +#include "application_manager/application_manager.h" +#include "application_manager/commands/command_impl.h" +#include "application_manager/message_helper.h" +#include "application_manager/smart_object_keys.h" +#include "smart_objects/smart_object.h" +#include "utils/logger.h" +#include "utils/make_shared.h" + +CREATE_LOGGERPTR_GLOBAL(logger_, "HelpPromptManagerImpl") + +namespace { +const size_t kLimitCommand = 30; +} + +namespace application_manager { + +HelpPromptManagerImpl::HelpPromptManagerImpl(Application& app, + ApplicationManager& app_manager) + : app_(app) + , app_manager_(app_manager) + , sending_type_(SendingType::kSendBoth) + , is_tts_send_(false) + , is_ui_send_(false) {} + +HelpPromptManagerImpl::~HelpPromptManagerImpl() { + LOG4CXX_AUTO_TRACE(logger_); +} + +bool HelpPromptManagerImpl::AddCommand( + const uint32_t cmd_id, const smart_objects::SmartObject& command) { + if (!command.keyExists(strings::vr_commands)) { + LOG4CXX_DEBUG(logger_, "vr_commands does`t present"); + return false; + } + + sync_primitives::AutoLock lock(vr_commands_lock_); + auto it = std::find_if( + vr_commands_.begin(), + vr_commands_.end(), + [cmd_id](const VRCommandPair& pair) { return pair.first == cmd_id; }); + + if (vr_commands_.end() != it) { + LOG4CXX_DEBUG(logger_, "Commands with id:" << cmd_id << " already exists"); + return false; + } + + const smart_objects::SmartObject& commands = command[strings::vr_commands]; + const size_t count_new_commands = commands.length(); + const bool limit_exceeded = + kLimitCommand <= GetCommandsCount(vr_commands_.end()); + + LOG4CXX_DEBUG(logger_, "Will be added " << count_new_commands << " commands"); + + smart_objects::SmartObjectSPtr vr_item = + utils::MakeShared<smart_objects::SmartObject>( + smart_objects::SmartType_Array); + smart_objects::SmartArray& ar_vr_cmd = *(vr_item->asArray()); + smart_objects::SmartArray& ar_cmd = *(commands.asArray()); + ar_vr_cmd.reserve(count_new_commands); + ar_vr_cmd.insert( + ar_vr_cmd.end(), ar_cmd.begin(), ar_cmd.begin() + count_new_commands); + vr_commands_.push_back(std::make_pair(cmd_id, vr_item)); + + LOG4CXX_DEBUG(logger_, + "VR commands with id: " << cmd_id << " added for appID: " + << app_.app_id() << ". Total " + << vr_commands_.size() << " in cache"); + + return !limit_exceeded; +} + +bool HelpPromptManagerImpl::DeleteCommand(const uint32_t cmd_id) { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock lock(vr_commands_lock_); + + auto it = std::find_if( + vr_commands_.begin(), + vr_commands_.end(), + [cmd_id](const VRCommandPair& pair) { return pair.first == cmd_id; }); + + if (vr_commands_.end() == it) { + LOG4CXX_WARN(logger_, "VR command with id: " << cmd_id << " not found"); + return false; + } + + const size_t commands_before_current = GetCommandsCount(it); + vr_commands_.erase(it); + LOG4CXX_DEBUG(logger_, + "VR command with id: " + << cmd_id << " found after " << commands_before_current + << " commands was deleted for appID: " << app_.app_id() + << " Cache size after deleting: " << vr_commands_.size()); + + return commands_before_current < kLimitCommand; +} + +void HelpPromptManagerImpl::OnVrCommandAdded( + const uint32_t cmd_id, + const smart_objects::SmartObject& command, + const bool is_resumption) { + LOG4CXX_AUTO_TRACE(logger_); + if (SendingType::kNoneSend == sending_type_) { + LOG4CXX_DEBUG(logger_, + "SendingType::kNoneSend" + << " commands with id:" << cmd_id + << " will not be added"); + return; + } + if (AddCommand(cmd_id, command) && !is_resumption) { + SendRequests(); + } +} + +void HelpPromptManagerImpl::OnVrCommandDeleted(const uint32_t cmd_id, + const bool is_resumption) { + LOG4CXX_AUTO_TRACE(logger_); + if (SendingType::kNoneSend == sending_type_) { + LOG4CXX_DEBUG(logger_, + "SendingType::kNoneSend" + << " commands with id:" << cmd_id + << " will not be deleted"); + return; + } + if (DeleteCommand(cmd_id) && !is_resumption) { + SendRequests(); + } +} + +void HelpPromptManagerImpl::OnSetGlobalPropertiesReceived( + const smart_objects::SmartObject& msg, const bool is_response) { + LOG4CXX_AUTO_TRACE(logger_); + if (SendingType::kNoneSend == sending_type_) { + LOG4CXX_DEBUG(logger_, + "SendingType::kNoneSend" + " do not track SetGlobalProperties"); + return; + } + + if (!is_response) { + if (msg.keyExists(strings::help_prompt)) { + is_tts_send_ = true; + } + if (msg.keyExists(strings::vr_help)) { + is_ui_send_ = true; + } + + LOG4CXX_DEBUG(logger_, "is_tts_send_:" << is_tts_send_); + LOG4CXX_DEBUG(logger_, "is_ui_send_:" << is_ui_send_); + return; + } + + SetSendingType(msg); +} + +HelpPromptManagerImpl::SendingType HelpPromptManagerImpl::GetSendingType() + const { + return sending_type_; +} + +size_t HelpPromptManagerImpl::GetCommandsCount( + VRCommandPairs::const_iterator end_element) const { + size_t commands_count = 0; + std::for_each(vr_commands_.begin(), + end_element, + [&commands_count](const VRCommandPair& pair) { + commands_count += pair.second->length(); + }); + return commands_count; +} + +void HelpPromptManagerImpl::SendTTSRequest() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "TTS request for appID:" << app_.app_id()); + smart_objects::SmartObjectSPtr tts_global_properties = + utils::MakeShared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + if (tts_global_properties) { + smart_objects::SmartObject& ref = *tts_global_properties; + + ref[strings::params][strings::message_type] = + hmi_apis::messageType::request; + ref[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + ref[strings::params][strings::protocol_type] = + commands::CommandImpl::hmi_protocol_type_; + ref[strings::params][strings::correlation_id] = + app_manager_.GetNextHMICorrelationID(); + + smart_objects::SmartObject& so_to_send = *tts_global_properties; + so_to_send[strings::params][strings::function_id] = + hmi_apis::FunctionID::TTS_SetGlobalProperties; + + smart_objects::SmartObject msg_params = + smart_objects::SmartObject(smart_objects::SmartType_Map); + + CreatePromptMsg(msg_params); + + msg_params[strings::app_id] = app_.app_id(); + so_to_send[strings::msg_params] = msg_params; + app_manager_.GetRPCService().ManageHMICommand(tts_global_properties); + } + is_tts_send_ = false; +} + +void HelpPromptManagerImpl::SendUIRequest() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "UI request for appID:" << app_.app_id()); + smart_objects::SmartObjectSPtr ui_global_properties = + utils::MakeShared<smart_objects::SmartObject>( + smart_objects::SmartType_Map); + if (ui_global_properties) { + smart_objects::SmartObject& ref = *ui_global_properties; + + ref[strings::params][strings::message_type] = + hmi_apis::messageType::request; + ref[strings::params][strings::protocol_version] = + commands::CommandImpl::protocol_version_; + ref[strings::params][strings::protocol_type] = + commands::CommandImpl::hmi_protocol_type_; + ref[strings::params][strings::correlation_id] = + app_manager_.GetNextHMICorrelationID(); + + smart_objects::SmartObject& so_to_send = *ui_global_properties; + so_to_send[strings::params][strings::function_id] = + hmi_apis::FunctionID::UI_SetGlobalProperties; + + smart_objects::SmartObject msg_params = + smart_objects::SmartObject(smart_objects::SmartType_Map); + + CreateVRMsg(msg_params); + + msg_params[strings::app_id] = app_.app_id(); + so_to_send[strings::msg_params] = msg_params; + app_manager_.GetRPCService().ManageHMICommand(ui_global_properties); + } + is_ui_send_ = false; +} + +void HelpPromptManagerImpl::SendBothRequests() { + LOG4CXX_AUTO_TRACE(logger_); + SendTTSRequest(); + SendUIRequest(); +} + +void HelpPromptManagerImpl::SendRequests() { + LOG4CXX_AUTO_TRACE(logger_); + + sync_primitives::AutoLock lock(vr_commands_lock_); + switch (sending_type_) { + case SendingType::kSendHelpPrompt: + SendTTSRequest(); + return; + case SendingType::kSendVRHelp: + SendUIRequest(); + return; + case SendingType::kSendBoth: + SendBothRequests(); + return; + case SendingType::kNoneSend: + break; + } + LOG4CXX_DEBUG(logger_, + "SendingType:" << static_cast<uint32_t>(sending_type_) + << " request not sending"); +} + +void HelpPromptManagerImpl::CreatePromptMsg( + smart_objects::SmartObject& out_msg_params) { + LOG4CXX_AUTO_TRACE(logger_); + out_msg_params[strings::help_prompt] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + uint32_t index = 0; + for (size_t i = 0; i < vr_commands_.size(); ++i) { + const VRCommandPair& pair = vr_commands_[i]; + for (size_t j = 0; j < pair.second->length() && index < kLimitCommand; + ++j) { + smart_objects::SmartObject item(smart_objects::SmartType_Map); + + item[strings::text] = pair.second->getElement(j).asString(); + item[strings::type] = mobile_apis::SpeechCapabilities::SC_TEXT; + + out_msg_params[strings::help_prompt][index++] = item; + } + } + app_.set_help_prompt(out_msg_params[strings::help_prompt]); +} + +void HelpPromptManagerImpl::CreateVRMsg( + smart_objects::SmartObject& out_msg_params) { + LOG4CXX_AUTO_TRACE(logger_); + if (false == out_msg_params.keyExists(strings::vr_help_title)) { + if (app_.vr_help_title()) { + out_msg_params[strings::vr_help_title] = (*app_.vr_help_title()); + } else { + out_msg_params[strings::vr_help_title] = app_.name(); + } + } + out_msg_params[strings::vr_help] = + smart_objects::SmartObject(smart_objects::SmartType_Array); + uint32_t index = 0; + for (size_t i = 0; i < vr_commands_.size(); ++i) { + const VRCommandPair& pair = vr_commands_[i]; + for (size_t j = 0; j < pair.second->length() && index < kLimitCommand; + ++j) { + smart_objects::SmartObject item(smart_objects::SmartType_Map); + + item[strings::text] = pair.second->getElement(j).asString(); + item[strings::position] = index + 1; + + out_msg_params[strings::vr_help][index++] = item; + } + } + if (out_msg_params[strings::vr_help].empty()) { + out_msg_params.erase(strings::vr_help); + app_.reset_vr_help(); + } else { + app_.set_vr_help(out_msg_params[strings::vr_help]); + } +} + +void HelpPromptManagerImpl::SetSendingType( + const smart_objects::SmartObject& msg) { + LOG4CXX_AUTO_TRACE(logger_); + + hmi_apis::Common_Result::eType result = + static_cast<hmi_apis::Common_Result::eType>( + msg[strings::params][hmi_response::code].asInt()); + LOG4CXX_DEBUG(logger_, "HMI response result:" << result); + if (hmi_apis::Common_Result::eType::SUCCESS == result) { + hmi_apis::FunctionID::eType function_id = + static_cast<hmi_apis::FunctionID::eType>( + msg[strings::params][strings::function_id].asUInt()); + LOG4CXX_DEBUG(logger_, "Function id:" << function_id); + switch (function_id) { + case hmi_apis::FunctionID::TTS_SetGlobalProperties: { + if (is_tts_send_) { + is_tts_send_ = false; + sending_type_ = SendingType::kSendHelpPrompt == sending_type_ + ? SendingType::kNoneSend + : SendingType::kSendVRHelp; + } + break; + } + case hmi_apis::FunctionID::UI_SetGlobalProperties: { + if (is_ui_send_) { + is_ui_send_ = false; + sending_type_ = SendingType::kSendVRHelp == sending_type_ + ? SendingType::kNoneSend + : SendingType::kSendHelpPrompt; + } + break; + } + default: { break; } + } + LOG4CXX_DEBUG( + logger_, + "Sending type set to:" << static_cast<uint32_t>(sending_type_)); + } +} + +} // namespace application_manager diff --git a/src/components/application_manager/src/helpers/application_helper.cc b/src/components/application_manager/src/helpers/application_helper.cc index 66afd6b0b6..59f1c6caf2 100644 --- a/src/components/application_manager/src/helpers/application_helper.cc +++ b/src/components/application_manager/src/helpers/application_helper.cc @@ -21,6 +21,7 @@ void DeleteCommands(ApplicationSharedPtr app, ApplicationManager& app_manager) { for (auto cmd : cmap) { MessageHelper::SendDeleteCommandRequest(cmd.second, app, app_manager); app->RemoveCommand(cmd.first); + app->help_prompt_manager().OnVrCommandDeleted(cmd.first, true); } } diff --git a/src/components/application_manager/src/message_helper/message_helper.cc b/src/components/application_manager/src/message_helper/message_helper.cc index 47bcffd3f5..81491b7bf9 100644 --- a/src/components/application_manager/src/message_helper/message_helper.cc +++ b/src/components/application_manager/src/message_helper/message_helper.cc @@ -1069,9 +1069,19 @@ MessageHelper::CreateGlobalPropertiesRequestsToHMI( return requests; } + auto& help_prompt_manager = + const_cast<Application*>(app.get())->help_prompt_manager(); + + const bool can_send_ui = helpers::Compare<HelpPromptManager::SendingType, + helpers::EQ, + helpers::ONE>( + help_prompt_manager.GetSendingType(), + HelpPromptManager::SendingType::kSendVRHelp, + HelpPromptManager::SendingType::kSendBoth); + // UI global properties - if (app->vr_help_title() || app->vr_help()) { + if (can_send_ui && (app->vr_help_title() || app->vr_help())) { smart_objects::SmartObjectSPtr ui_global_properties = CreateMessageForHMI(hmi_apis::messageType::request, correlation_id); if (!ui_global_properties) { @@ -1105,8 +1115,15 @@ MessageHelper::CreateGlobalPropertiesRequestsToHMI( requests.push_back(ui_global_properties); } + const bool can_send_vr = helpers::Compare<HelpPromptManager::SendingType, + helpers::EQ, + helpers::ONE>( + help_prompt_manager.GetSendingType(), + HelpPromptManager::SendingType::kSendHelpPrompt, + HelpPromptManager::SendingType::kSendBoth); + // TTS global properties - if (app->help_prompt() || app->timeout_prompt()) { + if (can_send_vr && (app->help_prompt() || app->timeout_prompt())) { smart_objects::SmartObjectSPtr tts_global_properties = CreateMessageForHMI(hmi_apis::messageType::request, correlation_id); if (!tts_global_properties) { diff --git a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc index 2cdab710f1..be2bff5534 100644 --- a/src/components/application_manager/src/resumption/resume_ctrl_impl.cc +++ b/src/components/application_manager/src/resumption/resume_ctrl_impl.cc @@ -625,8 +625,12 @@ void ResumeCtrlImpl::AddCommands(ApplicationSharedPtr application, saved_app[strings::application_commands]; for (size_t i = 0; i < app_commands.length(); ++i) { const smart_objects::SmartObject& command = app_commands[i]; + const uint32_t cmd_id = command[strings::cmd_id].asUInt(); + const bool is_resumption = true; - application->AddCommand(command[strings::cmd_id].asUInt(), command); + application->AddCommand(cmd_id, command); + application->help_prompt_manager().OnVrCommandAdded( + cmd_id, command, is_resumption); } ProcessHMIRequests(MessageHelper::CreateAddCommandRequestToHMI( application, application_manager_)); |