summaryrefslogtreecommitdiff
path: root/src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc')
-rw-r--r--src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc289
1 files changed, 209 insertions, 80 deletions
diff --git a/src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc b/src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc
index 583f0a046..813f55091 100644
--- a/src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc
+++ b/src/components/application_manager/src/commands/mobile/create_interaction_choice_set_request.cc
@@ -45,18 +45,22 @@ namespace application_manager {
namespace commands {
CreateInteractionChoiceSetRequest::CreateInteractionChoiceSetRequest(
- const MessageSharedPtr& message)
- : CommandRequestImpl(message) {
+ const MessageSharedPtr& message)
+ : CommandRequestImpl(message),
+ expected_chs_count_(0),
+ received_chs_count_(0),
+ error_from_hmi_(false) {
}
CreateInteractionChoiceSetRequest::~CreateInteractionChoiceSetRequest() {
+ LOG4CXX_AUTO_TRACE(logger_);
}
void CreateInteractionChoiceSetRequest::Run() {
- LOG4CXX_INFO(logger_, "CreateInteractionChoiceSetRequest::Run");
-
+ LOG4CXX_AUTO_TRACE(logger_);
+ using namespace mobile_apis;
ApplicationSharedPtr app = ApplicationManagerImpl::instance()->application(
- (*message_)[strings::params][strings::connection_key].asUInt());
+ (*message_)[strings::params][strings::connection_key].asUInt());
if (!app) {
LOG4CXX_ERROR(logger_, "NULL pointer");
@@ -64,97 +68,91 @@ void CreateInteractionChoiceSetRequest::Run() {
return;
}
for (uint32_t i = 0;
- i < (*message_)[strings::msg_params][strings::choice_set].length();
- ++i) {
- mobile_apis::Result::eType verification_result_image =
- mobile_apis::Result::SUCCESS;
- mobile_apis::Result::eType verification_result_secondary_image =
- mobile_apis::Result::SUCCESS;
+ i < (*message_)[strings::msg_params][strings::choice_set].length();
+ ++i) {
+ Result::eType verification_result_image = Result::SUCCESS;
+ Result::eType verification_result_secondary_image = Result::SUCCESS;
if ((*message_)[strings::msg_params]
- [strings::choice_set][i].keyExists(strings::image)) {
+ [strings::choice_set][i].keyExists(strings::image)) {
verification_result_image = MessageHelper::VerifyImage(
- (*message_)[strings::msg_params][strings::choice_set]
- [i][strings::image], app);
+ (*message_)[strings::msg_params][strings::choice_set]
+ [i][strings::image], app);
}
if ((*message_)[strings::msg_params]
- [strings::choice_set][i].keyExists(strings::secondary_image)) {
+ [strings::choice_set][i].keyExists(strings::secondary_image)) {
verification_result_secondary_image = MessageHelper::VerifyImage(
- (*message_)[strings::msg_params][strings::choice_set]
- [i][strings::secondary_image], app);
+ (*message_)[strings::msg_params][strings::choice_set]
+ [i][strings::secondary_image], app);
}
- if (verification_result_image == mobile_apis::Result::INVALID_DATA ||
- verification_result_secondary_image == mobile_apis::Result::INVALID_DATA) {
+ if (verification_result_image == Result::INVALID_DATA ||
+ verification_result_secondary_image == Result::INVALID_DATA) {
LOG4CXX_ERROR(logger_, "VerifyImage INVALID_DATA!");
- SendResponse(false, mobile_apis::Result::INVALID_DATA);
+ SendResponse(false, Result::INVALID_DATA);
return;
}
}
- const int32_t choice_set_id = (*message_)[strings::msg_params]
- [strings::interaction_choice_set_id].asInt();
+ choice_set_id_ = (*message_)[strings::msg_params]
+ [strings::interaction_choice_set_id].asInt();
- if (app->FindChoiceSet(choice_set_id)) {
+ if (app->FindChoiceSet(choice_set_id_)) {
LOG4CXX_ERROR(logger_, "Invalid ID");
- SendResponse(false, mobile_apis::Result::INVALID_ID);
+ SendResponse(false, Result::INVALID_ID);
return;
}
- mobile_apis::Result::eType result = CheckChoiceSet(app);
- if (mobile_apis::Result::SUCCESS != result) {
+ Result::eType result = CheckChoiceSet(app);
+ if (Result::SUCCESS != result) {
SendResponse(false, result);
return;
}
uint32_t grammar_id = ApplicationManagerImpl::instance()->GenerateGrammarID();
(*message_)[strings::msg_params][strings::grammar_id] = grammar_id;
- app->AddChoiceSet(choice_set_id, (*message_)[strings::msg_params]);
- SendVRAddCommandRequest(app);
- SendResponse(true, mobile_apis::Result::SUCCESS);
- app->UpdateHash();
+ app->AddChoiceSet(choice_set_id_, (*message_)[strings::msg_params]);
+ SendVRAddCommandRequests(app);
}
mobile_apis::Result::eType CreateInteractionChoiceSetRequest::CheckChoiceSet(
- ApplicationConstSharedPtr app) {
- LOG4CXX_INFO(logger_, "CreateInteractionChoiceSetRequest::CheckChoiceSet");
+ ApplicationConstSharedPtr app) {
+ LOG4CXX_AUTO_TRACE(logger_);
const smart_objects::SmartArray* new_choice_set_array =
(*message_)[strings::msg_params][strings::choice_set].asArray();
smart_objects::SmartArray::const_iterator it_array =
- new_choice_set_array->begin();
+ new_choice_set_array->begin();
smart_objects::SmartArray::const_iterator it_array_end =
- new_choice_set_array->end();
+ new_choice_set_array->end();
// Self check of new choice set for params coincidence
for (; it_array != it_array_end; ++it_array) {
const smart_objects::SmartArray* vr_array =
- (*it_array)[strings::vr_commands].asArray();
+ (*it_array)[strings::vr_commands].asArray();
CoincidencePredicateChoiceID c((*it_array)[strings::choice_id].asInt());
if (1 != std::count_if(
- new_choice_set_array->begin(),
- new_choice_set_array->end(),
- c)) {
-
+ new_choice_set_array->begin(),
+ new_choice_set_array->end(), c)) {
LOG4CXX_ERROR(logger_, "Incoming choice set has duplicate IDs.");
return mobile_apis::Result::INVALID_ID;
}
// Check new choice set params along with already registered choice sets
- const ChoiceSetMap& app_choice_set_map = app->choice_set_map();
+ const DataAccessor<ChoiceSetMap> accessor = app->choice_set_map();
+ const ChoiceSetMap& app_choice_set_map = accessor.GetData();
ChoiceSetMap::const_iterator it = app_choice_set_map.begin();
ChoiceSetMap::const_iterator itEnd = app_choice_set_map.end();
for (; it != itEnd; ++it) {
const smart_objects::SmartObject* app_choice_set = it->second;
if (NULL != app_choice_set) {
-
const smart_objects::SmartArray* curr_choice_set =
- (*app_choice_set)[strings::choice_set].asArray();
+ (*app_choice_set)[strings::choice_set].asArray();
if (0 != std::count_if(
- curr_choice_set->begin(),
- curr_choice_set->end(),
- c)) {
+ curr_choice_set->begin(),
+ curr_choice_set->end(),
+ c)) {
LOG4CXX_ERROR(logger_, "Incoming choice ID already exists.");
return mobile_apis::Result::INVALID_ID;
}
@@ -163,10 +161,9 @@ mobile_apis::Result::eType CreateInteractionChoiceSetRequest::CheckChoiceSet(
CoincidencePredicateMenuName m((*it_array)[strings::menu_name].asString());
if (1 != std::count_if(
- new_choice_set_array->begin(),
- new_choice_set_array->end(),
- m)) {
-
+ new_choice_set_array->begin(),
+ new_choice_set_array->end(),
+ m)) {
LOG4CXX_ERROR(logger_, "Incoming choice set has duplicate menu names.");
return mobile_apis::Result::DUPLICATE_NAME;
}
@@ -179,7 +176,6 @@ mobile_apis::Result::eType CreateInteractionChoiceSetRequest::CheckChoiceSet(
for (; it_vr != it_vr_end; ++it_vr) {
CoincidencePredicateVRCommands v((*it_vr));
if (1 != std::count_if(vr_array->begin(), vr_array->end(), v)) {
-
LOG4CXX_ERROR(logger_,
"Incoming choice set has duplicate VR command(s)");
@@ -189,22 +185,19 @@ mobile_apis::Result::eType CreateInteractionChoiceSetRequest::CheckChoiceSet(
// Check along with VR commands in other choices in the new set
smart_objects::SmartArray::const_iterator it_same_array =
- new_choice_set_array->begin();
+ new_choice_set_array->begin();
smart_objects::SmartArray::const_iterator it_same_array_end =
- new_choice_set_array->end();
+ new_choice_set_array->end();
for (; it_same_array != it_same_array_end; ++it_same_array) {
-
// Skip check for itself
if ((*it_array)[strings::choice_id] ==
(*it_same_array)[strings::choice_id]) {
-
continue;
}
if (compareSynonyms((*it_array), (*it_same_array))) {
-
LOG4CXX_ERROR(logger_,
"Incoming choice set has duplicate VR command(s).");
@@ -223,14 +216,13 @@ mobile_apis::Result::eType CreateInteractionChoiceSetRequest::CheckChoiceSet(
}
bool CreateInteractionChoiceSetRequest::compareSynonyms(
- const NsSmartDeviceLink::NsSmartObjects::SmartObject& choice1,
- const NsSmartDeviceLink::NsSmartObjects::SmartObject& choice2) {
-
+ const NsSmartDeviceLink::NsSmartObjects::SmartObject& choice1,
+ const NsSmartDeviceLink::NsSmartObjects::SmartObject& choice2) {
smart_objects::SmartArray* vr_cmds_1 =
- choice1[strings::vr_commands].asArray();
+ choice1[strings::vr_commands].asArray();
DCHECK(vr_cmds_1 != NULL);
smart_objects::SmartArray* vr_cmds_2 =
- choice2[strings::vr_commands].asArray();
+ choice2[strings::vr_commands].asArray();
DCHECK(vr_cmds_2 != NULL);
smart_objects::SmartArray::iterator it;
@@ -249,15 +241,14 @@ bool CreateInteractionChoiceSetRequest::compareSynonyms(
}
bool CreateInteractionChoiceSetRequest::compareStr(
- const NsSmartDeviceLink::NsSmartObjects::SmartObject& str1,
- const NsSmartDeviceLink::NsSmartObjects::SmartObject& str2) {
-
+ const NsSmartDeviceLink::NsSmartObjects::SmartObject& str1,
+ const NsSmartDeviceLink::NsSmartObjects::SmartObject& str2) {
return 0 == strcasecmp(str1.asCharArray(), str2.asCharArray());
}
bool CreateInteractionChoiceSetRequest::IsWhiteSpaceExist(
- const smart_objects::SmartObject& choice_set) {
- LOG4CXX_INFO(logger_, "CreateInteractionChoiceSetRequest::IsWhiteSpaceExist");
+ const smart_objects::SmartObject& choice_set) {
+ LOG4CXX_AUTO_TRACE(logger_);
const char* str = NULL;
str = choice_set[strings::menu_name].asCharArray();
@@ -284,7 +275,7 @@ bool CreateInteractionChoiceSetRequest::IsWhiteSpaceExist(
if (choice_set.keyExists(strings::vr_commands)) {
const size_t len =
- choice_set[strings::vr_commands].length();
+ choice_set[strings::vr_commands].length();
for (size_t i = 0; i < len; ++i) {
str = choice_set[strings::vr_commands][i].asCharArray();
@@ -306,37 +297,175 @@ bool CreateInteractionChoiceSetRequest::IsWhiteSpaceExist(
if (choice_set.keyExists(strings::secondary_image)) {
str = choice_set[strings::secondary_image][strings::value].asCharArray();
if (!CheckSyntax(str)) {
- LOG4CXX_ERROR(logger_, "Invalid secondary_image value syntax check failed");
+ LOG4CXX_ERROR(logger_, "Invalid secondary_image value. "
+ "Syntax check failed");
return true;
}
}
return false;
}
-void CreateInteractionChoiceSetRequest::SendVRAddCommandRequest(
- application_manager::ApplicationSharedPtr const app) {
-
- smart_objects::SmartObject* choice_set = &(*message_)[strings::msg_params];
+void CreateInteractionChoiceSetRequest::SendVRAddCommandRequests(
+ application_manager::ApplicationSharedPtr const app) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ smart_objects::SmartObject& choice_set = (*message_)[strings::msg_params];
+ smart_objects::SmartObject msg_params = smart_objects::SmartObject(
+ smart_objects::SmartType_Map);
+ msg_params[strings::type] = hmi_apis::Common_VRCommandType::Choice;
+ msg_params[strings::app_id] = app->app_id();
+ msg_params[strings::grammar_id] = choice_set[strings::grammar_id];
+ const uint32_t choice_count = choice_set[strings::choice_set].length();
+ SetAllowedToTerminate(false);
+
+ expected_chs_count_ = choice_count;
+ size_t chs_num = 0;
+ for (; chs_num < choice_count; ++chs_num) {
+ {
+ sync_primitives::AutoLock error_lock(error_from_hmi_lock_);
+ if (error_from_hmi_) {
+ LOG4CXX_WARN(logger_, "Error from HMI received. Stop sending VRCommands");
+ break;
+ }
+ }
- for (size_t j = 0; j < (*choice_set)[strings::choice_set].length(); ++j) {
- smart_objects::SmartObject msg_params = smart_objects::SmartObject(
- smart_objects::SmartType_Map);
- msg_params[strings::app_id] = app->app_id();
msg_params[strings::cmd_id] =
- (*choice_set)[strings::choice_set][j][strings::choice_id];
+ choice_set[strings::choice_set][chs_num][strings::choice_id];
msg_params[strings::vr_commands] = smart_objects::SmartObject(
smart_objects::SmartType_Array);
msg_params[strings::vr_commands] =
- (*choice_set)[strings::choice_set][j][strings::vr_commands];
+ choice_set[strings::choice_set][chs_num][strings::vr_commands];
+
+ sync_primitives::AutoLock commands_lock(vr_commands_lock_);
+ const uint32_t vr_cmd_id = msg_params[strings::cmd_id].asUInt();
+ const uint32_t vr_corr_id =
+ SendHMIRequest(hmi_apis::FunctionID::VR_AddCommand, &msg_params, true);
+
+ VRCommandInfo vr_command(vr_cmd_id);
+ sent_commands_map_[vr_corr_id] = vr_command;
+ LOG4CXX_DEBUG(logger_, "VR_command sent corr_id "
+ << vr_corr_id << " cmd_id " << vr_corr_id);
+ }
+ expected_chs_count_ = chs_num;
+ LOG4CXX_DEBUG(logger_, "expected_chs_count_ = " << expected_chs_count_);
+}
+
+void CreateInteractionChoiceSetRequest::on_event(
+ const event_engine::Event& event) {
+ using namespace hmi_apis;
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ const smart_objects::SmartObject& message = event.smart_object();
+ if (event.id() == hmi_apis::FunctionID::VR_AddCommand) {
+ received_chs_count_++;
+ LOG4CXX_DEBUG(logger_, "Got VR.AddCommand response, there are "
+ << expected_chs_count_ - received_chs_count_
+ << " more to wait.");
+
+ uint32_t corr_id = static_cast<uint32_t>(message[strings::params]
+ [strings::correlation_id].asUInt());
+ SentCommandsMap::iterator it = sent_commands_map_.find(corr_id);
+ if (sent_commands_map_.end() == it) {
+ LOG4CXX_WARN(logger_, "HMI response for unknown VR command received");
+ return;
+ }
+
+ Common_Result::eType vr_result_ = static_cast<Common_Result::eType>(
+ message[strings::params][hmi_response::code].asInt());
+ if (Common_Result::SUCCESS == vr_result_) {
+ VRCommandInfo& vr_command = it->second;
+ vr_command.succesful_response_received_ = true;
+ } else {
+ LOG4CXX_DEBUG(logger_, "Hmi response is not Success: " << vr_result_
+ << ". Stop sending VRAddCommand requests");
+ sync_primitives::AutoLock error_lock(error_from_hmi_lock_);
+ if (!error_from_hmi_) {
+ error_from_hmi_ = true;
+ SendResponse(false, GetMobileResultCode(vr_result_));
+ }
+ }
+
+ // update request timeout for case we send many VR add command requests
+ // and HMI has no time to send responses for all of them
+ LOG4CXX_DEBUG(logger_, "expected_chs_count_ = " << expected_chs_count_
+ << "received_chs_count_ = " << received_chs_count_);
+ if (received_chs_count_ < expected_chs_count_) {
+ sync_primitives::AutoLock timeout_lock_(is_timed_out_lock_);
+ if (!is_timed_out_) {
+ ApplicationManagerImpl::instance()->updateRequestTimeout(
+ connection_key(), correlation_id(), default_timeout());
+ }
+ } else {
+ OnAllHMIResponsesReceived();
+ }
+ }
+}
- msg_params[strings::type] = hmi_apis::Common_VRCommandType::Choice;
- msg_params[strings::grammar_id] = (*choice_set)[strings::grammar_id];
+void CreateInteractionChoiceSetRequest::onTimeOut() {
+ LOG4CXX_AUTO_TRACE(logger_);
- SendHMIRequest(hmi_apis::FunctionID::VR_AddCommand, &msg_params);
+ sync_primitives::AutoLock error_lock(error_from_hmi_lock_);
+ if (!error_from_hmi_) {
+ SendResponse(false, mobile_apis::Result::GENERIC_ERROR);
}
+ // We have to keep request alive until receive all responses from HMI
+ // according to SDLAQ-CRS-2976
+ sync_primitives::AutoLock timeout_lock_(is_timed_out_lock_);
+ is_timed_out_ = true;
+ ApplicationManagerImpl::instance()->updateRequestTimeout(
+ connection_key(), correlation_id(), 0);
}
+void CreateInteractionChoiceSetRequest::DeleteChoices() {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ ApplicationSharedPtr application =
+ ApplicationManagerImpl::instance()->application(connection_key());
+ if (!application) {
+ LOG4CXX_ERROR(logger_, "NULL pointer");
+ return;
+ }
+ application->RemoveChoiceSet(choice_set_id_);
+
+ smart_objects::SmartObject msg_param(smart_objects::SmartType_Map);
+ msg_param[strings::app_id] = application->app_id();
+
+ sync_primitives::AutoLock commands_lock(vr_commands_lock_);
+ SentCommandsMap::const_iterator it = sent_commands_map_.begin();
+ for (; it != sent_commands_map_.end(); ++it) {
+ const VRCommandInfo& vr_command_info = it->second;
+ if (vr_command_info.succesful_response_received_) {
+ msg_param[strings::cmd_id] = vr_command_info.cmd_id_;
+ SendHMIRequest(hmi_apis::FunctionID::VR_DeleteCommand, &msg_param);
+ } else {
+ LOG4CXX_WARN(
+ logger_, "Succesfull response has not been received for cmd_id = "
+ << vr_command_info.cmd_id_);
+ }
+ }
+ sent_commands_map_.clear();
+}
+
+void CreateInteractionChoiceSetRequest::OnAllHMIResponsesReceived() {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ if (!error_from_hmi_) {
+ SendResponse(true, mobile_apis::Result::SUCCESS);
+
+ ApplicationSharedPtr application =
+ ApplicationManagerImpl::instance()->application(connection_key());
+ if (!application) {
+ LOG4CXX_ERROR(logger_, "NULL pointer");
+ return;
+ }
+ application->UpdateHash();
+ } else {
+ DeleteChoices();
+ }
+ ApplicationManagerImpl::instance()->TerminateRequest(connection_key(),
+ correlation_id());
+}
} // namespace commands